【问题标题】:Mask PNG image with black and white mask使用黑白蒙版蒙版 PNG 图像
【发布时间】:2020-05-13 01:37:11
【问题描述】:

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

我也有一个黑白面具大小相同

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

1) ImageMagick(命令行)

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

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

编辑

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

来源:

面具:

命令:

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

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

【问题讨论】:

    标签: php imagemagick wideimage


    【解决方案1】:

    我想你想要这个:

    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
    

    【讨论】:

    • 谢谢马克!为什么我需要否定面具?它需要是一个白色圆圈(我可以更改图像)吗?我测试了命令,但得到了:convert-im6.q16: unrecognized compose operator ``copyalpha' @ error/convert.c/ConvertImageCommand/1100.
    • 那是因为您使用的是旧的 v6 ImageMagick。请改用copyopacity
    • 我编辑了我的问题,命令有效,但结果看起来“模糊”。
    【解决方案2】:

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

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

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

    用于创建透明画布的方法是读取括号内的其他图像之一,将所有红色更改为透明,然后将所有红色更改为透明。这会产生一个完全透明的画布,用作合成列表中的第一张图像,即目标图像。

    【讨论】:

    • 我编辑了我的问题,命令有效,但结果看起来“模糊”。
    【解决方案3】:

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

    输入:

    面具:

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


    上面使用convert的命令是针对ImageMagick 6的。如果使用ImageMagick 7,把convert改成magick。两者都对我有用。

    【讨论】:

      【解决方案4】:

      最后,我一直在使用 WideImage,虽然速度很慢,但效果很好。这是我用来屏蔽图像的类:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-11
        • 1970-01-01
        • 2014-08-29
        • 2022-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-05
        相关资源
        最近更新 更多