The LoadJpeg Advantage on Windows Phone
March 17, 2012
New York, N.Y.
Windows Phone includes a class named Extensions in the System.Windows.Media.Imaging namespace that contains two extension methods for WriteableBitmap named LoadJpeg and SaveJpeg. The first one loads a JPEG from a Stream into a WriteableBitmap, and the second saves the contents of a WriteableBitmap to a Stream.
Although I was overjoyed with the SaveJpeg method and used it a few times in my book, the LoadJpeg method seemed unnecessary because BitmapSource — the parent class to BitmapImage and WriteableBitmap — defines a SetSource method that alos accepts a Stream object for creating the image, and not only that, but it works with PNG files as well!
Today I found out that LoadJpeg has a definite benefit when loading large images.
For an MSDN Magazine article to be published in the June issue, I needed to download a 3811×2099 JPEG and create either a BitmapImage or WriteableBitmap from it. I used WebClient and wrote some test code to see if the download and bitmap creation worked OK:
void OnWebClientOpenReadCompleted(object sender,
OpenReadCompletedEventArgs args)
{
if (!args.Cancelled && args.Error == null && args.Result != null)
{
BitmapImage bitmap = new BitmapImage();
bitmap.SetSource(args.Result);
Debug.WriteLine("{0} x {1}", bitmap.PixelWidth, bitmap.PixelHeight);
}
}
What printed was "1906 x 1050". BitmapImage apparently does not want to deal with large images, and so cut it down to something it felt more comfortable with, discarding 75% of the pixels.
I then tried WriteableBitmap. Surely specifying the size of the image in the WriteableBitmap constructor would guarantee success:
void OnWebClientOpenReadCompleted(object sender,
OpenReadCompletedEventArgs args)
{
if (!args.Cancelled && args.Error == null && args.Result != null)
{
WriteableBitmap bitmap = new WriteableBitmap(3811, 2099);
bitmap.SetSource(args.Result);
Debug.WriteLine("{0} x {1}", bitmap.PixelWidth, bitmap.PixelHeight);
}
}
Nope: Once again I got "1906 x 1050".
At this point, I was already considering incorporating a JPEG decoder into the program so I could split it into several images, etc, because I really wanted the high-resolution image. I had forgotten about the extension methods in Windows Phone until I glimpsed them while trying to find some documentation about image restrictions. Surely an extension method couldn't work where a builtin method failed, but it was worth a try:
void OnWebClientOpenReadCompleted(object sender,
OpenReadCompletedEventArgs args)
{
if (!args.Cancelled && args.Error == null && args.Result != null)
{
WriteableBitmap bitmap = new WriteableBitmap(3811, 2099);
bitmap.LoadJpeg(args.Result);
Debug.WriteLine("{0} x {1}", bitmap.PixelWidth, bitmap.PixelHeight);
}
}
And much to my amazement it printed "3811 x 2099"!
It's hard to imagine what the difference is between SetSource and LoadJpeg, but for now I'll just acept it.