c#之UWP透明png颜色叠加

lexus 阅读:30 2024-10-25 08:56:14 评论:0

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

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

我记得,这在 unity 中是可能的,现在我想在 uwp-app 中做到这一点。我考虑过使用 Lumia ImagingSDK或者可能是 Composition API ,但不知道,热与那些做。

请您参考如下方法:

实现此目的的一种方法是使用合成效果系统。

先决条件

  1. 目标至少是 build 10586(Composition API 在此之前是实验性的)。
  2. 虽然没有严格要求,但对视觉层有基本的了解也无妨。我写了一篇博文介绍这个主题 here .
  3. 添加 Win2D nuget 包。

此外,您可以查看我写的要点 here ,这是在 XAML 应用程序中使用 Composition API 启动和运行的快速方法。它也使用效果进行演示。不仅如此,它还包括使用 Composition API(使用我编写的包)加载图像。

入门

你会想要做一些与要点非常相似的事情,但不是定义一个 InvertEffect,你会想要同时定义一个 CompositeEffect 和一个 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") 
    } 
}; 

下一步是创建效果工厂:

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

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

var effectBrush = effectFactory.CreateBrush(); 

但是,首先您需要应用您的图像作为 mask 。您可以使用我编写的名为 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); 

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

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

然后你就完成了!请注意,如果您想在这之后更改颜色,您所要做的就是使用新颜色调用与上面相同的 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); 

请注意,在此示例中,视觉对象附加到 this,这是我的 MainPage。您可以将它附加到任何 XAML 元素。如果您想查看自定义控件的示例,您可以在 XAML 标记中定义该自定义控件,它会在您调整控件大小时创建并调整视觉对象的大小,您可以找到 here .

要查看更多与 Composition 相关的内容,请访问我们的 GitHub page !我们很乐意帮助您解决有关 API 的任何问题。


标签:C#
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号