Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Imagick: compose with mask

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

like image 677
Michael Avatar asked Nov 05 '12 12:11

Michael


3 Answers

try using compositeImage method and Imagick::COMPOSITE_COPYOPACITY

like image 69
Godfre Avatar answered Nov 20 '22 06:11

Godfre


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); 
like image 38
Maks Brainiac Avatar answered Nov 20 '22 08:11

Maks Brainiac


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:

  • https://github.com/mkoppanen/imagick/issues/49
  • https://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=26323
  • Merging RGB channels back into a single image with ImageMagick (php)
  • https://imagemagick.org/script/command-line-options.php#combine
like image 1
Michael Avatar answered Nov 20 '22 08:11

Michael