【问题标题】:PHP GD2: how to maintain alpha channel transparency and correct gammaPHP GD2:如何保持 alpha 通道透明度和正确的 gamma
【发布时间】:2011-03-19 05:36:07
【问题描述】:

我对图像缩放的this discussion 很感兴趣,随后发现我用来从上传的图像创建缩略图的 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);
?>

有谁知道如何调整图像大小,采用伽玛校正技巧,同时保持原始图像的 Alpha 通道透明度?

编辑

示例图片:

  1. 原始文件 - 具有 Alpha 通道透明度的 PNG
  2. 已注释掉两个 imagegammacorrect() 函数调用的调整大小文件
  3. 使用两个 imagegammacorrect() 函数调用调整大小的文件

在您尝试校正 Gamma 之前,您可以看到透明度很好。 (查看透明度的最简单方法是检查包裹在图像周围的段落标签,并通过 FireBug 或类似方法将背景添加到其样式属性中。)

original image http://ender.hosting.emarketsouth.com/images/test-image.png no gamma correction http://ender.hosting.emarketsouth.com/images/test-image-resized-no-gamma.png gamma corrected - no transparency http://ender.hosting.emarketsouth.com/images/test-image-resized.png

【问题讨论】:

    标签: php png transparency gd2 gamma


    【解决方案1】:

    这里有一些有效的代码。基本上,它分离出 alpha 通道,使用 gamma 校正调整图像大小,调整 alpha 通道的大小没有 gamma 校正,然后将 alpha 通道复制到使用 gamma 校正完成的调整大小的图像。

    我的猜测是 imagegammacorrect() 函数有一个错误。也许 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');
    ?>
    

    当然用变量替换硬编码的值......这是我使用你的图像和我的代码得到的结果:


    (来源:jejik.com

    【讨论】:

    • 有趣,我明天回到办公室时得花点时间处理这个:)
    • 为了将其与我现有的代码结合起来,需要进行一些重构,但最终效果很好。非常感谢!
    【解决方案2】:

    imagecopyresampled() 和透明度存在问题。请查看this comment on php.net 以获得可能的解决方案。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 2014-12-29
    • 2012-01-02
    • 1970-01-01
    • 2010-12-30
    • 2012-12-24
    • 2019-03-28
    相关资源
    最近更新 更多