Search code examples
c#bitmaparmwin-universal-appintptr

Alternative of Bitmap (System.Drawing) in Windows Universal Application


I am developing a Windows Universal Application that will be running on ARM Architecture(RaspberryPi 3, OS: Windows IoT).

The problem i am facing is that UWP doesn't allow a lot of standard .Net libraries like "System.Drawing"

I currently have an IntPtr which contains the raw data for an image and i need to use it as Bitmap which of course is not possible in this scenario. Is there any possible alternative for it.

I have looked for BitmapImage but didn't found any solution to it.

I have also tried Converting the IntPtr to Byte[] but then Converting array to Image or BitmapImage is not Possible in UWP.

Please Go Easy on me as i am newbie on C# Programming.

All I want is any Type of Bitmap or Image from an IntPtr

Thanks in Advance!


Solution

  • To conver the IntPtr to Byte[], we can use the Marshal.Copy method. It copies data from a one-dimensional, managed 8-bit unsigned integer array to an unmanaged memory pointer.

    Then we can use the WriteableBitmap class to set the Byte[] to WriteableBitmap.

    The image source data of a WriteableBitmap is an underlying pixel buffer. PixelBuffer cannot be written to directly, however, you can use language-specific techniques to access the buffer and change its contents.

    To access the pixel content from C# or Microsoft Visual Basic, you can use the AsStream extension method to access the underlying buffer as a stream.

    For more info, refer Remarks of the WriteableBitmap.

    To Convert the WriteableBitmap to BitmapImage, we should be able to encode the stream from WriteableBitmap.

    For example:

    private byte[] managedArray;
    
    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        Windows.Storage.Streams.IRandomAccessStream random = await Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/sunset.jpg")).OpenReadAsync();
        Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(random);
        Windows.Graphics.Imaging.PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
        byte[] buffer = pixelData.DetachPixelData();
        unsafe
        {
            fixed (byte* p = buffer)
            {
                IntPtr ptr = (IntPtr)p;
                managedArray = new byte[buffer.Length];
                Marshal.Copy(ptr, managedArray, 0, buffer.Length);
            }
        }
        WriteableBitmap bitmap = new WriteableBitmap((int)decoder.PixelWidth, (int)decoder.PixelHeight);
        await bitmap.PixelBuffer.AsStream().WriteAsync(managedArray, 0, managedArray.Length);
        InMemoryRandomAccessStream inMemoryRandomAccessStream = new InMemoryRandomAccessStream();
        BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, inMemoryRandomAccessStream);
        Stream pixelStream = bitmap.PixelBuffer.AsStream();
        byte[] pixels = new byte[pixelStream.Length];
        await pixelStream.ReadAsync(pixels, 0, pixels.Length);
        encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)bitmap.PixelWidth, (uint)bitmap.PixelHeight, 96.0, 96.0, pixels);
        await encoder.FlushAsync();
        BitmapImage bitmapImage = new BitmapImage();
        bitmapImage.SetSource(inMemoryRandomAccessStream);
        MyImage.Source = bitmapImage;
    }