Is that enough TLAs (Three Letter Acronyms) in the title there? I continue to mentally deny the existence of DPI (dots per inch) as a concept. It's my own fault. I have been living on PCs at 96dpi for so many years, I just stopped caring. This problem we ran into is SO obvious after the fact, but it flummoxed us for a half-hour.
I've been helping a buddy on a super-cool super secret WPF application and the window has multiple states - regular, compact, and minimized. We've got three transparent PNGs for these three buttons. The designer created them and sent them along.
However, with one of them, it kept showing up at the wrong size, and was blurry. Even if we set the width and height ourselves, it looked totally wrong.
Here's wrong:
Unrelated to the scaling issue, I saw that the file was 3099 bytes, which I thought was a little large. I opened it up in the Visual Studio binary hex editor and noticed that I could see strings like "Photoshop ICC profile" in the header. PNGs are lossless (they are like Bitmaps, not JPEGs) and while they compress, there are may ways they can compress, like removing crap from headers.
I like to run PNGOUT on all my PNGs as it'll try different techniques to make the PNG as small as possible without losing any data (without changing the way the PNG looks). I ran PNGOUT on the wrong file and it went from 3099 bytes to 292 bytes. It also just happened it look right afterwards.
Here's right:
So why did it look right suddenly? Turns out that PNGOUT also changes the DPI, without asking, to 96dpi. Here's a little C# program I wrote to test:
static void Main(string[] args){ Image i = Image.FromFile(@"c:\users\scott\desktop\collapse-wrong.png"); Console.WriteLine(i.HorizontalResolution + " " + i.VerticalResolution); Console.WriteLine(i.Width + " " + i.Height); Image i2 = Image.FromFile(@"c:\users\scott\desktop\collapse.png"); Console.WriteLine(i2.HorizontalResolution + " " + i2.VerticalResolution); Console.WriteLine(i2.Width + " " + i2.Height);}
The output of this is:
72.009 72.009 56 10 96 96 56 10
Both files are 56x10 in dimension, but the first is 72.009 dpi and the second is 96 dpi. WPF defaults to 96 dpi so when it encounters the 72 dpi image it scales it up. If you can't change the image, there are funky ways around it. Personally, I believe if you are running into this because of a designer/developer mismatch, then just coordinate between each other and decide on a DPI, probably 96. In our case, DPI didn't really matter as the designer was developing pixel-accurate images, so we just run PNGOUT on all the images.
I usually run PNGOUT from Powershell, but there is a nice free .NET app called PNGGaunlet from Ben Hollis that provides a nice GUI frontend.
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. I am a failed stand-up comic, a cornrower, and a book author.
Typical circa-2000 cathode ray tube or LCD computer displays range from 67 to 130 PPI. The IBM T220/T221 LCD monitors marketed from 2001 to 2005 reached 204 PPI. The Toshiba Portégé G900 Windows Mobile 6 Professional phone, launched in mid 2007, came with a 3" WVGA LCD having "print-quality" pixel density of 313 PPI…
Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.