2
\$\begingroup\$

I have created a function that will take as a parameter a StorageFile and return a WriteableBitmap. I use this data type so that I can later encode the image into a base64 string.

My concern is with the intermediary BitmapImage that I create to get the original dimensions. Any other improvements would be welcomed as well.

Also, it should be noted that this is Windows 10 Universal code, so I am unable to use the System.Drawing libraries.

public static async Task<WriteableBitmap> ScaledWImage(StorageFile file, int maxWidth, int maxHeight)
{
    WriteableBitmap newImage;

    using (var fileStream = await file.OpenReadAsync())
    {
        var bitmap = new BitmapImage();
        bitmap.SetSource(fileStream);
        var origHeight = bitmap.PixelHeight;
        var origWidth = bitmap.PixelWidth;
        var ratioX = maxWidth / (float)origWidth;
        var ratioY = maxHeight / (float)origHeight;
        var ratio = Math.Min(ratioX, ratioY);
        var newHeight = (int)(origHeight * ratio);
        var newWidth = (int)(origWidth * ratio);

        if (ratio > 1)
        {
            newHeight = origHeight;
            newWidth = origWidth;
        }

        newImage = new WriteableBitmap(newWidth, newHeight);
        fileStream.Seek(0);
        var decoder = await BitmapDecoder.CreateAsync(fileStream);

        // Scale image to appropriate size 
        var transform = new BitmapTransform()
        {
            ScaledWidth = Convert.ToUInt32(newImage.PixelWidth),
            ScaledHeight = Convert.ToUInt32(newImage.PixelHeight)
        };
        var pixelData = await decoder.GetPixelDataAsync(
            BitmapPixelFormat.Bgra8, // WriteableBitmap uses BGRA format 
            BitmapAlphaMode.Straight,
            transform,
            ExifOrientationMode.IgnoreExifOrientation, // This sample ignores Exif orientation 
            ColorManagementMode.DoNotColorManage
        );

        // An array containing the decoded image data, which could be modified before being displayed 
        var sourcePixels = pixelData.DetachPixelData();

        // Open a stream to copy the image contents to the WriteableBitmap's pixel buffer 
        using (var stream = newImage.PixelBuffer.AsStream())
        {
            await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length);
        }
    }

    return newImage;
}

This code is adapted from a Microsoft sample found here.

\$\endgroup\$
4
\$\begingroup\$

If you're still looking for a way how to find out the dimensions of a StorageFile image, there is an easy way to do that. I am using it in uwp as well.

I guess it would be less expensive than creation of a new BitmapImage.

        StorageFile image;
        ImageProperties properties = await image.Properties.GetImagePropertiesAsync();
        int height = (int)properties.Height;
        int width = (int)properties.Width;

As well I have this one method which I am using couple of places:

        private async Task<WriteableBitmap> StorageFileToWbmp(StorageFile file)
              {
        ImageProperties props = await file.Properties.GetImagePropertiesAsync();
        WriteableBitmap bitmap = new WriteableBitmap((int) props.Width, (int) props.Height);
        await bitmap.SetSourceAsync(await file.OpenReadAsync());
        return bitmap;
              }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.