0

I have a grid that covers whole screen and i want to make that grid as image and then this image i want to send on server. I have used RenderTargetBitmap for this purpose and successfully make writeablebitmap to save using FileSave Picker. Image save is at normal size as expected 700kb but these bytes are too big for uploading on server. Expected bytes for 700kb image could be 200 thousand but in my situation bytes are more than 30 hundred thousand. There is definitely issue with bytes. Here is code that i use to save grid as image using file save picker.

        await bitmap.RenderAsync(testgrid);
        var pixelBuffer = await bitmap.GetPixelsAsync();
        byte[] pixels = pixelBuffer.ToArray();
        var wb = new WriteableBitmap((int)bitmap.PixelWidth, (int)bitmap.PixelHeight);
        using (stream2 = wb.PixelBuffer.AsStream())
        {
            await stream2.WriteAsync(pixels, 0, pixels.Length);            
        }
        FileSavePicker picker = new FileSavePicker();

        picker.FileTypeChoices.Add("JPG File", new List<string>() { ".jpg" });

        StorageFile file = await picker.PickSaveFileAsync();
        if (file != null)
        {
            await (wb as WriteableBitmap).SaveAsync(file);
        }   

The above code successfully save image to given location with normal size. but when i use above pixel byte array to server. Http send task cancelled exception while send request and i have detail checked on it. It is due to huge amount of Bytes array. Also if i send a very small grid of 50x50 then uploading done successfully because it has 30 thousand bytes only but image uploaded on the server is empty or corrupted.

Also i have used above converted writeablebitmap to make its bytes array using this method...

using (Stream stream = mywriteablebitmap.PixelBuffer.AsStream())
        using (MemoryStream memoryStream = new MemoryStream())
        {
            stream.CopyTo(memoryStream);
            return memoryStream.ToArray();
        }

it also returns same number of bytes Array and same error occurred from server.

Please tell me the correct way of making byte array from RenderTargetBitmap and that can easily be uploaded on server.

Shani74
  • 43
  • 8
  • You're confusing raw pixel data with an encoded image buffer. Use a [BitmapEncoder](https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmapencoder.aspx) to encode the bitmap, then transfer the encoded buffer. – Clemens Aug 10 '16 at 12:57
  • clemens could u provide some code help?? In one function i used BitmapEncoder but i got error on this line. 'var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, inMemoryRandomStream);' – Shani74 Aug 10 '16 at 13:25

2 Answers2

0

but when i use above pixel byte array to server. Http send task cancelled exception while send request and i have detail checked on it. It is due to huge amount of Bytes array.

I totally agree with Clemens,you need to encode your image before uploading it. You can use the following codes to encode your image:

private async Task<String> ToBase64(byte[] image, uint height, uint width, double dpiX = 96, double dpiY = 96)
{
    var encoded = new InMemoryRandomAccessStream();
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, encoded);
    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, height, width, dpiX, dpiY, image);
    await encoder.FlushAsync();
    encoded.Seek(0);

    var bytes = new byte[encoded.Size];
    await encoded.AsStream().ReadAsync(bytes, 0, bytes.Length);
    var base64String=Convert.ToBase64String(bytes);
    return base64String;
}

And call it in your codes:

var pixelBuffer = await bitmap.GetPixelsAsync();
byte[] pixels = pixelBuffer.ToArray();
await ToBase64(pixels, (uint)bitmap.PixelHeight, (uint)bitmap.PixelWidth);

For details about encoding Image in WinRT you can refer to Reading and Writing Base64 in the Windows Runtime.

Elvis Xia - MSFT
  • 10,801
  • 1
  • 13
  • 24
  • i have try to encode image butI am getting error on this linevar encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, encoded); – Shani74 Aug 20 '16 at 11:18
0

After lot of searching i save the renderTargetBitmap in to isolatedstorage and then access the image file from storage and make its stream byte array using this method.

 var stream = await imageStorageFile.OpenStreamForReadAsync();
        imageBytes=ReadFully(stream);

  public byte[] ReadFully(Stream input)
    {
        byte[] buffer = new byte[16 * 1024];
        using (MemoryStream ms = new MemoryStream())
        {
            int read;
            while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
            return ms.ToArray();
        }
    }

now this method works perfect.

Shani74
  • 43
  • 8