简体   繁体   English

UWP将Colorfilter应用于BitmapImage

[英]UWP Apply Colorfilter to BitmapImage

How can I easly apply a ColorFilter to a Bitmap, Image, whatsoever. 如何轻松地将ColorFilter应用于位图,图像,无论如何。 On Android this is a one-liner: myDrawable.setColorFilter(Color.GRAY, Mode.SRC_IN); 在Android上,这是一个单行: myDrawable.setColorFilter(Color.GRAY, Mode.SRC_IN); For Windows I only found giant over the top compilcated samples to manipulate images in every way. 对于Windows,我只发现顶部编译样本的巨人以各种方式操纵图像。 That is way too much for my needs. 这对我的需求来说太过分了。 I don't want to manipulate every pixel at once or similar, I just have a Image with a white Icon and i want that to become green or else programmatically. 我不想一次或类似地操纵每个像素,我只有一个带有白色图标的图像,我希望它变成绿色或者以编程方式。

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

After much time spent wandering around MSDN and S/O, I pieced together the following class. 花了很多时间在MSDN和S / O上游荡,我拼凑了下面的课程。 It doesn't use WriteableBitmapEx or any library beyond what is already provided by Microsoft. 它不使用WriteableBitmapEx或Microsoft已提供的任何库。

There is technically only one blend mode available with this answer; 这个答案在技术上只有一种混合模式可用; SRC_ATOP. SRC_ATOP。 This will iterate over each pixel and replace the colour value with the specified tint colour if the pixel is not transparent (alpha 0). 如果像素不透明(alpha 0),这将迭代每个像素并用指定的色调颜色替换颜色值。

As noted in many of the answers I've seen; 正如我所看到的许多答案所述; this will be quite slow and not recommended for anything other than applying a one-time tint (ie on start-up of your app). 这将是非常缓慢的,除了应用一次性色调(即应用程序的启动)时,不建议用于任何其他任何事情。 If the colour will not be changing frequently, you may wish to save the result to a local file rather than apply the tint each time. 如果颜色不会经常更改,您可能希望将结果保存到本地文件,而不是每次都应用色调。

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;
        }

    }
}

Happy Coding ^_^ 快乐编码^ _ ^

References: 参考文献:

WriteableBitmap to byte array WriteableBitmap到字节数组

Set a pixel in WriteableBitmap 在WriteableBitmap中设置一个像素

How to create WriteableBitmap from BitmapImage 如何从BitmapImage创建WriteableBitmap

Although not a direct answer because you asked about a more general case of BitmapImage , it's still worth noting that many times you need such a coloring with icons. 虽然不是直接的答案,因为您询问了BitmapImage的更一般情况,但仍然值得注意的是,很多时候您需要使用图标进行这样的着色。 If you are actually using a BitmapIcon , you are free to change its Foreground and you'll get that same support you found in Android. 如果您实际使用的是BitmapIcon ,则可以自由更改其Foreground并获得在Android中找到的相同支持。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM