phpimagemagickwideimage

Mask PNG image with black and white mask


I have the following image (please note the transparent background):

enter image description here

I also have a black/white mask of the same size:

enter image description here

I would like to "crop" the dress and get just the portion of the first image contained in the black circle. I tried many different methods but they didn't work or are too slow:

1) ImageMagick (command line) <== which command can I use to achieve this? I tried multiply and copyopacity but they didn't work

2) WideImage is working: $maskedImage = $source->applyMask($mask); but it takes more than 12 seconds.

I am interested in a ImageMagick solution if possible.

EDIT

The provided solutions work fine if the mask is smaller than the original image and if the original image is simple. With these source image and mask the result is "smeared":

Source:

enter image description here

Mask:

enter image description here

Command:

convert source.png \( mask.png -negate \) -alpha off -compose copy_opacity -composite result.png

Result (I added a grey background instead of the transparent one in order to show the wrong white):

enter image description here


Solution

  • At the end of the day I kept using WideImage which is quite slow but works well. This is the class I use to mask images:

    <?php
    
    namespace AppBundle\Service\Import;
    
    use WideImage\WideImage;
    
    class ImageMasker
    {
        /**
         * @var string
         */
        private $tempDirectory;
    
        public function __construct(string $tempDirectory)
        {
            $this->tempDirectory = $tempDirectory;
        }
    
        /**
         * @param string $sourcePath
         * @param string $maskPath
         */
        public function mask($sourcePath, $maskPath)
        {
            $source = WideImage::load($sourcePath);
            $mask   = WideImage::load($maskPath);
    
            $tempFilename = uniqid().'.png';
            $tempPath     = rtrim($this->tempDirectory, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$tempFilename;
    
            // applies the mask and saves the file
            $maskedImage = $source->applyMask($mask);
            $maskedImage->saveToFile($tempPath);
    
            return $tempPath;
        }
    }