使用PHP的GDlib imagecopy重新采样时,能否保留PNG图像的透明度?

时间:2020-03-05 18:44:22  来源:igfitidea点击:

以下PHP代码段使用GD将浏览器上传的PNG的大小调整为128x128. 效果很好,只是在我的情况下,原始图像中的透明区域已被替换为纯色黑色。

即使设置了" 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 );

解决方案

回答

我相信这应该可以解决问题:

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

编辑:PHP文档中的某人声称imagealphablending应该为true,而不为false。 YMMV。

回答

imagealphablending( $targetImage, false );
imagesavealpha( $targetImage, true );

为我做了。谢谢ceejayoz。

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

编辑:
完整的替换代码。另请参见下面的答案及其评论。不能保证这是完美的,但确实满足了我的需求。

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

回答

重新设置保留透明性,然后像其他文章中所述的那样,必须将imageavealpha()设置为true,才能使用alpha标志imagealphablending()必须设置为false,否则它将不起作用。

另外,我在代码中发现了两个小问题:

  • 我们不需要调用getimagesize()来获取imagecopyresmapled()的宽度/高度。
  • $ uploadWidth和$ uploadHeight应该是值-1,因为坐标是从0开始而不是从1开始,因此它将复制到一个空像素中。替换为:imagesx($ targetImage)-1imagesy($ targetImage)-1,相对来说应该这样做:)

回答

你为什么使事情变得如此复杂?以下是我使用的内容,到目前为止,它已经为我完成了工作。

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

回答

我想这可能会解决问题:

$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%绿色像素被剥离。无论如何,希望对我们有所帮助:)