我注意到Imagick::paintOpaqueImage
仅对 alpha 值为 1 的像素进行操作。这会导致转换后的图像带有大量我要替换的颜色的剩余像素。以此测试图像为例
这段代码用红色像素替换蓝色像素。
$img->paintOpaqueImage('rgb(12,0,245)', 'rgb(255,0,0)', 0);
结果只是纯蓝色像素被替换。
请注意,该测试图像中的所有像素(除了完全透明的像素)都是相同的蓝色。唯一的区别是 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 的红色图像,其中保留了我想要的半透明(和完全透明)像素。
主要问题,也是最终让我想到我的问题的是,这种方法非常慢。有没有办法直接使用 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');
结果:
关于php - Imagick::paintOpaqueImage 忽略半透明像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32515666/