This is the bug I was reminded of, which caused me to decide it was time to start a blog. Two years ago, I wrote my first WPF project. Basically, it's a program that gives you access to high quality images, which you can zoom in on, etc. Now, because of issues with WPF memory management ( which I'll cover at a later date ), we decided to save memory, by loading images as requested, then resizing them to the size of the screen. We'd reload at a bigger size if the user zoomed. What we found was, some of our images would become distorted sometimes when we zoomed ( which involved reloading the image at a new size ). WPF has a control for scaling images, however, it keeps the full size image in memory, making it useless for our purpose ( it just wasn't what it was for ). So, we resize the image the way the docs tell you to. Something like this:
fullHeight = bi.PixelHeight;
fullWidth = bi.PixelWidth;
bi = new BitmapImage();
bi.DecodePixelHeight = (int)Math.Min(height, fullHeight);
bi.DecodePixelWidth = (int)Math.Min(width, fullWidth);
bi.StreamSource = new MemoryStream(fileBuffer);
As I said, this worked sometimes, and others, would destroy the image. We have illustrations in the program which are PNGs, and photos which are JPEGs. I am not sure if it was the photographic content, or the JPEG format that made the latter ones get distorted, but I have a feeling we changed some images to PNG and that helped, so I'd say that I believe it's the format that is the issue. In any case, it would only happen sometimes, but by experimenting, I proved that the issue was that it would only happen for certain sizes of image, that is, the same image would consistently break, if you found a new size that would break it.
I created a sample app and sent to Microsoft, it produces the following output:
As compared to my original image, which looked like this:
It actually took me three emails back and forth of 'I don't see a problem', before the Microsoft guy accepted that image 1 does NOT look like image 2. This seemed to me to be a pretty major bug, and it was duly reported and went on the pile. Two years later, I run the latest version of WPF and .NET ( 3.5 SP1 ), and my program still destroys this image, which is how I got that screenshot.
The only solution I could find, was to revert to GDI+ to do my image resizing. So, our application does something like this every time we load an image:
int scaledWidth = (int)Math.Round(fullWidth * scale);
int scaledHeight = (int)Math.Round(fullHeight * scale);
System.Drawing.Size newSize = new System.Drawing.Size(scaledWidth, (int)height);
using (System.Drawing.Bitmap bp = new System.Drawing.Bitmap(img, newSize))
using (MemoryStream ms2 = new MemoryStream())
bi = new BitmapImage();
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms2;
So, GDI+ reloads the image at a new size, then saves it to a memory stream, and from there we read the stream into a WPF BitmapImage. Hardly neat, but it works, and WPF still does not.