2016-07-05 66 views
1

如何輕鬆地將ColorFilter應用於位圖,圖像,無論如何。在Android上,這是一個單行:myDrawable.setColorFilter(Color.GRAY, Mode.SRC_IN); 對於Windows,我只發現巨大的頂級編譯樣本以各種方式操作圖像。這對我的需求太多了。我不想一次操作或類似的每個像素,我只是有一個白色圖標的圖像,我希望這成爲綠色或以編程方式。UWP將ColorFilter應用於BitmapImage

回答

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