1

I'm trying to learn how to interact with the some of the WinRT (Metro) objects for images. Basically, I'm working towards creating a "GetPixel" and "SetPixel" method that's easy to use (similiar to what's in System.Drawing.Bitmap that can't be used in Metro apps).

For testing, I created a "Bitmap" class. It loads based off of a IRandomAccessStream that I get from the Metro file picker control. I'm able to load the pixel data into a Byte array and then create a BitmapImage from it that renders correctly on a XAML form when I toss it into an Image control.

Here's my issue, I can look at the byte array and see the individual ARGB values, but, it has far less pixels than it should. For example, the image I'm loading is 254x197 pixels (254*197*4=200,152). When I load my Byte array though with the below code, it's only got 16,382 bytes (which also doesn't equally divide by 4). I assume, this is compressed?.. I dunno.

My question is, what am I doing wrong.. I would like to return the 200,152 bytes representing the 50,038 pixels that I should have so I can create GetPixel(x,y) and a SetPixel(x,y,Color) methods.

Public Class Bitmap

    Public Sub New()

    End Sub

    Public Async Function Load(s As Windows.Storage.Streams.IRandomAccessStream) As Task
        Dim dr As New DataReader(s.GetInputStreamAt(0))
        Await dr.LoadAsync(s.Size)
        Me.Pixels = New Byte(s.Size - 1) {}
        dr.ReadBytes(Me.Pixels)

        ' We're going to get the height and the width of the image this way. ;)
        Dim bi As New BitmapImage
        Dim stream As New MemoryStream(Me.Pixels)
        bi.SetSource(New RandomStream(stream))
        Me.Width = bi.PixelWidth
        Me.Height = bi.PixelHeight
    End Function

    Public Function ToBitmapImage() As BitmapImage
        Dim bi As New BitmapImage
        Dim stream As New MemoryStream(Me.Pixels)
        bi.SetSource(New RandomStream(stream))
        Return bi
    End Function

    Public Property Pixels As Byte()
    Public Property Width As Integer = 0
    Public Property Height As Integer = 0

End Class
Kate Gregory
  • 18,808
  • 8
  • 56
  • 85
b.pell
  • 3,873
  • 2
  • 28
  • 39
  • One comment.. the RandomStream is a class that implements IRandomAccessStream and converts a Stream into it. – b.pell Apr 16 '12 at 20:16
  • You need to learn about the JPEG or PNG file formats. – SLaks Apr 16 '12 at 20:18
  • What should I search for to learn this? I assume that means I need to convert the compressed JPEG/PNG into a raw pixel format? Do you have any direction.. my searches for this with WinRT are coming up slim (I maybe using the wrong keywords)? Is there something in WinRT to handle this? – b.pell Apr 16 '12 at 20:22
  • You can read the Wikipedia articles. However, you should not re-invent the wheel; there should be spme way to read the decoded `BitmapImage` in WinRT. – SLaks Apr 16 '12 at 20:27
  • That's what I'm searching for but haven't found yet. – b.pell Apr 16 '12 at 23:34

1 Answers1

6

I have a WinRT version of the WriteableBitmapEx project here that does what you are looking for. Basically you need to load the image into a WriteableBitmap, then access its pixel buffer by calling PixelBuffer.AsStream(). Then you need to seek the stream to the x,y position (y * bmp.PixelWidth + x) to be able to read the pixel value. Then also convert the 4 bytes you get to the pixel format that works for you.

EDIT*

WriteableBitmapEx does natively support WinRT now.

Filip Skakun
  • 31,624
  • 6
  • 74
  • 100
  • Excellent. :) I was looking for WinRT ports of this. I'm going to go take a look at this and then I'll be back to mark the answer. :) Much appreciated! – b.pell Apr 17 '12 at 00:17
  • Yes, I wanted to help René with the port to WinRT, but I seem to have based my code on an older version of WBX and I never found the time to rebase it on the latest version and get it checked in. – Filip Skakun Apr 17 '12 at 21:08