How to scale an image to half size through an array of bytes?

379 Views Asked by At

I found many examples about how to scale an image in Windows Forms, but at this case I'm using an array of bytes in a Windows Store application. This is the snippet code what I'm using.

// Now that you have the raw bytes, create a Image Decoder
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);

// Get the first frame from the decoder because we are picking an image
BitmapFrame frame = await decoder.GetFrameAsync(0);

// Convert the frame into pixels
PixelDataProvider pixelProvider = await frame.GetPixelDataAsync();

// Convert pixels into byte array
srcPixels = pixelProvider.DetachPixelData();
wid = (int)frame.PixelWidth;
hgt =(int)frame.PixelHeight;

// Create an in memory WriteableBitmap of the same size
bitmap = new WriteableBitmap(wid, hgt);
Stream pixelStream = bitmap.PixelBuffer.AsStream();
pixelStream.Seek(0, SeekOrigin.Begin);

// Push the pixels from the original file into the in-memory bitmap
pixelStream.Write(srcPixels, 0, (int)srcPixels.Length);
bitmap.Invalidate();

At this case, it is just creating a copy of the stream. I don't know how to manipulate the byte array to reduce it to the half width and height.

1

There are 1 best solutions below

0
On

If you look at the MSDN documentation for GetPixelDataAsync, you can see that it has an overload that allows you to specify a BitmapTransform to be applied during the operation.

So you can do this in your example code, something like this:

// decode a frame (as you do now)
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream);
BitmapFrame frame = await decoder.GetFrameAsync(0);

// calculate required scaled size
uint newWidth = frame.PixelWidth / 2;
uint newHeight = frame.PixelHeight / 2;

// convert (and resize) the frame into pixels
PixelDataProvider pixelProvider = 
    await frame.GetPixelDataAsync(
        BitmapPixelFormat.Rgba8,
        BitmapAlphaMode.Straight,
        new BitmapTransform() { ScaledWidth = newWidth, ScaledHeight = newHeight},
        ExifOrientationMode.RespectExifOrientation,
        ColorManagementMode.DoNotColorManage);

Now, you can call DetachPixelData as in your original code, but this will give you the resized image instead of the full sized image.

srcPixels = pixelProvider.DetachPixelData();

// create an in memory WriteableBitmap of the scaled size
bitmap = new WriteableBitmap(newWidth, newHeight);
Stream pixelStream = bitmap.PixelBuffer.AsStream();
pixelStream.Seek(0, SeekOrigin.Begin);

// push the pixels from the original file into the in-memory bitmap
pixelStream.Write(srcPixels, 0, (int)srcPixels.Length);
bitmap.Invalidate();