带有黑白面具的蒙版 PNG 图像

Mask PNG image with black and white mask

我有如下图片(请注意透明背景):

我也有一个black/white口罩同样大小:

我想 "crop" 这件衣服,只得到第一张图片中黑色圆圈中的部分。我尝试了很多不同的方法,但它们都不起作用或太慢:

1) ImageMagick(命令行)<== 我可以使用哪个命令来实现此目的?我试过 multiply 和 copyopacity 但它们没有用

2) WideImage 正在运行:$maskedImage = $source->applyMask($mask); 但需要超过 12 秒。

如果可能,我对 ImageMagick 解决方案感兴趣。

编辑

如果掩码小于原始图像并且原始图像很简单,则提供的解决方案可以正常工作。使用这些源图像和蒙版,结果是 "smeared":

来源:

掩码:

命令:

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

结果(为了显示错误的白色,我添加了灰色背景而不是透明背景):

我想你想要这个:

magick dress.png \( mask.png -alpha off -negate \) -compose copyalpha -composite result.png

或者,如果您不喜欢括号,请先加载蒙版并整理您的 alpha 通道,然后加载裙子,然后 +swap 合成前的顺序:

magick mask.png -alpha off -negate dress.png +swap  -compose copyalpha -composite result.png

您的 ImageMagick 版本似乎太旧,无法包含 "copyalpha" 组合运算符。这是获得结果的另一种方法...

convert dress.png \( circle.png -negate \) \
   \( -clone 0 -transparent red +transparent red \) -insert 0 -composite result.png

读入你的主图像,然后读入你的蒙版图像并取消它,然后创建一个透明层并使用“-insert”将其移动到列表中的第一个位置。 ImageMagick 对具有三个输入图像的“-composite”的默认处理是使用第三个图像(现在是带有黑色圆圈的图像)作为 alpha 蒙版。您仍然需要“-negate”那个蒙版,或者制作一个黑白颠倒的新蒙版。

那里用来创建透明的方法canvas是读入括号内的其他图像之一,将所有红色更改为透明,然后将所有更改红色至透明。这导致完全透明 canvas 用作复合列表中的第一张图像,即目标图像。

使用 copy_opacity 而不是 copy_alpha,它应该在 ImageMagick 6 或 ImageMagick 7 中正常工作。这对我来说很好用:

输入:

掩码:

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


上面使用convert的命令适用于ImageMagick 6。如果使用ImageMagick 7,请将convert改为magick。两者都对我有用。

一天结束时,我一直在使用 WideImage,虽然速度很慢,但效果很好。这是我用来屏蔽图像的 class:

<?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;
    }
}