为BitmapImage应用颜色滤镜



如何轻松地将ColorFilter应用于位图,图像等。在Android上,这是一行代码:myDrawable.setColorFilter(Color.GRAY, Mode.SRC_IN);对于Windows,我只找到了giant over top编译的样本来以各种方式处理图像。这对我来说太多了。我不想一次操作每个像素或类似的,我只是有一个白色图标的图像,我想把它变成绿色或其他编程

你可以使用新的合成api很容易地做到这一点,任何视觉-你可以看到这里的代码https://github.com/Microsoft/WindowsUIDevLabs/blob/master/Demos/EffectEditor/MainPage.xaml.cs(见色彩/色相效果)

在MSDN和S/O上花了很多时间之后,我拼凑了下面的类。它不使用WriteableBitmapEx或任何超出微软已经提供的库。

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

正如我看到的许多答案所指出的那样;这将是相当缓慢的,不建议使用一次性色调(例如,在你的应用程序启动时)。如果颜色不会频繁变化,您可能希望将结果保存到本地文件,而不是每次都应用色彩。

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 ^_^

引用:

WriteableBitmap到字节数组

设置WriteableBitmap中的像素

如何从BitmapImage创建WriteableBitmap

虽然不是直接的答案,因为您问的是BitmapImage的更一般的情况,但仍然值得注意的是,很多时候您需要使用图标进行这样的着色。如果你实际使用的是BitmapIcon,你可以自由地改变它的Foreground,你会得到同样的支持,你发现在Android。

最新更新