一些 Image/GD 问题:裁剪、设置颜色和透明度
A number of Image/GD Problems: cropping, setting color and transparency
我写了一些 PHP 在 Ubuntu 机器(PHP 5.5.9)上使用 GD 的代码,然后将它转移到亚马逊的 Amazon EC2 Linux (PHP 5.5.31) 并且我从同一输入数据文件的代码中得到完全不同的结果(我只使用 imagecreatefromstring()
;$data
包含一个JPEG 文件。)
- 在我换机器之前,它会将白色变为透明。它不再进行该更改。
- 它曾经完美地裁剪图形。现在它在左侧留下一点白色,并在右侧稍微切断图像。
- 左侧有一条细黑线。
- 我什至无法用
imagecolorset()
使图像改变颜色。
代码如下:
if ($isFileString) {
$src2 = imagecreatefromstring($data);
} else {
$src2 = imagecreatefromjpeg($data);
}
// This was an attempt to get it to recognize transparent.
if (!unlink ("../drive/sigs/tmp.png"))
die("Failed to delete tmp.png");
imagepng($src2, "../drive/sigs/tmp.png");
imagedestroy($src2);
$src = imagecreatefrompng("../drive/sigs/tmp.png");
imagealphablending($src, false);
imagesavealpha($src, true);
for ($i=0; $i< 1024; $i++) {
echo $i;
echo print_r(imagecolorsforindex($src, $i));
imagecolorset($src, $i, 255, 255, 255,255);
echo print_r(imagecolorsforindex($src, $i));
echo "<BR>";
}
$src = imagecropauto($src, IMG_CROP_WHITE);
$white = imagecolorallocate($src, 255, 255, 255);
imagecolortransparent($src, $white);
$src = imagerotate($src, -90, 0);
编辑
作为我无法让 imagecolorset()
对文件进行更改的示例,下面是 $i
:
循环的输出
1Array ( [red] => 0 [green] => 0 [blue] => 1 [alpha] => 0 ) 1Array ( [red] => 0 [green] => 0 [blue] => 1 [alpha] => 0 ) 1
2Array ( [red] => 0 [green] => 0 [blue] => 2 [alpha] => 0 ) 1Array ( [red] => 0 [green] => 0 [blue] => 2 [alpha] => 0 ) 1
3Array ( [red] => 0 [green] => 0 [blue] => 3 [alpha] => 0 ) 1Array ( [red] => 0 [green] => 0 [blue] => 3 [alpha] => 0 ) 1
EDIT2
更多信息:我检查了 gd 版本 (php -i | grep -i gd
)。我很惊讶地看到带有 GD 版本 2.1.1-dev 的 Ubuntu 框和带有 "bundled (2.1.0 compatible)" 的 EC2 框。我是 GD 的新手,所以我更倾向于认为这是我的错,而不是亚马逊提供了错误版本的 GD。
EDIT3
看来不是内存问题。 memory_get_peak_usage()
报告大约 35MB。
gd_info()
报告的唯一区别是版本号。
那个版本的GD好像有问题。它并不完美,但这是我们确定的最终代码:
if ($isFileString) {
$im1 = imagecreatefromstring($data);
} else {
$im1 = imagecreatefromjpeg($data);
}
$tmp_file = $this->tmp_dir . md5(time() . mt_rand());
imagepng($im1, $tmp_file);
imagedestroy($im1);
// rotate, pre-resize and resample the source image
$im2 = imagecreatefrompng($tmp_file);
unlink($tmp_file);
if (imagesy($im2) > imagesx($im2))
$im2 = imagerotate($im2, $this->rotate, 0);
$width = imagesx($im2);
$height = imagesy($im2);
$percent = ($this->standard_width * 2) / $width;
$newWidth = $width * $percent;
$newHeight = $height * $percent;
$im = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($im, $im2, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
// create a transparent image with a size like $im image
$im3 = imagecreatetruecolor($newWidth, $newHeight);
imagesavealpha($im3, TRUE);
imagefill($im3, 0, 0, imagecolorallocatealpha($im3, 0, 0, 0, 127));
// find non-white-ish pixels on $im and copy them to $dst
$sizeX = $newWidth;
$sizeY = $newHeight;
$startX = $startY = 100000;
$finishX = $finishY = 0;
for ($x = 1; $x < $sizeX - 1; $x++) {
for ($y = 1; $y < $sizeY - 1; $y++) {
$rgb = imagecolorat($im, $x, $y);
$colors = imagecolorsforindex($im, $rgb);
$r = $colors['red'];
$g = $colors['green'];
$b = $colors['blue'];
if ($r < $this->redLimit && $g < $this->greenLimit && $b < $this->blueLimit) {
imagesetpixel($im3, $x, $y, $rgb);
if ($startX > $x) {
$startX = $x;
}
if ($startY > $y) {
$startY = $y;
}
if ($finishX < $x)
$finishX = $x;
if ($finishY < $y)
$finishY = $y;
}
}
}
// final resize
$width = $finishX - $startX + 1;
$height = $finishY - $startY + 1;
$percent = $this->standard_width / $width;
$newWidth = $width * $percent;
$newHeight = $height * $percent;
$im4 = imagecreatetruecolor($newWidth, $newHeight);
imagesavealpha($im4, TRUE);
imagefill($im4, 0, 0, imagecolorallocatealpha($im4, 0, 0, 0, 127));
imagecopyresampled($im4, $im3, 0, 0, $startX, $startY, $newWidth, $newHeight, $width, $height);
// returning image
ob_start();
imagepng($im4);
$image_data = ob_get_contents();
ob_end_clean();
return $image_data;
我写了一些 PHP 在 Ubuntu 机器(PHP 5.5.9)上使用 GD 的代码,然后将它转移到亚马逊的 Amazon EC2 Linux (PHP 5.5.31) 并且我从同一输入数据文件的代码中得到完全不同的结果(我只使用 imagecreatefromstring()
;$data
包含一个JPEG 文件。)
- 在我换机器之前,它会将白色变为透明。它不再进行该更改。
- 它曾经完美地裁剪图形。现在它在左侧留下一点白色,并在右侧稍微切断图像。
- 左侧有一条细黑线。
- 我什至无法用
imagecolorset()
使图像改变颜色。
代码如下:
if ($isFileString) {
$src2 = imagecreatefromstring($data);
} else {
$src2 = imagecreatefromjpeg($data);
}
// This was an attempt to get it to recognize transparent.
if (!unlink ("../drive/sigs/tmp.png"))
die("Failed to delete tmp.png");
imagepng($src2, "../drive/sigs/tmp.png");
imagedestroy($src2);
$src = imagecreatefrompng("../drive/sigs/tmp.png");
imagealphablending($src, false);
imagesavealpha($src, true);
for ($i=0; $i< 1024; $i++) {
echo $i;
echo print_r(imagecolorsforindex($src, $i));
imagecolorset($src, $i, 255, 255, 255,255);
echo print_r(imagecolorsforindex($src, $i));
echo "<BR>";
}
$src = imagecropauto($src, IMG_CROP_WHITE);
$white = imagecolorallocate($src, 255, 255, 255);
imagecolortransparent($src, $white);
$src = imagerotate($src, -90, 0);
编辑
作为我无法让 imagecolorset()
对文件进行更改的示例,下面是 $i
:
1Array ( [red] => 0 [green] => 0 [blue] => 1 [alpha] => 0 ) 1Array ( [red] => 0 [green] => 0 [blue] => 1 [alpha] => 0 ) 1
2Array ( [red] => 0 [green] => 0 [blue] => 2 [alpha] => 0 ) 1Array ( [red] => 0 [green] => 0 [blue] => 2 [alpha] => 0 ) 1
3Array ( [red] => 0 [green] => 0 [blue] => 3 [alpha] => 0 ) 1Array ( [red] => 0 [green] => 0 [blue] => 3 [alpha] => 0 ) 1
EDIT2
更多信息:我检查了 gd 版本 (php -i | grep -i gd
)。我很惊讶地看到带有 GD 版本 2.1.1-dev 的 Ubuntu 框和带有 "bundled (2.1.0 compatible)" 的 EC2 框。我是 GD 的新手,所以我更倾向于认为这是我的错,而不是亚马逊提供了错误版本的 GD。
EDIT3
看来不是内存问题。
memory_get_peak_usage()
报告大约 35MB。gd_info()
报告的唯一区别是版本号。
那个版本的GD好像有问题。它并不完美,但这是我们确定的最终代码:
if ($isFileString) {
$im1 = imagecreatefromstring($data);
} else {
$im1 = imagecreatefromjpeg($data);
}
$tmp_file = $this->tmp_dir . md5(time() . mt_rand());
imagepng($im1, $tmp_file);
imagedestroy($im1);
// rotate, pre-resize and resample the source image
$im2 = imagecreatefrompng($tmp_file);
unlink($tmp_file);
if (imagesy($im2) > imagesx($im2))
$im2 = imagerotate($im2, $this->rotate, 0);
$width = imagesx($im2);
$height = imagesy($im2);
$percent = ($this->standard_width * 2) / $width;
$newWidth = $width * $percent;
$newHeight = $height * $percent;
$im = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($im, $im2, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
// create a transparent image with a size like $im image
$im3 = imagecreatetruecolor($newWidth, $newHeight);
imagesavealpha($im3, TRUE);
imagefill($im3, 0, 0, imagecolorallocatealpha($im3, 0, 0, 0, 127));
// find non-white-ish pixels on $im and copy them to $dst
$sizeX = $newWidth;
$sizeY = $newHeight;
$startX = $startY = 100000;
$finishX = $finishY = 0;
for ($x = 1; $x < $sizeX - 1; $x++) {
for ($y = 1; $y < $sizeY - 1; $y++) {
$rgb = imagecolorat($im, $x, $y);
$colors = imagecolorsforindex($im, $rgb);
$r = $colors['red'];
$g = $colors['green'];
$b = $colors['blue'];
if ($r < $this->redLimit && $g < $this->greenLimit && $b < $this->blueLimit) {
imagesetpixel($im3, $x, $y, $rgb);
if ($startX > $x) {
$startX = $x;
}
if ($startY > $y) {
$startY = $y;
}
if ($finishX < $x)
$finishX = $x;
if ($finishY < $y)
$finishY = $y;
}
}
}
// final resize
$width = $finishX - $startX + 1;
$height = $finishY - $startY + 1;
$percent = $this->standard_width / $width;
$newWidth = $width * $percent;
$newHeight = $height * $percent;
$im4 = imagecreatetruecolor($newWidth, $newHeight);
imagesavealpha($im4, TRUE);
imagefill($im4, 0, 0, imagecolorallocatealpha($im4, 0, 0, 0, 127));
imagecopyresampled($im4, $im3, 0, 0, $startX, $startY, $newWidth, $newHeight, $width, $height);
// returning image
ob_start();
imagepng($im4);
$image_data = ob_get_contents();
ob_end_clean();
return $image_data;