使用 PHP 的 GDlib imagecopyresampled 时可以保留 PNG 图像透明度吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can PNG image transparency be preserved when using PHP's GDlib imagecopyresampled?
提问by Cheekysoft
The following PHP code snippet uses GD to resize a browser-uploaded PNG to 128x128. It works great, except that the transparent areas in the original image are being replaced with a solid color- black in my case.
以下 PHP 代码片段使用 GD 将浏览器上传的 PNG 大小调整为 128x128。它工作得很好,除了原始图像中的透明区域在我的情况下被替换为纯色 - 黑色。
Even though imagesavealphais set, something isn't quite right.
即使imagesavealpha设置了,也有些不对劲。
What's the best way to preserve the transparency in the resampled image?
在重新采样的图像中保留透明度的最佳方法是什么?
$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType )
= getimagesize( $uploadTempFile );
$srcImage = imagecreatefrompng( $uploadTempFile );
imagesavealpha( $targetImage, true );
$targetImage = imagecreatetruecolor( 128, 128 );
imagecopyresampled( $targetImage, $srcImage,
0, 0,
0, 0,
128, 128,
$uploadWidth, $uploadHeight );
imagepng( $targetImage, 'out.png', 9 );
回答by Cheekysoft
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );
did it for me. Thanks ceejayoz.
为我做的。谢谢ceejayoz。
note, the target image needs the alpha settings, not the source image.
请注意,目标图像需要 alpha 设置,而不是源图像。
Edit: full replacement code. See also answers below and their comments. This is not guaranteed to be be perfect in any way, but did achieve my needs at the time.
编辑:完整替换代码。另请参阅下面的答案及其评论。这不能保证在任何方面都是完美的,但确实满足了我当时的需求。
$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType )
= getimagesize( $uploadTempFile );
$srcImage = imagecreatefrompng( $uploadTempFile );
$targetImage = imagecreatetruecolor( 128, 128 );
imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );
imagecopyresampled( $targetImage, $srcImage,
0, 0,
0, 0,
128, 128,
$uploadWidth, $uploadHeight );
imagepng( $targetImage, 'out.png', 9 );
回答by Cheekysoft
Why do you make things so complicated? the following is what I use and so far it has done the job for me.
你为什么把事情弄得这么复杂?以下是我使用的,到目前为止它已经为我完成了这项工作。
$im = ImageCreateFromPNG($source);
$new_im = imagecreatetruecolor($new_size[0],$new_size[1]);
imagecolortransparent($new_im, imagecolorallocate($new_im, 0, 0, 0));
imagecopyresampled($new_im,$im,0,0,0,0,$new_size[0],$new_size[1],$size[0],$size[1]);
回答by ceejayoz
I believe this should do the trick:
我相信这应该可以解决问题:
$srcImage = imagecreatefrompng($uploadTempFile);
imagealphablending($srcImage, false);
imagesavealpha($srcImage, true);
edit:Someone in the PHP docs claims imagealphablendingshould be true, not false. YMMV.
编辑:PHP 文档中的某个人声称imagealphablending应该是正确的,而不是错误的。天啊。
回答by Jorrit Schippers
An addition that might help some people:
可能对某些人有所帮助的补充:
It is possible to toggle imagealphablending while building the image. I the specific case that I needed this, I wanted to combine some semi-transparent PNG's on a transparent background.
可以在构建图像时切换 imagealphablending。我需要这个的具体情况,我想在透明背景上组合一些半透明的 PNG。
First you set imagealphablending to false and fill the newly created true color image with a transparent color. If imagealphablending were true, nothing would happen because the transparent fill would merge with the black default background and result in black.
首先将 imagealphablending 设置为 false 并用透明色填充新创建的真彩色图像。如果 imagealphablending 为 true,则不会发生任何事情,因为透明填充将与黑色默认背景合并并导致黑色。
Then you toggle imagealphablending to true and add some PNG images to the canvas, leaving some of the background visible (ie. not filling up the entire image).
然后将 imagealphablending 切换为 true 并将一些 PNG 图像添加到画布,使一些背景可见(即不填满整个图像)。
The result is an image with a transparent background and several combined PNG images.
结果是一个带有透明背景的图像和几个组合的 PNG 图像。
回答by pricopz
I have made a function for resizing image like JPEG/GIF/PNG with copyimageresampleand PNG images still keep there transparency:
我已经制作了一个用于调整像 JPEG/GIF/PNG 这样的图像大小的函数,copyimageresample并且 PNG 图像仍然保持透明度:
$myfile=$_FILES["youimage"];
function ismyimage($myfile) {
if((($myfile["type"] == "image/gif") || ($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") || ($myfile["type"] == "image/png")) && ($myfile["size"] <= 2097152 /*2mb*/) ) return true;
else return false;
}
function upload_file($myfile) {
if(ismyimage($myfile)) {
$information=getimagesize($myfile["tmp_name"]);
$mywidth=$information[0];
$myheight=$information[1];
$newwidth=$mywidth;
$newheight=$myheight;
while(($newwidth > 600) || ($newheight > 400 )) {
$newwidth = $newwidth-ceil($newwidth/100);
$newheight = $newheight-ceil($newheight/100);
}
$files=$myfile["name"];
if($myfile["type"] == "image/gif") {
$tmp=imagecreatetruecolor($newwidth,$newheight);
$src=imagecreatefromgif($myfile["tmp_name"]);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
$con=imagegif($tmp, $files);
imagedestroy($tmp);
imagedestroy($src);
if($con){
return true;
} else {
return false;
}
} else if(($myfile["type"] == "image/jpg") || ($myfile["type"] == "image/jpeg") ) {
$tmp=imagecreatetruecolor($newwidth,$newheight);
$src=imagecreatefromjpeg($myfile["tmp_name"]);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
$con=imagejpeg($tmp, $files);
imagedestroy($tmp);
imagedestroy($src);
if($con) {
return true;
} else {
return false;
}
} else if($myfile["type"] == "image/png") {
$tmp=imagecreatetruecolor($newwidth,$newheight);
$src=imagecreatefrompng($myfile["tmp_name"]);
imagealphablending($tmp, false);
imagesavealpha($tmp,true);
$transparent = imagecolorallocatealpha($tmp, 255, 255, 255, 127);
imagefilledrectangle($tmp, 0, 0, $newwidth, $newheight, $transparent);
imagecopyresampled($tmp, $src, 0, 0, 0, 0, $newwidth, $newheight, $mywidth, $myheight);
$con=imagepng($tmp, $files);
imagedestroy($tmp);
imagedestroy($src);
if($con) {
return true;
} else {
return false;
}
}
} else
return false;
}
回答by Linus Unneb?ck
I suppose that this might do the trick:
我想这可能会奏效:
$uploadTempFile = $myField[ 'tmp_name' ]
list( $uploadWidth, $uploadHeight, $uploadType )
= getimagesize( $uploadTempFile );
$srcImage = imagecreatefrompng( $uploadTempFile );
$targetImage = imagecreatetruecolor( 128, 128 );
$transparent = imagecolorallocate($targetImage,0,255,0);
imagecolortransparent($targetImage,$transparent);
imagefilledrectangle($targetImage,0,0,127,127,$transparent);
imagecopyresampled( $targetImage, $srcImage,
0, 0,
0, 0,
128, 128,
$uploadWidth, $uploadHeight );
imagepng( $targetImage, 'out.png', 9 );
The downside is that the image will be stripped of every 100% green pixels. Anyhow, hope it helps :)
缺点是图像将每 100% 绿色像素被剥离一次。无论如何,希望它有帮助:)
回答by Kalle
Regrading the preserve transparency, then yes like stated in other posts imagesavealpha() have to be set to true, to use the alpha flag imagealphablending() must be set to false else it doesn't work.
重新分级保留透明度,然后就像其他帖子中所述一样,imagesavealpha() 必须设置为 true,要使用 alpha 标志 imagealphablending() 必须设置为 false,否则它不起作用。
Also I spotted two minor things in your code:
我还在你的代码中发现了两件小事:
- You don't need to call
getimagesize()to get the width/height forimagecopyresmapled() - The
$uploadWidthand$uploadHeightshould be-1the value, since the cordinates starts at0and not1, so it would copy them into an empty pixel. Replacing it with:imagesx($targetImage) - 1andimagesy($targetImage) - 1, relativily should do :)
- 你不需要打电话
getimagesize()来获取宽度/高度imagecopyresmapled() - 该
$uploadWidth和$uploadHeight应-1的值,因为cordinates开始于0而不是1,所以这将它们复制到一个空像素。用:imagesx($targetImage) - 1和替换它imagesy($targetImage) - 1,相对应该做:)
回答by Md. Imadul Islam
Here is my total test code. It works for me
这是我的总测试代码。这个对我有用
$imageFileType = pathinfo($_FILES["image"]["name"], PATHINFO_EXTENSION);
$filename = 'test.' . $imageFileType;
move_uploaded_file($_FILES["image"]["tmp_name"], $filename);
$source_image = imagecreatefromjpeg($filename);
$source_imagex = imagesx($source_image);
$source_imagey = imagesy($source_image);
$dest_imagex = 400;
$dest_imagey = 600;
$dest_image = imagecreatetruecolor($dest_imagex, $dest_imagey);
imagecopyresampled($dest_image, $source_image, 0, 0, 0, 0, $dest_imagex, $dest_imagey, $source_imagex, $source_imagey);
imagesavealpha($dest_image, true);
$trans_colour = imagecolorallocatealpha($dest_image, 0, 0, 0, 127);
imagefill($dest_image, 0, 0, $trans_colour);
imagepng($dest_image,"test1.png",1);
回答by tesla
Pay attention to the source image's widthand heightvalues which are passed to imagecopyresampledfunction. If they are bigger than actual source image size, the rest of image area will be filled with black color.
注意传递给函数的源图像width和height值imagecopyresampled。如果它们大于实际的源图像大小,则图像区域的其余部分将填充为黑色。
回答by Marco
I combined the answers from ceejayoz and Cheekysoft, which gave the best result for me. Without imagealphablending() and imagesavealpha() the image is not clear:
我结合了 ceejayoz 和 Cheekysoft 的答案,这给了我最好的结果。没有 imagealphablending() 和 imagesavealpha() 图像不清晰:
$img3 = imagecreatetruecolor(128, 128);
imagecolortransparent($img3, imagecolorallocate($img3, 0, 0, 0));
imagealphablending( $img3, false );
imagesavealpha( $img3, true );
imagecopyresampled($img3, $srcImage, 0, 0, 0, 0, 128, 128, $uploadWidth, $uploadHeight);
imagepng($img3, 'filename.png', 9);

