Search code examples
c#win-universal-appwindows-10-universalwritablebitmap

Incorrect Byte[] from WriteableBitmap in C# UWP10


I want to get the base64 string from WriteableBitmap. I believe the byte[] to be incorrect.

Because:

The code for creating image from base64 is working. Tested this when sending base64 string from file. However i can't see anything when i'm using my function for WriteableBitmap to base64.

My attempts so far.

   public static string GetByteArrayFromImage(WriteableBitmap writeableBitmap)
        {
             Stream stream = writeableBitmap.PixelBuffer.AsStream();
             MemoryStream memoryStream = new MemoryStream();
             stream.CopyTo(memoryStream);
             Byte[] bytes = memoryStream.ToArray();
             return Convert.ToBase64String(bytes);
        }

   public static string GetByteArrayFromImage(WriteableBitmap writeableBitmap)
        {
             Byte[] bytes = writeableBitmap.PixelBuffer.ToArray();
             return Convert.ToBase64String(bytes);
        }

Test example:

   public static async Task<string> GetBase64StringFromFileAsync(StorageFile storageFile)
        {
            Stream ms = await storageFile.OpenStreamForReadAsync();
            byte[] bytes = new byte[(int)ms.Length];
            ms.Read(bytes, 0, (int)ms.Length);
            return Convert.ToBase64String(bytes);
        }

Is the byte[] in the wrong format? If so how do i correct it?

My new attempt

        Stream stream = writeableBitmap.PixelBuffer.AsStream();
        byte[] pixels = new byte[(uint)stream.Length];
        await stream.ReadAsync(pixels, 0, pixels.Length);

        using (var writeStream = new InMemoryRandomAccessStream())
        {
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, writeStream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied, (uint)writeableBitmap.PixelWidth, (uint)writeableBitmap.PixelHeight, 96, 96, pixels);
            await encoder.FlushAsync();
        }
        return Convert.ToBase64String(pixels);

This attempt doesn't change my byte[] to the correct fromat.


Solution

  • The method below creates a BitmapEncoder that operates on an InMemoryRandomAccessStream, adds a SoftwareBitmap that is created from a WriteableBitmap, reads the stream content into a byte array, and finally converts that byte array into a base64 string:

    public async Task<string> ToBase64String(WriteableBitmap writableBitmap)
    {
        using (var stream = new InMemoryRandomAccessStream())
        {
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
    
            encoder.SetSoftwareBitmap(SoftwareBitmap.CreateCopyFromBuffer(
                writableBitmap.PixelBuffer,
                BitmapPixelFormat.Bgra8,
                writableBitmap.PixelWidth,
                writableBitmap.PixelHeight));
    
            await encoder.FlushAsync();
    
            var bytes = new byte[stream.Size];
            await stream.AsStream().ReadAsync(bytes, 0, bytes.Length);
    
            return Convert.ToBase64String(bytes);
        }
    }