使用PHP的GDlib imagecopyresampled时,可以保留PNG图像透明度吗?

以下PHP代码段使用GD将浏览器上传的PNG调整为128×128。 它工作的很好,除了在我的情况下,原始图像中的透明区域被replace为纯色 – 黑色。

即使imagesavealpha设置,一些不太正确的。

在重采样图像中保留透明度的最佳方法是什么?

 $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 ); 
 imagealphablending( $targetImage, false ); imagesavealpha( $targetImage, true ); 

为我做了。 谢谢ceejayoz。

请注意,目标图像需要alpha设置,而不是源图像。

编辑:完整的replace代码。 请参阅下面的答案和他们的意见。 这不能保证在任何方面都是完美的,但在当时确实达到了我的需求。

 $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 ); 

你为什么把事情弄得这么复杂? 以下是我使用的,到目前为止,它已经完成了我的工作。

 $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]); 

我相信这应该做的伎俩:

 $srcImage = imagecreatefrompng($uploadTempFile); imagealphablending($srcImage, false); imagesavealpha($srcImage, true); 

编辑:在PHP文档中有人声称imagealphablending应该是真实的,而不是假的。 因人而异。

另外可能会帮助一些人:

构build图像时可以切换图像相似性。 我需要的具体情况是,我想在透明背景上合并一些半透明的PNG。

首先,将imagealphablending设置为false,并用透明颜色填充新创build的真彩色图像。 如果imagealphablending是真的,则不会发生任何事情,因为透明填充将与黑色的默认背景合并,并导致黑色。

然后,将imagealphablending切换为true,并将一些PNG图像添加到canvas上,从而留下一些可见的背景(即不填充整个图像)。

结果是具有透明背景的图像和几个组合的PNG图像。

我已经做了一个function,像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; } 

我想这可能会有诀窍:

 $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 ); 

不利的一面是图像将被剥离每100%绿色像素。 总之,希望它有助于:)

regrading保持透明度,然后是像其他职位说明imageavealpha()必须设置为true,要使用alpha标志imagealphablending()必须设置为false否则它不起作用。

我还发现你的代码中有两件小事:

  1. 您不需要调用getimagesize()来获取imagecopyresmapled()的宽度/高度
  2. $uploadWidth$uploadHeight应该是-1的值,因为坐标从0开始而不是1 ,所以它会将它们复制到一个空像素中。 replace它: imagesx($targetImage) - 1imagesy($targetImage) - 1 ,相对应该做:)

这是我的总testing代码。 它适用于我

 $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); 

注意传递给imagecopyresampled函数的源图像的widthheight值。 如果它们大于实际的源图像大小,则图像区域的其余部分将被填充黑色。