109

以下 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 );
4

10 回答 10

211
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 );
于 2008-08-28T13:41:12.640 回答
22

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

$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]);
于 2008-11-14T23:22:35.327 回答
12

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

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

编辑: PHP 文档声明中的某个人imagealphablending应该是真的,而不是假的。YMMV。

于 2008-08-28T13:32:15.220 回答
9

可能对某些人有所帮助的补充:

可以在构建图像时切换 imagealphablending。在我需要这个的特定情况下,我想在透明背景上组合一些半透明的 PNG。

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

然后将 imagealphablending 切换为 true 并将一些 PNG 图像添加到画布,使一些背景可见(即不填满整个图像)。

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

于 2011-01-06T17:57:01.850 回答
7

我制作了一个用于调整 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;
}
于 2011-10-11T19:27:12.487 回答
5

我想这可能会奏效:

$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% 的绿色像素都会去除图像。无论如何,希望它有所帮助:)

于 2009-08-19T22:06:05.477 回答
2

重新分级保留透明度,然后像其他帖子中所说的那样是的,必须将imagesavealpha()设置为true,使用alpha标志imagealphablending()必须设置为false,否则它不起作用。

我还在您的代码中发现了两件小事:

  1. 你不需要打电话getimagesize()来获取宽度/高度imagecopyresmapled()
  2. $uploadWidthand$uploadHeight应该是值,-1因为坐标从0and not开始1,所以它会将它们复制到一个空像素中。将其替换为:imagesx($targetImage) - 1imagesy($targetImage) - 1,相对应该这样做:)
于 2008-09-01T02:01:23.353 回答
0

这是我的总测试代码。这个对我有用

$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);
于 2016-06-16T23:52:13.813 回答
0

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

于 2017-09-06T21:35:03.837 回答
0

我结合了 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);
于 2018-08-12T16:46:52.687 回答