Imagick: compose with mask

2020-02-10 12:58发布

I try to recreate a script that uses the ImageMagick command "convert" to compose an image. But I want to do the same in PHP using Imagick (version 6.6.2-10).

The command is as follows:

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

I found out that the parameters stand for the following:

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

The PHP Imagick gives me a compose method, but without a mask parameter: http://www.php.net/manual/en/imagick.compositeimage.php

I found another question and tries this (but does not result in the same image):

// 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);

So my question is: is this the right way to compose an image using a mask? Or what's wrong here?

To help visualizing what I want to do, here are some input images:

input image a1 (background):

a1

input image a3 (overlay):

a3

input image a4 (mask):

a4

What I want the result to be:

correct output

What my php code creates:

wrong output

Thanks in advance! Michael

4条回答
狗以群分
2楼-- · 2020-02-10 13:30

try using compositeImage method and Imagick::COMPOSITE_COPYOPACITY

查看更多
Juvenile、少年°
3楼-- · 2020-02-10 13:33

I do not know if this will help, but I processed your images in ImageMagick 6.9.10.62 and 6.9.10.5 Q16 Mac OSX with the same result as shown below.

So if there is an issue, it is likely with Imagick.

What was your exact version of 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

I notice that if the same image dx is combined for dy, then I get a result similar to your bad result. That might mean that either the addImage or the flattenImage or the combineImage is not working correctly in your new Imagick.

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


enter image description here

Check your code to be sure you do not have a typo using $a3, $a3, and either $a3 or $a4 for your addImage.

For a test, try PHP

exec("convert img.png \( dx.png dy.png dy.png -combine \) -define compose:args=312x26.6776 -compose displace -composite result.png")
查看更多
劳资没心,怎么记你
4楼-- · 2020-02-10 13:41

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); 
查看更多
仙女界的扛把子
5楼-- · 2020-02-10 13:42

After struggling with this I finally found a way how to do it properly with 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);

Resources that I used:

查看更多
登录 后发表回答