在PHP中从图像中裁剪空白
是否有可能删除PHP中的图像周围的空白?
注:澄清我的意思是像photoshops修剪function。
谢谢。
要调整所有的空格,就像你所说的那样,在图像的有趣部分周围,首先我们找出“空白”停止的位置,然后我们复制这些边界内的所有内容。
//load the image $img = imagecreatefromjpeg("http://ecx.images-amazon.comhttp://img.dovov.comI/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);
我的老例子,假设在图像的各个方面有相同的“边界”,只是为了澄清评论:)
//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的脚本冗余地调用了imagesx和imagesy。 它也会遍历每一个像素,即使在angular落重叠的时候。 这个改进的版本消除了多余的函数调用,并且只检查一次像素,从而显着提高速度。 如果每个像素是修剪的,则该函数返回等于2的状态($ result ['#'])。
example(); function example(){ $img = imagecreatefromjpeg("http://ecx.images-amazon.comhttp://img.dovov.comI/413XvF0yukL._SL500_AA280_.jpg"); // find the trimmed image border $box = imageTrimBox($img); // copy cropped portion $img2 = imagecreate($box['w'], $box['h']); imagecopy($img2, $img, 0, 0, $box['l'], $box['t'], $box['w'], $box['h']); // output cropped image to the browser header('Content-Type: image/png'); imagepng($img2); imagedestroy($img); imagedestroy($img2); } function imageTrimBox($img, $hex=null){ if (!ctype_xdigit($hex)) $hex = imagecolorat($img, 0,0); $b_top = $b_lft = 0; $b_rt = $w1 = $w2 = imagesx($img); $b_btm = $h1 = $h2 = imagesy($img); do { //top for(; $b_top < $h1; ++$b_top) { for($x = 0; $x < $w1; ++$x) { if(imagecolorat($img, $x, $b_top) != $hex) { break 2; } } } // stop if all pixels are trimmed if ($b_top == $b_btm) { $b_top = 0; $code = 2; break 1; } // bottom for(; $b_btm >= 0; --$b_btm) { for($x = 0; $x < $w1; ++$x) { if(imagecolorat($img, $x, $b_btm-1) != $hex) { break 2; } } } // left for(; $b_lft < $w1; ++$b_lft) { for($y = $b_top; $y <= $b_btm; ++$y) { if(imagecolorat($img, $b_lft, $y) != $hex) { break 2; } } } // right for(; $b_rt >= 0; --$b_rt) { for($y = $b_top; $y <= $b_btm; ++$y) { if(imagecolorat($img, $b_rt-1, $y) != $hex) { break 2; } } } $w2 = $b_rt - $b_lft; $h2 = $b_btm - $b_top; $code = ($w2 < $w1 || $h2 < $h1) ? 1 : 0; } while (0); // result codes: // 0 = Trim Zero Pixels // 1 = Trim Some Pixels // 2 = Trim All Pixels return array( '#' => $code, // result code 'l' => $b_lft, // left 't' => $b_top, // top 'r' => $b_rt, // right 'b' => $b_btm, // bottom 'w' => $w2, // new width 'h' => $h2, // new height 'w1' => $w1, // original width 'h1' => $h1, // original height ); }
我知道这是相当古老的,但如果您启用ImageMagick您可以使用此方法
修剪图像
查看PHP中的ImageMagick库。 它有处理和操作图像(包括裁剪 )的好方法。
你必须弄清楚图像周围的“空白”在哪里。 这可能是具有挑战性的,因为“空白”可能是白色,其他颜色,透明度等等。
我意识到这是相当古老,但我有一个稍微不同的采取通过GD修剪图像。 而不是一次只做一个方面 – 做所有四个。 在某些方面它更快,更便宜。 但是,如果您停止FOR循环,则会发现上下左右两侧 – 比这更快。
所以首先是:
# # Do all four sides at once # echo "Finding the top-left-bottom-right edges of the image...please wait.\n"; $top = 99999; $bot = -99999; $left = 99999; $right = -99999; for( $x=$offset; $x<($w-$offset); $x++ ){ for( $y=$offset; $y<($h-$offset); $y++ ){ $rgb = imagecolorat( $gd, $x, $y ); if( $color != $rgb ){ $left = ($x < $left) ? $x : $left; $right = ($x > $right) ? $x : $right; $top = ($y < $top) ? $y : $top; $bot = ($y > $bot) ? $y : $bot; } } }
然后是:
# # Top # echo "Finding the top of the image\n"; $top = null; for( $y=$offset; $y<($h-$offset); $y++ ){ for( $x=$offset; $x<($w-$offset); $x++ ){ $rgb = imagecolorat( $gd, $x, $y ); if( $color != $rgb ){ $top = $y; break; } } if( !is_null($top) ){ break; } } # # Bottom # echo "Finding the bottom of the image\n"; $bot = null; for( $y=($h-$offset); $y>$offset; $y-- ){ for( $x=$offset; $x<($w-$offset); $x++ ){ $rgb = imagecolorat( $gd, $x, $y ); if( $color != $rgb ){ $bot = $y; break; } } if( !is_null($bot) ){ break; } } # # Left # echo "Finding the left of the image\n"; $left = null; for( $x=$offset; $x<($w-$offset); $x++ ){ for( $y=$offset; $y<($h-$offset); $y++ ){ $rgb = imagecolorat( $gd, $x, $y ); if( $color != $rgb ){ $left = $x; break; } } if( !is_null($left) ){ break; } } # # right # echo "Finding the right of the image\n"; $right = null; for( $x=($w-$offset); $x>$offset; $x-- ){ for( $y=$offset; $y<($h-$offset); $y++ ){ $rgb = imagecolorat( $gd, $x, $y ); if( $color != $rgb ){ $right = $x; break; } } if( !is_null($right) ){ break; } }
在这两种情况下,$ colorvariables都包含图像中的第一个颜色点:
$color = imagecolorat( $gd, 0, 0 );
这是因为在GIF图像中 – 第一个点是透明(或背景)颜色的99%。 此外,$偏移是(对我来说)一种方式来说,我知道图像只会是如此宽,如此之高。 所以,如果我画的东西只有最大256乘256,但我把它放在一个1024 x 1024的背景,我可以砍掉一些背景,并作出了255的偏移量,从而使FOR循环只能从255到1024 -255)或769。
好的 – 在别人问之前 – 为什么我会做这样的事情 – 因为有些字体(如Bastarda)没有正确的字体信息,字母“z”的256pt输出会产生一个图像, z“超过了256(下降到512),所以为了得到整个图像,你必须开始(或结束)比你想象的字体更远的地方。 所以我分开了差异,并从任何一端剔除了255个像素。 这是在看到Bastarda做到这一点之后。
一些附加说明:
1.您可以将PNG图像设置为像GIF图像,但通常您必须指定背景颜色。
2. JPEG图像每次都不会以完全相同的方式解压缩。 所以,即使比较两次加载的图像可能也不一样,可能会给出不同的大小。
3.这些例程最适合简单的黑白(或两色)图像。 多种颜色可以抛出这些例程。 特别是如果你决定使用公差。
4.要使用公差来确定是否find了图像的边缘,您只需预先计算高差和低差(即:如果红色分量上的公差为5(5) ,那么你可以计算公差为X-5-to-x + 5或者x-2.5-to-x + 2.5,这取决于你希望公差是整个范围还是只是+/-范围)。 您可以对颜色的RED,GREEN,BLUE和ALPHA部分或整个颜色本身有一个容差。 因此,如果您需要,您可以计算出几种不同的公差,并且根据您的需要,所有公差都是正确的。
PHP的gd库有imagecropauto
function:
<?php $img=imagecreatefrompng("tux.png"); // Load and instantiate the image if($img) { $cropped=imagecropauto($img,IMG_CROP_DEFAULT); // Auto-crop the image imagedestroy($img); // Clean up as $img is no longer needed header("Content-type: image/png"); // Set the appropriate header so the browser // knows how to present it imagepng($cropped); // Return the newly cropped image }
默认情况下, imagecropauto
将尝试使用透明度进行裁剪,然后使用图像的四个angular落尝试检测裁剪的背景; 在上面的例子中,我也用下面的常量代替了IMG_CROP_AUTO
:
-
IMG_CROP_BLACK
– 用于黑色背景的图像 -
IMG_CROP_WHITE
– 用于白色背景的图像 -
IMG_CROP_THRESHOLD
– 允许您设置裁剪时使用的颜色和阈值
imagecropauto
已经包含在PHP从5.5版本,更多的信息在这里看imagecropauto
的PHP文档 。