tags:

views:

830

answers:

3

Is it possible to remove the whitespace surrounding an image in PHP?

NOTE: to clarify I mean something like photoshops trim feature.

Thanks.

+1  A: 

Check out the ImageMagick library in PHP. It has good methods of working with and manipulating images (including crop).

You'll have to figure out where the "whitespace" is around the image. It could be challenging, since "whitespace" could be the color white, some other color, transparency, etc...

jheddings
+4  A: 

To trim all whitespace, as you call it, surrounding the interesting part of the image, first we find out where the "whitespace" stops, and then we copy everything inside of those borders.

//load the image
$img = imagecreatefromjpeg("http://ecx.images-amazon.com/images/I/413XvF0yukL._SL500_AA280_.jpg");

//find the size of the borders
$b_top = 0;
$b_btm = 0;
$b_lft = 0;
$b_rt = 0;

//top
for(; $b_top < imagesy($img); ++$b_top) {
  for($x = 0; $x < imagesx($img); ++$x) {
    if(imagecolorat($img, $x, $b_top) != 0xFFFFFF) {
       break 2; //out of the 'top' loop
    }
  }
}

//bottom
for(; $b_btm < imagesy($img); ++$b_btm) {
  for($x = 0; $x < imagesx($img); ++$x) {
    if(imagecolorat($img, $x, imagesy($img) - $b_btm-1) != 0xFFFFFF) {
       break 2; //out of the 'bottom' loop
    }
  }
}

//left
for(; $b_lft < imagesx($img); ++$b_lft) {
  for($y = 0; $y < imagesy($img); ++$y) {
    if(imagecolorat($img, $b_lft, $y) != 0xFFFFFF) {
       break 2; //out of the 'left' loop
    }
  }
}

//right
for(; $b_rt < imagesx($img); ++$b_rt) {
  for($y = 0; $y < imagesy($img); ++$y) {
    if(imagecolorat($img, imagesx($img) - $b_rt-1, $y) != 0xFFFFFF) {
       break 2; //out of the 'right' loop
    }
  }
}

//copy the contents, excluding the border
$newimg = imagecreatetruecolor(
    imagesx($img)-($b_lft+$b_rt), imagesy($img)-($b_top+$b_btm));

imagecopy($newimg, $img, 0, 0, $b_lft, $b_top, imagesx($newimg), imagesy($newimg));

//finally, output the image
header("Content-Type: image/jpeg");
imagejpeg($newimg);

My old example, that assumes an identical "border" on all sides of the image, just to clarify the comments :)

//load the image
$img = imagecreatefromjpeg("img.jpg");

//find the size of the border.
$border = 0;
while(imagecolorat($img, $border, $border) == 0xFFFFFF) {
  $border++;
}

//copy the contents, excluding the border
//This code assumes that the border is the same size on all sides of the image.
$newimg = imagecreatetruecolor(imagesx($img)-($border*2), imagesy($img)-($border*2));
imagecopy($newimg, $img, 0, 0, $border, $border, imagesx($newimg), imagesy($newimg));

//finally, if you want, overwrite the original image
imagejpeg($newimg, "img.jpg");
gnud
Nice example... As you point out (just to clarify), this assumes a fixed-size border of white all around the image.
jheddings
Hi, the border isn't a fixed size. I'm thinking of something like photoshops trim feature.
usertest
I just tried the code, it cuts off some of the image.
usertest
This code doesn't assume a fixed size of border (like, all borders are 14px), but it assumes that the border is the same size on all sides of the image. You can use this as a starting point, though. Remember that checking all pixels on all sides will get slow - don't do this every time you show the image, do it when the user uploads it the first time :)
gnud
@gnud: I see what your saying, you mean work out the white border on each side individually. Is the code above calculating the border from the top or left of the page?
usertest
Added a new example that might help - it's not tested at all, though. And I'm not sure how it deals with transparency. But you can perhaps figure that out on your own :)
gnud
All image coordinates in the GD library are 0,0 for top left. My original example (now the 2nd one) searches diagonally downwards towards the bottom right, looking for a non-white pixel.
gnud
Now it works perfectly for the top and left, but doesn't do anything for the bottom and right.
usertest
Like I said in my comment, I never tested any of this code. Start by fixing typos, and see where that gets you - if you provide an example image, I'll test it.
gnud
Thanks gnud, how about this one?http://ecx.images-amazon.com/images/I/413XvF0yukL._SL500_AA280_.jpg
usertest
OK, I've made two changes, and it works for me. Fixed one typo, and added a "-1" to the bottom and right indexes, because the index starts at 0, not 1.
gnud
Excellent thanks, very good code. And thanks again for all the help.
usertest
A: 

I know this is pretty old but if you have ImageMagick enabled you can use this method

Trim Image

Bill H