Thursday, December 9, 2010

Issue with the WP7 PictureDecoder and Workaround

This is fixed in the WP 7.1 SDK /  WP 7.5 / Mango!
I noticed a strange behavior of the Windows Phone PictureDecoder DecodeJpeg method while I was working on my Pictures Lab app.
This short post describes the issue I encountered and also provides a workaround.
The built-in DecodeJpeg method decodes a JPEG image stream into a WriteableBitmap. The method has two overloads, where the first only takes the JPEG stream and the second also uses parameters for the maximum width and height of the output. I encountered a strange behavior of the latter method.

Issue
The DecodeJpeg method with 3 parameters swaps the width and the height parameters when a landscape photo should be resized. For example, an image with the original size of 3264 x 2448 should be decoded to a WriteableBitmap and resized to 1024 x 768. But the resulting output will have a size of 768 x 576 cause the method swapped the input parameters while preserving the correct aspect ratio.
Please note that this only happens with landscape pictures, which means the width of the image is greater than the height.

Will it get fixed?
Yes! I contacted Microsoft and they confirmed this issue and said that it will get fixed in a future version of the Windows Phone Silverlight runtime.

Workaround
Isolating the cause of this strange behavior took a bit of time, fortunately the easier was the obvious workaround.

int w = desiredOutputWidth;
int h = desiredOutputHeight;

// Workaround for issue in DecodeJpeg method:
// Swap width and height for landscape pictures.
if (originalWidth > originalHeight)
{
   w ^= h;
   h ^= w;
   w ^= h;
}
var writeableBitmap = PictureDecoder.DecodeJpeg(jpegStream, w, h);
The code tests if the original width is greater than the height and then swaps the output width and height using the good old XOR swap trick.
Alternatively you can avoid the DecodeJpeg overload with the resizing functionality, decode the full sized image and use the WriteableBitmapEx Resize method afterwards. It produces similar results when bilinear interpolation is used, but it's an extra step that costs resources.

The above photo was taken with a HTC Mozart and edited with Pictures Lab (cropped, rotated and 1989 vintage effect).

2 comments:

  1. I am the first time on this site and am really enthusiastic about and so many good articles.
    Best regards !

    ReplyDelete
  2. Nice way to swap values, it's so few people who knows that ;)

    ReplyDelete