Imagick:使用遮罩合成

16

我试图重新创建一个使用ImageMagick命令“convert”组合图像的脚本。但是我想在PHP中使用Imagick(版本6.6.2-10)完成同样的操作。

命令如下:

convert A1.mpc A3.mpc A4.mpc -channel rgba -alpha on -virtual-pixel background -background none -define compose:args=312x26.6776 -compose displace -composite out.mpc

我发现这些参数分别代表以下含义:

convert  {background} {overlay} [{mask}] [-compose {method}] -composite {result}

PHP Imagick提供了一个合成方法,但没有掩码参数:http://www.php.net/manual/en/imagick.compositeimage.php

我发现另一个问题并尝试了这个方法(但结果与原图不同):

// load images
$a1 = new Imagick('a1.png');
$a3 = new Imagick('a3.png');
$a4 = new Imagick('a4.png');

// mask the overlay
$a1->compositeImage($a4, Imagick::COMPOSITE_DSTIN, 0, 0, Imagick::CHANNEL_ALPHA);

// compose overlay to background
$a1->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_BACKGROUND);
$a1->setImageBackgroundColor(new ImagickPixel('none'));
$a1->setOption('compose:args', '312x26.6776');
$a1->compositeImage($a3, Imagick::COMPOSITE_DISPLACE, 0, 0);

那么我的问题是: 使用遮罩合成图像的方式是否正确?还是哪里出了问题?

为了帮助您理解我想做什么,以下是一些输入图像:

输入图像a1(背景):

a1

输入图像a3(叠加层):

a3

输入图像a4(遮罩):

a4

我想要的结果:

correct output

我的PHP代码创建的结果:

wrong output

提前感谢! Michael


1
为什么不使用 COMPOSITE_OVERLAY 标志? - artragis
我曾经也遇到过这个问题,最终我写了一个专门用于合成带有滤镜和图层的图像的包。这个包叫做 pslayers,我们在几个应用程序中使用它进行生产。 - darryn.ten
4个回答

3

尝试使用compositeImage方法和Imagick::COMPOSITE_COPYOPACITY


1

Try this code:

// x-displacement
$a3->setImageArtifact('compose:args', "312x0");
$a1->compositeImage($a3, Imagick::COMPOSITE_DISPLACE, 0, 0);

// y-displacement
$a4->setImageArtifact('compose:args', "0x26.6776");
$a1->compositeImage($a4, Imagick::COMPOSITE_DISPLACE, 0, 0); 

4
虽然这段代码可能是解决方案,但包括解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而那些人可能不知道您提供代码建议的原因。 - yivi
经过更多的测试,这不是理想的解决方案,因为ImageMagick的行为非常奇怪:有时会生成正确的图像,有时则不会。最终我采用了另一种解决方案,我将其发布为答案。 - Michael

1

在经过一番努力后,我终于找到了使用PHP-Imagick正确处理此问题的方法。

// merge x-displacement and y-displacement into one displacement-map
$displaceMask = new Imagick();
$displaceMask->addImage($a3);
$displaceMask->addImage($a4);
$displaceMask->addImage($a4);
$displaceMask->flattenImages();
$displaceMask = $displaceMask->combineImages(Imagick::CHANNEL_ALL);

$displaceMask->setImageArtifact('compose:args', '312x26.6776');
$a1->compositeImage($displaceMask, Imagick::COMPOSITE_DISPLACE, 0, 0);

我使用的资源:


1
恭喜,这是在Imagick中正确的方法。请参阅https://imagemagick.org/Usage/mapping/#displace_2d部分末尾关于统一位移映射的注释。 - fmw42
@fmw42 似乎某些ImageMagick/Imagick版本更改了如何应用位移映射。我现在将ImageMagick从6.7.9-Q16更新到6.9.10-Q16(我知道,仍然不是最新的),将Imagick从3.2.0更新到3.4.3,那么生成的图像不再是圆柱形了。你有任何提示是发生了什么变化吗? - Michael
抱歉,不会。我不知道升级会导致问题的原因,除非新版本的ImageMagick在这方面有错误。抱歉,我对Imagick了解不多。您只需要将3个图像合并成一个RGB图像。X位移放入红色通道,Y位移放入绿色通道,黑色(或任何颜色)的图像放入蓝色通道。但我不是Imagick的专家。 - fmw42
@fmw42 好的,不过还是谢谢您查看!顺便说一句,“flattenImage”也是必须的,正如这里所描述的一样:https://dev59.com/tmTWa4cB1Zd3GeqPDnYC#10888157 - Michael
1
另一种可能的方法是仅使用复合三次,每次使用copy_red、copy_green和copy_blue之一,分别针对X、Y、黑色图像。这样,X、Y、黑色就会被复制到位移图像的三个通道中。 - fmw42
显示剩余7条评论

1
我不知道这是否有帮助,但我使用ImageMagick 6.9.10.62和6.9.10.5 Q16 Mac OSX处理了您的图像,并得到了与下面显示的相同结果。
因此,如果存在问题,很可能是Imagick的问题。
您确切使用的版本是6.9.10.x吗?
convert img.png \
\( dx.png dy.png dy.png -combine \) \
-define compose:args=312x26.6776 -compose displace -composite \
result.png


enter image description here

我注意到如果相同的图像dx用于dy,那么得到的结果与您的不良结果类似。这可能意味着在您的新Imagick中,addImage、flattenImage或combineImage其中之一未正常工作。
convert img.png \
\( dx.png dx.png dy.png -combine \) \
-define compose:args=312x26.6776 -compose displace -composite \
result2.png


enter image description here

请检查您的代码,确保您在使用 $a3、$a3 以及 $a3 或 $a4 作为 addImage 参数时没有打错字。

作为测试,请尝试 PHP。

exec("convert img.png \( dx.png dy.png dy.png -combine \) -define compose:args=312x26.6776 -compose displace -composite result.png")

我尝试了这个,通过命令行似乎可以正常工作,两个版本的结果相同。我将其作为第二次编辑添加:https://stackoverflow.com/questions/57722353/apply-displacement-map-via-imagick-after-version-update - Michael
作为最新的更新:它是这样工作的,但结果有些像素化。所以到目前为止,我无法将其用作解决方法 :-( - Michael

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