简体   繁体   中英

Crop non transparent pixels from a transperent 16x16 image using PHP

I would like to crop the non-transparent pixels from a transparent 16x16 canvas. Since the non transparent pixels is actually an image. Is it possible in PHP GD or Imagick?

Since the image is so small, you could probable loop through all the pixels with imagecolorat and then write the ones that aren't transparent to a new image with imagesetpixel or make note of the corners and copy the whole thing with imagecopy

Something like:

$x1 = -1;
$y1 = -1;
for($x=0;$x<16;$x++){
    for($y=0;$y<16;$y++){
        if (!transparent(imagecolorat($im, $x, $y))){
            if($x1 < 0 ){
                $x1 = $x;
                $y1 = $y;
            }else{
                $x2 = $x;
                $y2 = $y;       
            }
        }
    }
}
imagecopy($im2, $im, 0, 0, $x1, $y1, $x2-$x1+1, $y2-$y1+1); 

You will have to define the function transparent() - either do a bit shift to get the alpha channel or identify what the transparent color is if it's a gif.

Edit: Height/Width math updated

image magick has a trim method http://www.php.net/manual/en/imagick.trimimage.php I think that's what you need

<?php
/* Create the object and read the image in */
$im = new Imagick("image.jpg");

/* Trim the image. */
$im->trimImage(0);

/* Ouput the image */
header("Content-Type: image/" . $im->getImageFormat());
echo $im;
?>

Just spent ages fiddling with this and it's now the early hours!!

I couldn't find a function/script anywhere that only used GD so I hope this helps someone.

Essentially it loops through the rows and columns of the source image working out if the whole row/column is transparent, if it is it updates the $left, $right, $top and $bottom variables accordingly.

The only limitation I can think of is an image where there is a row or column that splits the image down the middle, at which point this would mark the $bottom or $right earlier than desired, but a nice start for anyone looking.

In my case the source image was a gd resource, and there is need of some imagedestroy() calls at the end....

function transparent($src_img,$in){
    $c = imagecolorsforindex($src_img,$in);
    if($c["alpha"] == 127){
        return true;
    }else{
        return false;
    }
    //var_dump($c);
}

function crop($src_img){

    $width = imagesx($src_img);
    $height = imagesy($src_img);

    $top = 0;
    $bottom = 0;
    $left = 0;
    $right = 0;

    for($x=0;$x<$width;$x++){
        $clear = true;
        for($y=0;$y<$height;$y++){
            if ($this->transparent($src_img,imagecolorat($src_img, $x, $y))){

            }else{
                $clear = false;
            }
        }
        if($clear===false){
            if($left == 0){
                $left = ($x-1);
            }
        }
        if(($clear===true)and($left != 0)){
            if($right == 0){
                $right = ($x-1);
            }else{
                break;
            }
        }
    }

    for($y=0;$y<$height;$y++){
        $clear = true;
        for($x=0;$x<$width;$x++){
            if ($this->transparent($src_img,imagecolorat($src_img, $x, $y))){

            }else{
                $clear = false;
            }
        }
        if($clear===false){
            if($top == 0){
                $top = ($y-1);
            }
        }
        if(($clear===true)and($top != 0)){
            if($bottom == 0){
                $bottom = ($y-1);
            }else{
                break;
            }
        }
    }

    $new = imagecreatetruecolor($right-$left, $bottom-$top);
    $transparent = imagecolorallocatealpha($new,255,255,255,127);
    imagefill($new,0,0,$transparent);


    imagecopy($new, $src_img, 0, 0, $left, $top, $right-$left, $bottom-$top);
    return $new;

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM