Я заметил, что Imagick::paintOpaqueImage
работает только с пикселями с альфа-значением 1. Это оставляет преобразованные изображения с большим количеством оставшихся пикселей из цветов, которые я пытаюсь заменить. Возьму для примера тестового изображенияImagick :: paintOpaqueImage игнорирует полупрозрачные пиксели
И этот код, чтобы заменить синие пиксели с красными.
$img->paintOpaqueImage('rgb(12,0,245)', 'rgb(255,0,0)', 0);
В результате заменены только твердые синие пиксели.
Обратите внимание всем пикселей в этом тестовом изображении (в стороне от полностью прозрачных) имеют такой же цвет синие. Единственное отличие - значение альфа. Также обратите внимание, что я использовал значение 0 для параметра $fuzz
. Изначально я сталкивался с этим, прежде чем я обнаружил, что такое настоящая проблема, и это вызывало его собственные нежелательные результаты.
Я взломал решение, используя ImagickPixelIterator
; это clones
текущий пиксель и устанавливает альфа-значение как текущего пикселя, так и клонированного пикселя в 1, чтобы заставить ImagickPixel::isSimilar
работать агностически в отношении альфа-значений.
$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();
}
В результате получается блестящий красный образ, с полупрозрачными (и полностью прозрачными) пикселей сохранились, как хотелось бы.
Основная проблема, и что, наконец, приносит мне на мой вопрос в том, что этот метод является нечестивым медленно. Есть ли способ использовать PHP Imagick::paintOpaqueImage
непосредственно, чтобы сделать такой вид преобразования цвета?
Просто выбрасывая идеи, можно отделить альфа-канал от изображения, применить paintOpaqueImage, а затем восстановить альфа-канал? – Scuzzy