是否可以删除PHP中图像周围的空白?
注意:澄清我的意思是像photoshops修剪功能。
感谢。
答案 0 :(得分:49)
要修剪所有空白,就像你所说的那样,围绕图像的有趣部分,首先我们找到“空白”停止的位置,然后我们复制这些边界内的所有内容。
//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);
我的旧例子,假设图像四周都有相同的“边框”,只是为了澄清评论:)
//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");
答案 1 :(得分:12)
Gnud的脚本冗余地调用imagesx和imagesy。它还迭代每一侧的每个像素,即使角落重叠。这个改进版本消除了冗余函数调用,并且只检查每个像素一次,从而显着提高了速度。如果每个像素都被修剪,该函数返回一个等于2的状态($ result ['#'])。
example();
function example(){
$img = imagecreatefromjpeg("http://ecx.images-amazon.com/images/I/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
);
}
答案 2 :(得分:6)
我知道这已经很老了,但如果你启用了ImageMagick,你可以使用这个方法
答案 3 :(得分:3)
PHP的gd库具有imagecropauto
函数(PHP版本5.5 +):
<?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
会尝试使用透明度进行裁剪,然后使用图像的4个角落尝试检测要裁剪的背景;在上面的示例中,我还使用以下常量代替IMG_CROP_AUTO
取得了成功:
IMG_CROP_BLACK
- 适用于黑色背景的图片IMG_CROP_WHITE
- 对于具有白色背景的图片很有用IMG_CROP_THRESHOLD
- 允许您设置裁剪时使用的颜色和阈值答案 4 :(得分:2)
我意识到这已经很老了,但我对通过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; }
}
在这两种情况下,$ color变量都包含图像中的第一个颜色点:
$color = imagecolorat( $gd, 0, 0 );
这是因为在GIF图像中 - 第一个点是透明(或背景)颜色的99%。另外,$ offset是(对我来说)一种说法,我知道图像只会如此宽,如此之高。因此,如果我绘制的东西最多只有256乘256但我把它放在1024 x 1024背景上我可以打破一些背景并使偏移量为255,从而使FOR循环仅从255变为(1024 -255)或769。
好的 - 在有人问之前 - 为什么我会做这样的事情 - 因为某些字体(如Bastarda)中没有正确的字体信息,而字母“z”的256pt输出会产生一个底部的图像“z”超过256(低至512),所以为了获得整个图像,你必须比你认为的字体更开始(或结束)。所以我分开差异并从任一端击落255像素。这是在实际看到Bastarda这样做之后。
一些补充说明:
1.您可以将PNG图像设置为像GIF图像,但通常您必须指定背景颜色。
2. JPEG图像每次都不会以完全相同的方式解压缩。因此,即使比较您加载两次的相同图像也可能无法正常工作,并且可能会有不同的尺寸
这些例程最适用于简单的黑白(或双色)图像。多种颜色可以抛弃这些例程。特别是如果你决定使用公差
4.要使用公差来确定是否找到了图像的边缘,您所要做的就是预先计算高公差和低公差(即:如果红色组件的公差为5(5) ,然后您可以将公差计算为XITH 5-to-x + 5 OR x-2.5-to-x + 2.5,具体取决于您是希望公差为整个范围还是仅+/-范围。您可以对颜色的RED,GREEN,BLUE和ALPHA部分或整个颜色本身进行容差。因此,如果您愿意,可以计算几种不同的公差,并且根据您的需要,所有这些公差都是正确的。
答案 5 :(得分:1)
在PHP中查看ImageMagick库。它有很好的处理和处理图像的方法(包括crop)。
你必须弄清楚图像周围的“空白”。这可能具有挑战性,因为“空白”可能是白色,其他颜色,透明度等......