user444707
user444707

Reputation:

Windows universal app draw on WriteableBitmap

I'm trying to draw lines on a graphic which I have stored as a byte array and then save as a jpg in my windows 10 universal app.

I have a byte[] which I have converted to a bitmapimage to get the pixel size using

BitmapImage bImage;
using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream())
{
    using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0)))
    {
        writer.WriteBytes(myByteArray);
        await writer.StoreAsync();
    }

    bImage = new BitmapImage();
    bImage.SetSource(ms);
}

Then I created a writeablebitmap using

WriteableBitmap writeableBmp = BitmapFactory.New(bImage.PixelWidth, bImage.PixelHeight).FromByteArray(myByteArray);

I then draw a line on the graphic

writeableBmp.DrawLine(10, 10, 200, 10, Colors.Black);

and then save it as a jpg

var file = await ApplicationData.Current.LocalFolder.CreateFileAsync("graphic.jpg");

using (var storageStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, storageStream);
    var pixelStream = writeableBmp.PixelBuffer.AsStream();
    var pixels = new byte[pixelStream.Length];
    await pixelStream.ReadAsync(pixels, 0, pixels.Length);

    encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint)writeableBmp.PixelWidth, (uint)writeableBmp.PixelHeight, 48, 48, pixels);
    await encoder.FlushAsync();
}

unfortunately the resulting image is just a thin horizontal line of colours. The original image is lost and no black line is shown.

I am new to graphics programming and the code snippets are basically just bits and pieces i've put together from various sources.

Any help is appreciated.

Upvotes: 0

Views: 192

Answers (2)

user444707
user444707

Reputation:

Solved!

Changed:

WriteableBitmap writeableBmp = BitmapFactory.New(bImage.PixelWidth, bImage.PixelHeight).FromByteArray(myByteArray);

to:

WriteableBitmap writeableBmp = BitmapFactory.New(bImage.PixelWidth, bImage.PixelHeight).FromStream(new MemoryStream(myByteArray));

Upvotes: 0

Vincent
Vincent

Reputation: 3746

I've not found anything wrong with your encoding code. As long as you have valid raw data to create your initial WriteableBitmap, it should work.

My guess is that the error comes from the image data you are loading which are not valid. Something might be corrupted/improperly saved. You can try to display your BitmapImage and see if it loads properly. You can also use the BitmapImage.ImageFailed event for that. You can also check that you are actually retrieving some data from your stream by either checking the stream length and that if the cursor is set at position 0 before reading it.

Here is a sample code that generates a raw image and draw on it.

var width   = 35;
var height  = 35;
var imageData   = new byte[width * height * 4];
for(var i = 0; i < imageData.Length; i += 4)
{
    imageData[i]    = 255;
    imageData [i+1] = 0;
    imageData [i+2] = 0;
    imageData [i+3] = 255;
}

var image           = BitmapFactory.New(width, height).FromByteArray(imageData);        // source image data is ARGB
image.DrawLine(0,0, width -1, height -1, Colors.Red);

var file            = await ApplicationData.Current.LocalFolder.CreateFileAsync("output.jpg", CreationCollisionOption.ReplaceExisting);
var outstream       = await file.OpenAsync(FileAccessMode.ReadWrite);

var encoder         = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, outstream);
var outImageData    = image.PixelBuffer.ToArray();

encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, (uint) image.PixelWidth, (uint) image.PixelHeight, 96, 96, outImageData);
await encoder.FlushAsync();
outstream.Dispose();

Upvotes: 0

Related Questions