如何合成两个图像(使用 Source In 合成)?

How to compose two images (using Source In composition)?

我需要对 2 张图像执行 Source In composition

例如这张图片:

和蒙版图像(用黑色透明和黑白测试):

应该产生结果:

我正在尝试用 ImageSharp 来做到这一点:

img.Mutate(imgMaskIn =>
{
    using (var mask = Image.Load(maskImageFileName))
    {
        imgMaskIn.DrawImage(mask, new GraphicsOptions { AlphaCompositionMode = PixelAlphaCompositionMode.SrcIn});
    }
});

但结果是蒙版图像。它应该基于 this merge request.
工作 是我用错库了,还是有bug?

在 ASP.NET Core 中还有其他方法可以做到这一点吗?

不幸的是,ImageSharp 的语法在当前预览版和开发版之间发生变化,这应该是最终的 API。

使用 1.0.0-beta0005,您可以像这样混合这些图像:

using (var pattern = Image.Load("img_pattern.png"))
using (var texture = Image.Load("img_texture.png"))
{
    var options = new GraphicsOptions { BlenderMode = PixelBlenderMode.In };
    using (var result = pattern.Clone(x => x.DrawImage(options, texture)))
    {
        result.Save("img_out.png");
    }
}

请注意,您必须为此使用具有 alpha 透明度的图案图像。您不能使用键控透明度(至少不能使用此解决方案)。

为此,我已将图案设为透明(您可以 get the one I used here)并得到以下结果:


在最终版本中,它将如下所示:

using (var pattern = Image.Load("img_pattern.png"))
using (var texture = Image.Load("img_texture.png"))
{
    var options = new GraphicsOptions { AlphaCompositionMode = PixelAlphaCompositionMode.SrcIn };
    using (var result = pattern.Clone(x => x.DrawImage(texture, options)))
    {
        result.Save("img_out.png");
    }
}

顺便说一下,这是一个很好的解决方法。是查看包含此功能测试的 PorterDuffCompositorTests file,因此将始终反映当前的 API。

截至 2022 年 3 月,已接受的答案不再适用于 ImageSharp 2。以下代码并未解决问题中的确切问题,但这是我获得类似工作的方法:

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Drawing;
...
using (var inImg = Image.Load<RgbaVector>(imagePath)) //has some transparent pixels
using (var background = new Image<RgbaVector>(inImg.Width, inImg.Height, new RgbaVector(1, 0, 0, 1))) //this is just a solid red image of the same size as the loaded image, but it could be any image
{
    var processorCreator = new DrawImageProcessor(
        inImg, 
        Point.Empty, 
        PixelColorBlendingMode.Normal, 
        PixelAlphaCompositionMode.SrcAtop, //this is the setting you want to play with to get the behavior from the original question
        1f
    ); 
                
    var pxProcessor = processorCreator.CreatePixelSpecificProcessor(
        Configuration.Default, 
        background, 
        inImg.Bounds());

    pxProcessor.Execute(); //writes to the image passed into CreatePixelSpecificProcessor, in this case background

    background.Save("some_path.png");
    }
}