Search code examples
c#uwpmemorystreambitmapimage

UWP BitmapImage to Stream


I have an image that's loaded in XAML using a converter. Rather than load this image again, I want to take that image and find the dominant colour to be able to use for other graphics on the page. So far I have this:

var himage = (BitmapImage)image_home.Source;

using (var stream = await himage.OpenReadAsync())  //**can't open himage this way**
    {
      //Create a decoder for the image
         var decoder = await BitmapDecoder.CreateAsync(stream);

      //Create a transform to get a 1x1 image
         var myTransform = new BitmapTransform { ScaledHeight = 1, ScaledWidth = 1 };

      //Get the pixel provider
         var pixels = await decoder.GetPixelDataAsync(
         BitmapPixelFormat.Rgba8,
         BitmapAlphaMode.Ignore,
         myTransform,
         ExifOrientationMode.IgnoreExifOrientation,
         ColorManagementMode.DoNotColorManage);

      //Get the bytes of the 1x1 scaled image
         var bytes = pixels.DetachPixelData();

      //read the color 
         var myDominantColor = Color.FromArgb(255, bytes[0], bytes[1], bytes[2]);
   }

Obviously I can't open the BitmapImage himage using OpenReadAsync, what do I need to do there to be able to achieve this?


Solution

  • BitmapDecoder requires RandomAccessStream object to create a new instance. BitmapImage may not be directly extract as RandomAccessStream unless you know the original source. According to your comment, you are binding image Uri to the image control, so you could know the original source and you can get the RandomAccessStream from the BitmapImage's UriSource property by RandomAccessStreamReference class, you don't need load the Image again. Code as follows:

     var himage = (BitmapImage)image_home.Source;
     RandomAccessStreamReference random = RandomAccessStreamReference.CreateFromUri(himage.UriSour‌​ce);
    
     using (IRandomAccessStream stream = await random.OpenReadAsync())   
     {
         //Create a decoder for the image
         var decoder = await BitmapDecoder.CreateAsync(stream);
        ...
         //read the color 
         var myDominantColor = Color.FromArgb(255, bytes[0], bytes[1], bytes[2]);
     }