UWP透明png颜色叠加

use*_*834 2 c# imaging win-universal-app

我的UWP c#项目中有一个图像,它是带有白色前景的透明png。我现在想将白色从此png图像更改为另一种颜色(如蓝色)。

示例(请注意,彩色图像没有透明的背景。这是由于我使用的不好的图像处理软件引起的,并且演示了白色的变化。最终的背景应该是透明的)。

泡泡1 泡泡2

我记得,这是可以统一实现的,现在我想现在在uwp-app中做到这一点。我曾考虑过使用Lumia ImagingSDKComposition API,但不知道热衷于使用它们。

rob*_*ikh 5

您可以使用合成效果系统来做到这一点。

先决条件

  1. 至少定位到版本10586(Composition API在此之前是实验性的)。
  2. 虽然不是严格要求,但对视觉层有基本了解不会有任何伤害。我写了一篇博客文章,这里是对该主题的介绍。
  3. 添加Win2D nuget包。

此外,您可以参考我在这里写的要点,这是在XAML应用程序中使用Composition API进行安装和运行的快速方法。它也会演示使用效果。不仅如此,它还涵盖了使用Composition API(带有我编写的程序包)加载图像。

入门

您需要做与要点非常相似的操作,但是InvertEffect要定义a CompositeEffect和a 而不是定义an ColorSourceEffect。要做的是拍摄图像并将其用作“蒙版”,然后将图像中的白色替换为彩色。您可以这样定义效果:

IGraphicsEffect graphicsEffect = new CompositeEffect
{
    Mode = Microsoft.Graphics.Canvas.CanvasComposite.DestinationIn,
    Sources =
    {
        new ColorSourceEffect
        {
            Name = "colorSource",
            Color = Color.FromArgb(255, 255, 255, 255)
        },
        new CompositionEffectSourceParameter("mask")
    }
};
Run Code Online (Sandbox Code Playgroud)

下一步是创建一个效果工厂:

var effectFactory = compositor.CreateEffectFactory(graphicsEffect, new string[] { "colorSource.Color" });
Run Code Online (Sandbox Code Playgroud)

在这种情况下,第二个参数(虽然不是必需的)可能是您想要的。设置此参数可让您在效果编译后更改属性,从而允许您手动设置它以及创建的每个新效果笔刷或在效果笔刷上对该属性设置动画。我们只是手动设置它。使用新的效果工厂创建新的效果笔刷。请注意,该工厂可以使用您上面使用的定义来创建许多新的效果笔刷:

var effectBrush = effectFactory.CreateBrush();
Run Code Online (Sandbox Code Playgroud)

但是,首先,您需要将图像用作蒙版。您可以使用我编写的名为CompositionImageLoader的库将图像加载到表面中。您也可以在nuget上下载它。用图像创建表面后,创建一个CompositionSurfaceBrush并将其应用于效果。

var imageLoader = ImageLoaderFactory.CreateImageLoader(compositor);

var surface = imageLoader.LoadImageFromUri(new Uri("ms-appx:///Assets/Images/HAvng.png"));
var brush = compositor.CreateSurfaceBrush(surface);

effectBrush.SetSourceParameter("mask", brush);
Run Code Online (Sandbox Code Playgroud)

请注意,您可能应该将ImageLoader放在某个位置,因为一遍又一遍地创建将很昂贵。剩下要做的就是将效果画笔应用于视觉效果并设置颜色:

visual.Brush = effectBrush;

effectBrush.Properties.InsertColor("colorSource.Color", Colors.Red);
Run Code Online (Sandbox Code Playgroud)

然后您就完成了!请注意,如果要在此之后更改颜色,您要做的就是InsertColor使用新颜色调用与上述相同的方法。

最终产品

在我的测试代码中,该方法如下所示:

var compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
var visual = compositor.CreateSpriteVisual();

visual.Size = new Vector2(83, 86);
visual.Offset = new Vector3(50, 50, 0);

_imageLoader = ImageLoaderFactory.CreateImageLoader(compositor);

var surface = _imageLoader.LoadImageFromUri(new Uri("ms-appx:///Assets/Images/HAvng.png"));
var brush = compositor.CreateSurfaceBrush(surface);

IGraphicsEffect graphicsEffect = new CompositeEffect
{
    Mode = Microsoft.Graphics.Canvas.CanvasComposite.DestinationIn,
    Sources =
    {
        new ColorSourceEffect
        {
            Name = "colorSource",
            Color = Color.FromArgb(255, 255, 255, 255)
        },
        new CompositionEffectSourceParameter("mask")
    }
};

_effectFactory = compositor.CreateEffectFactory(graphicsEffect, new string[] { "colorSource.Color" });
var effectBrush = _effectFactory.CreateBrush();

effectBrush.SetSourceParameter("mask", brush);

visual.Brush = effectBrush;

effectBrush.Properties.InsertColor("colorSource.Color", Colors.Red);

ElementCompositionPreview.SetElementChildVisual(this, visual);
Run Code Online (Sandbox Code Playgroud)

请注意,在此示例中,视觉内容已附加到this,这是我的MainPage。您可以将其附加到任何XAML元素。如果您想查看一个可在XAML标记中定义的自定义控件的示例,该自定义控件可在创建该控件并在调整控件的大小时调整其视觉效果,请在此处找到。

要查看更多与组合有关的内容,请转到我们的GitHub页面!我们很乐意为您解决有关API的任何问题。