2016-03-21 85 views
2

我在我的UWP c#项目中有一个图像,那是一个带有白色前景的透明png。我现在想把这个PN​​G图像的白色变成另一种颜色(如蓝色)。UWP透明png颜色叠加

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

bubble1 bubble2

我记得,这是团结可能的,现在我想现在在UWP-应用程序做到这一点。我想过使用Lumia ImagingSDK或者Composition API,但不知道,用这两种方法做热门。

+1

当然,可以改变色调并对位图进行图像处理,但是您需要怎么做?为什么不预先生成所需的所有色彩?一个可能的答案是在这个线程:http://stackoverflow.com/questions/14364716/faster-algorithm-to-change-hue-saturation-lightness-in-a-bitmap其中与色调播放 - 但我会认真考虑需要,并根据预先加载所需颜色的速度来衡量它。 –

+0

你为什么不预先生成你需要的所有色彩?'我想要相同的图像,但颜色不同。考虑到包装尺寸和成本,我认为改变颜色的方法可能适合这一点。所以,我明白你的意思:你的方法会从ARGB转换到HSV/HSL色彩空间,并手动进行颜色处理?我希望,已经有一些MS API实现了功能。 – user3079834

+0

打开Photoshop并生成所需的所有变体 - 然后您可以将它们预加载到您的应用中,并且具有比以编程方式更改色调更快的应用程序。但是,这是一个考虑因素,您可能需要更少的内存使用量或更高的性能。我不知道你正在建立的应用程序,在这种情况下,改变色调是一种快速和整洁的方式来达到:) –

回答

4

您可以这样做的方法是使用合成效果系统。

先决条件

  1. 定位至少建立10586(该组合物是API这之前的实验)。
  2. 虽然没有严格要求,但对Visual层有基本的了解并不会造成伤害。我写了一篇博客文章,介绍了这个主题here
  3. 添加Win2D nuget包。

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

Gettings开始

你会想要做的非常相似的要点的东西,但不是定义InvertEffect,你要定义既CompositeEffectColorSourceEffect。这将做的是拍摄一张图像并将其用作“蒙版”,然后用一种颜色替换图像中的白色。您需要定义的效果是这样的:

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(); 

但是,首先你需要申请你的形象面具。您可以使用我编写的名为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

要查看更多与组成相关的东西,请进入我们的GitHub page!如果您有任何关于API的问题,我们很乐意为您提供帮助。

+0

这很好,谢谢。而不是'this',我正在使用图像。该代码创建了一个很好的红色,之前它是透明的白色,就像我想要的那样。我设置了'visual.Offset = new Vector3(0,0,0);'现在有两个问题:1.如何在旧的(原始)'Image'之前放置新元素**?使用当前代码,新图片将显示在旧图片的后面。 2.如何替换旧的(原始)'Image'? – user3079834

+0

@robmikh,是否已将此类效果添加到Composition示例应用程序?是否有一些更新的参考代码,我们可以看看如何使用Composition进行颜色替换?这段代码稍显过时,特别是使用ImageLoaderFactory。而且就像OP所说的那样,这将很适合直接应用于Image控件。 – Maximus