PHPGD2:如何保持alpha通道的透明度和正确的gamma

PHPGD2:如何保持alpha通道的透明度和正确的gamma,php,png,transparency,gd2,gamma,Php,Png,Transparency,Gd2,Gamma,我对图像缩放的效果很感兴趣,后来发现我用来从上传的图像创建缩略图的PHP代码也有同样的问题。我决定尝试底部附近发布的PHP修复程序(将gamma从2.2转换为1.0,调整图像大小,将gamma从1.0转换回2.2)。这可以解决文章中提到的问题,但是对代码的这种修改有一个不幸的副作用,那就是破坏了PNG alpha通道的透明度 这是我的伽马校正代码 <?php $image = imagecreatefrompng($source_file); $resized_image = imagec

我对图像缩放的效果很感兴趣,后来发现我用来从上传的图像创建缩略图的PHP代码也有同样的问题。我决定尝试底部附近发布的PHP修复程序(将gamma从2.2转换为1.0,调整图像大小,将gamma从1.0转换回2.2)。这可以解决文章中提到的问题,但是对代码的这种修改有一个不幸的副作用,那就是破坏了PNG alpha通道的透明度

这是我的伽马校正代码

<?php
$image = imagecreatefrompng($source_file);
$resized_image = imagecreatetruecolor($new_width, $new_height);
imagealphablending($resized_image, false);
imagesavealpha($resized_image, true);
imagegammacorrect($image, 2.2, 1.0);
imagecopyresampled($resized_image, $image, 0, 0, 0, 0, $new_width, $new_height, $image_width, $image_height);
imagegammacorrect($resized_image, 1.0, 2.2);
imagepng($resized_image, $dest_file);
?>

有人知道如何使用gamma校正技巧调整图像大小,同时保持原始图像的alpha通道透明度吗

编辑 示例图像:

  • 原始文件-具有alpha通道透明度的PNG
  • 已调整文件大小,两个imagegammacorrect()函数调用都已注释掉
  • 已调整文件大小,同时执行imagegammacorrect()函数调用
  • 在尝试校正gamma之前,可以看到透明度良好。(查看下面的透明度的最简单方法是检查环绕图像的段落标记,并通过FireBug或类似方式将背景:黑色添加到其样式属性。)


    imagecopyresampled()和透明度存在问题。请查看可能的解决方案。

    以下是一些确实有效的代码。基本上,它分离出alpha通道,使用gamma correct调整图像大小,在不使用gamma correct的情况下调整alpha通道大小,然后在alpha通道上复制到使用gamma correct调整大小的图像

    我猜imagegammacorrect()函数有一个bug。也许gamma只适用于RGB,而GD也尝试对alpha通道进行相同的计算?色彩理论不是我的专长

    不管怎样,这是代码。不幸的是,我找不到比逐个循环像素更好的方法来分离通道。哦,好吧

    <?php
    // Load image
    $image = imagecreatefrompng('test-image.png');
    
    // Create destination
    $resized_image = imagecreatetruecolor(100, 100);
    imagealphablending($resized_image, false); // Overwrite alpha
    imagesavealpha($resized_image, true);
    
    // Create a separate alpha channel
    $alpha_image = imagecreatetruecolor(200, 200);
    imagealphablending($alpha_image, false); // Overwrite alpha
    imagesavealpha($alpha_image, true);
    
    for ($x = 0; $x < 200; $x++) {
        for ($y = 0; $y < 200; $y++) {
            $alpha = (imagecolorat($image, $x, $y) >> 24) & 0xFF;
            $color = imagecolorallocatealpha($alpha_image, 0, 0, 0, $alpha);
            imagesetpixel($alpha_image, $x, $y, $color);
        }
    }
    
    // Resize image to destination, using gamma correction
    imagegammacorrect($image, 2.2, 1.0);
    imagecopyresampled($resized_image, $image, 0, 0, 0, 0, 100, 100, 200, 200);
    imagegammacorrect($resized_image, 1.0, 2.2);
    
    // Resize alpha channel
    $alpha_resized_image = imagecreatetruecolor(200, 200);
    imagealphablending($alpha_resized_image, false);
    imagesavealpha($alpha_resized_image, true);
    
    imagecopyresampled($alpha_resized_image, $alpha_image, 0, 0, 0, 0, 100, 100, 200, 200);
    
    // Copy alpha channel back to resized image
    for ($x = 0; $x < 100; $x++) {
        for ($y = 0; $y < 100; $y++) {
            $alpha = (imagecolorat($alpha_resized_image, $x, $y) >> 24) & 0xFF;
            $rgb = imagecolorat($resized_image, $x, $y);
            $r = ($rgb >> 16 ) & 0xFF;
            $g = ($rgb >> 8 ) & 0xFF;
            $b = $rgb & 0xFF;
            $color = imagecolorallocatealpha($resized_image, $r, $g, $b, $alpha);
            imagesetpixel($resized_image, $x, $y, $color);
        }
    }
    
    imagepng($resized_image, 'test-image-scaled.png');
    ?>
    
    
    
    用变量替换硬编码值当然。。。下面是我使用你的图像和我的代码得到的结果:



    (来源:)

    否,当我删除imagegammacorrect()函数调用时,透明度将毫无问题地保留下来。帮了忙。啊,那是个挑战!:-我看到了我的新答案。有趣的是,我明天回到办公室后将不得不花一些时间来解决这个问题:)为了将它与我现有的代码结合起来,我做了一些重构,但最终效果很好。非常感谢!