Imagick::paintOpaqueImage 忽略半透明像素
Imagick::paintOpaqueImage ignores translucent pixels
我注意到 Imagick::paintOpaqueImage
仅对 alpha 值为 1 的像素进行操作。这会使转换后的图像留下许多我要替换的颜色的剩余像素。以这个测试图像为例
此代码用红色像素替换蓝色像素。
$img->paintOpaqueImage('rgb(12,0,245)', 'rgb(255,0,0)', 0);
结果只是替换了纯蓝色像素。
请注意该测试图像中的所有像素(除了完全透明的像素)都是相同的蓝色。唯一的区别是 alpha 值。另请注意,我为 $fuzz
参数使用了 0 值。在我发现真正的问题是什么之前,我最初是这样颠簸的,这导致了它自己的不良结果。
我已经使用 ImagickPixelIterator
; it clones
the current pixel and sets the alpha value of both the current pixel and cloned pixel to 1 to coerce 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();
}
结果是闪亮的红色图像,保留了我想要的半透明(和完全透明)像素。
主要问题,也是最终让我想到我的问题的是,这种方法非常慢。有没有办法直接用PHPImagick::paintOpaqueImage
做这种颜色变换?
您可以在替换颜色值之前停用 alpha 通道,然后在使用 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');
结果:
我注意到 Imagick::paintOpaqueImage
仅对 alpha 值为 1 的像素进行操作。这会使转换后的图像留下许多我要替换的颜色的剩余像素。以这个测试图像为例
此代码用红色像素替换蓝色像素。
$img->paintOpaqueImage('rgb(12,0,245)', 'rgb(255,0,0)', 0);
结果只是替换了纯蓝色像素。
请注意该测试图像中的所有像素(除了完全透明的像素)都是相同的蓝色。唯一的区别是 alpha 值。另请注意,我为 $fuzz
参数使用了 0 值。在我发现真正的问题是什么之前,我最初是这样颠簸的,这导致了它自己的不良结果。
我已经使用 ImagickPixelIterator
; it clones
the current pixel and sets the alpha value of both the current pixel and cloned pixel to 1 to coerce 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();
}
结果是闪亮的红色图像,保留了我想要的半透明(和完全透明)像素。
主要问题,也是最终让我想到我的问题的是,这种方法非常慢。有没有办法直接用PHPImagick::paintOpaqueImage
做这种颜色变换?
您可以在替换颜色值之前停用 alpha 通道,然后在使用 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');
结果: