UWP将Colorfilter应用于BitmapImage

时间:2016-07-05 09:31:29

标签: uwp tint colorfilter

如何轻松地将ColorFilter应用于位图,图像,无论如何。在Android上,这是一个单行:myDrawable.setColorFilter(Color.GRAY, Mode.SRC_IN); 对于Windows,我只发现顶部编译样本的巨人以各种方式操纵图像。这对我的需求来说太过分了。我不想一次或类似地操纵每个像素,我只有一个带有白色图标的图像,我希望它变成绿色或者以编程方式。

3 个答案:

答案 0 :(得分:0)

您可以使用新的Composition API对任何视觉效果都相当容易 - 您可以在此处查看此代码https://github.com/Microsoft/WindowsUIDevLabs/blob/master/Demos/EffectEditor/MainPage.xaml.cs(请参阅色调/色调效果)

答案 1 :(得分:0)

花了很多时间在MSDN和S / O上闲逛之后,我拼凑了下面的课程。它没有使用WriteableBitmapEx或任何超出Microsoft已提供的库。

这个答案在技术上只有一种混合模式可用; SRC_ATOP。如果像素不透明(alpha 0),这将迭代每个像素并用指定的色调颜色替换颜色值。

正如我所看到的许多答案所述;这将是非常缓慢的,除了应用一次性色调(即在您的应用程序启动时),不推荐用于任何其他任何事情。如果颜色不会经常变化,您可能希望将结果保存到本地文件,而不是每次都应用色调。

using System;
using System.IO;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI;
using Windows.UI.Xaml.Media.Imaging;

namespace Helpers
{
    public class ImageManipulationHelper
    {

        public static async Task<WriteableBitmap> ApplyTint(Uri sourceUri, Color tintColour)
        {
            WriteableBitmap source = await GetImageFile(sourceUri);
            byte[] byteArray = null;
            using (Stream stream = source.PixelBuffer.AsStream())
            {
                long streamLength = stream.Length;
                byteArray = new byte[streamLength];
                await stream.ReadAsync(byteArray, 0, byteArray.Length);
                if (streamLength > 0)
                {
                    for (int i = 0; i < streamLength; i += 4)
                    {
                        // check the pixel is not transparent (BGRA)
                        if (byteArray[i + 3] != 0)
                        {
                            byteArray[i] = tintColour.B; // Blue
                            byteArray[i + 1] = tintColour.G;  // Green
                            byteArray[i + 2] = tintColour.R; // Red
                        }
                    }
                }   
            }
            if (byteArray != null)
            {
                WriteableBitmap destination = await PixelBufferToWriteableBitmap(byteArray, source.PixelWidth, source.PixelHeight);
                return destination;
            }
            return null;
        }

        private static async Task<WriteableBitmap> GetImageFile(Uri fileUri)
        {
            StorageFile imageFile = await StorageFile.GetFileFromApplicationUriAsync(fileUri);

            WriteableBitmap writeableBitmap = null;
            using (IRandomAccessStream imageStream = await imageFile.OpenReadAsync())
            {
                BitmapDecoder bitmapDecoder = await BitmapDecoder.CreateAsync(imageStream);

                BitmapTransform dummyTransform = new BitmapTransform();
                PixelDataProvider pixelDataProvider =
                   await bitmapDecoder.GetPixelDataAsync(BitmapPixelFormat.Bgra8,
                   BitmapAlphaMode.Premultiplied, dummyTransform,
                   ExifOrientationMode.RespectExifOrientation,
                   ColorManagementMode.ColorManageToSRgb);
                byte[] pixelData = pixelDataProvider.DetachPixelData();

                writeableBitmap = new WriteableBitmap(
                   (int)bitmapDecoder.OrientedPixelWidth,
                   (int)bitmapDecoder.OrientedPixelHeight);
                using (Stream pixelStream = writeableBitmap.PixelBuffer.AsStream())
                {
                    await pixelStream.WriteAsync(pixelData, 0, pixelData.Length);
                }
            }

            return writeableBitmap;
        }



        public static async Task PixelBufferToWriteableBitmap(WriteableBitmap wb, byte[] bgra)
        {
            using (Stream stream = wb.PixelBuffer.AsStream())
            {
                await stream.WriteAsync(bgra, 0, bgra.Length);
            }
        }

        public static async Task<WriteableBitmap> PixelBufferToWriteableBitmap(byte[] bgra, int width, int height)
        {
            var wb = new WriteableBitmap(width, height);
            await PixelBufferToWriteableBitmap(wb, bgra);
            return wb;
        }

    }
}

快乐编码^ _ ^

参考文献:

WriteableBitmap to byte array

Set a pixel in WriteableBitmap

How to create WriteableBitmap from BitmapImage

答案 2 :(得分:0)

尽管不是直接回答,因为您询问了BitmapImage的更一般情况,但仍然值得注意的是,很多时候您都需要使用图标来着色。如果您实际使用的是BitmapIcon,则可以随意更改其Foreground,并且可以获得与Android相同的支持。