PHP和GD - 透明背景被填充近似颜色

6

我知道PHP+GD透明度问题已经在这个和许多其他网站上被反复讨论,但我已经遵循了所有建议,但似乎无法解决我的问题。

首先,解释一下:

我试图将一张图片覆盖在另一张图片上。它们都有透明区域。作为一个我知道应该呈现特定方式的演示,我试图在我创建的蓝色箭头形状上覆盖一个勾选标记。

这是这两个图片:

check mark

blue arrow

现在来看我的代码:
我正在使用一个我构建的库/API,以减轻使用PHP+GD编辑图像时的一点点痛苦。它仍处于萌芽阶段,但相关文件包括: 基础类 主加载器 (命名不恰当的)合并类 我正在使用以下脚本运行代码:
<?php
    require_once('Image.php');

    header("Content-Type: image/png");

    $img = new Image();
    $over = new Image();

    $img->source = "arrow.png";
    $over->source = "chk-done_24.png";

    $img->Combine->Overlay($over, 20, 20, 0, 0, $over->width, $over->height);
    $img->output();
    $img->clean();
    unset($img);
?>

我期望的输出应该像这样:

Combined images

但我得到了这个:

Square bottom

我完全理解这个问题,如果填充区域是白色或黑色,但用蓝色填充就没有任何意义。
在我上面链接的“Combine Class”中,我还尝试了imagecopy, imagecopyresampled和普通的imagecopymerge,结果都类似。
我完全不知所措。
编辑:
明确一下,我的问题是:我的代码哪部分有误?为什么它会用颜色填充透明区域(而不是黑色或白色),我如何修复它,同时仍然保持合并具有透明度的图像的能力?
更新:
请注意,当创建新的 Image 对象时,它调用 newImage,其中包含以下代码:
$this->handle = imagecreatetruecolor($this->width, $this->height);
imagealphablending($this->handle, false);
imagesavealpha($this->handle, true);

我觉得那可能很容易被忽略。


你可以很容易地使用GD来完成这个任务,但是尝试仅使用叠加而不是合并两个图像。 - Khurram Ijaz
你制作箭头文件的方法可能存在透明度问题吗? - Jared Farrish
@Jared 我想这是可能的。我不是图片/透明度方面的专家,所以我不知道有不同的方法可以获得完全透明的背景。我将离开电脑几个小时,但我会在今天晚些时候尝试在另一张图片上获得不同的结果。 - rockerest
1
@rockerest - 嗯,当我在Photoshop中打开您的原始箭头图像时,它显示为合并图像中的样子(下半部分没有透明度)。当我谷歌Photoshop PNG透明度时,我发现Photoshop处理此类问题存在问题,因此您可以尝试使用蒙版构建图像或只擦除您不想显示的额外像素,并查看是否会改变结果(我想象中会这样)。 - Jared Farrish
检查一下Jared说的话,我以前也遇到过这种情况,虽然我不记得问题是什么了,但在Photoshop中看起来很好,但在网页上却不正常。可能你的脚本没问题,但未经优化的图像可能会导致这种情况。如果你可以尝试其他透明图片,也可以帮助你进行故障排除。 - Stephane Gosselin
1个回答

2
请注意,您在newImage中创建句柄并调用imagealphablendingimagesavealpha是无关紧要的,因为loadImage会丢弃该句柄。
之所以会用蓝色填充透明区域,是因为它根本没有用任何东西填充透明区域。它只是完全丢弃了Alpha通道,并且蓝色恰好存储在那些Alpha值为零的像素中。请注意,在图形程序中可能很难看到这一点,因为该程序可能会用黑色或白色替换完全透明的像素。
至于您的代码有什么问题,我不能确定,因为当我尝试您现有的代码时,我的结果与您报告的结果不同。但如果我将您的loadImage更改为以下内容,使源图像强制为真彩色,则对我有效:
            private function loadImage()
            {
                    $img = null;
                    switch( $this->type )
                    {
                            case 1:
                                            $img = imagecreatefromgif($this->source);
                                            break;
                            case 2:
                                            $img = imagecreatefromjpeg($this->source);
                                            break;
                            case 3:
                                            $img = imagecreatefrompng($this->source);
                                            break;
                            default:
                                            break;
                    }
                    if (!$img) return false;
                    $this->handle = imagecreatetruecolor($this->width, $this->height);
                    imagealphablending($this->handle, false);
                    imagesavealpha($this->handle, true);
                    imagecopyresampled($this->handle, $img, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
                    return true;
            }

就我个人而言,我更喜欢使用ImageMagick而非GD。


你说得都对。我使用了在网上找到的一个透明图像,它“起作用了”。我得到了两个图像合并后的黑色填充。我将修复我的代码,使加载的图像强制保持alpha通道,并且当它工作时,我会回来给你奖励金。感谢您提供的代码示例! - rockerest
谢谢帮忙,这个方法有效。我会在能够颁发奖励的时候(显然是一个小时后)进行颁发。 - rockerest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接