php - Imagick::paintOpaqueImage 忽略半透明像素

标签 php image-processing imagick

我注意到Imagick::paintOpaqueImage仅对 alpha 值为 1 的像素进行操作。这会导致转换后的图像带有大量我要替换的颜色的剩余像素。以此测试图像为例

enter image description here

这段代码用红色像素替换蓝色像素。

$img->paintOpaqueImage('rgb(12,0,245)', 'rgb(255,0,0)', 0);

结果只是纯蓝色像素被替换。

enter image description here

请注意,该测试图像中的所有像素(除了完全透明的像素)都是相同的蓝色。唯一的区别是 alpha 值。另请注意,我为 $fuzz 参数使用了值 0。最初我是这样颠簸的,直到我发现真正的问题是什么,这才导致了不良的结果。

我使用 ImagickPixelIterator 编写了一个解决方案;它克隆当前像素,并将当前像素和克隆像素的 alpha 值设置为 1 以强制 ImagickPixel::isSimilar与 alpha 值无关地工作。

$img      = new Imagick('./test-paint-opaque-image.png');
$iterator = new ImagickPixelIterator($img);
$target   = new ImagickPixel('rgb(12,0,245)'); // blue
$fill     = new ImagickPixel('rgb(255,0,0)');  // red
$fuzz     = 0;

foreach($iterator as $pixels) {
    foreach($pixels as $curPixel) {
        // Modify the alpha of the comparePixel so it won't throw off the isSimilar() check
        $comparePixel = clone $curPixel;
        $fOrigAlpha   = $curPixel->getColorValue(Imagick::COLOR_ALPHA);

        // Bail on fully transparent pixels
        if($fOrigAlpha == 0)
            continue;

        // It seems the only way isSimilar will work is when the alpha is 1 for both pixels...
        $comparePixel->setColorValue(Imagick::COLOR_ALPHA, 1);
        $curPixel->setColorValue(Imagick::COLOR_ALPHA, 1);

        if($comparePixel->isSimilar($target, $fuzz)) {
            $curPixel->setColorValue(Imagick::COLOR_RED,   $fill->getColorValue(Imagick::COLOR_RED));
            $curPixel->setColorValue(Imagick::COLOR_GREEN, $fill->getColorValue(Imagick::COLOR_GREEN));
            $curPixel->setColorValue(Imagick::COLOR_BLUE,  $fill->getColorValue(Imagick::COLOR_BLUE));

            // Set the modified alpha back to what it was after the color change
            if($fOrigAlpha > 0) {
                echo "Setting alpha to $fOrigAlpha\n";
                $curPixel->setColorValue(Imagick::COLOR_ALPHA, $fOrigAlpha);
            }
        }
    }
    $iterator->syncIterator();
}

结果是一个 Shiny 的红色图像,其中保留了我想要的半透明(和完全透明)像素。

enter image description here

主要问题,也是最终让我想到我的问题的是,这种方法非常慢。有没有办法直接使用 PHP Imagick::paintOpaqueImage 来进行这种颜色转换?

最佳答案

您可以在替换颜色值之前停用 Alpha channel ,然后使用 setImageAlphaChannel() 重新激活它。 ,像这样:

$img = new Imagick('./test-paint-opaque-image.png');
$img->setImageAlphaChannel(Imagick::ALPHACHANNEL_DEACTIVATE);
$img->opaquePaintImage('rgb(12,0,245)', 'rgb(255,0,0)', 0, false);
$img->setImageAlphaChannel(Imagick::ALPHACHANNEL_ACTIVATE);
$img->writeImage('./out.png');

结果:

Result


关于php - Imagick::paintOpaqueImage 忽略半透明像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32515666/

相关文章:

php - 如何检测 Joomla! 的当前语言!网站?

php - 将包含放在函数内会减慢执行速度吗?

php - 视频上传,只上传20秒以下的视频

java - OpenCV 图像采集卡输出图像不正确

imagemagick 将具有透明层的 AI 文件转换为 PNG

php - 带类型转换的空合并运算符

c++ - 如何进入图像处理编程?

php - 使用 imagick 驱动程序调整为小图像的图像会产生大文件大小

php - 更改 ImageMagick 的 tmp

python - 如何预处理图像以去除噪声并提取Python文本?