Sunday, 3 January 2010

New Year’s (Image) Resolution

I’ve been messing with GDI+ a bit lately.

Working with multi-page TIFF images has been both frustrating and rewarding. Once I needed to add a dynamic header to each page, I ran into the usual pitfalls with that sort of thing…

Set the encoder parameter to MultiFrame? Check.
Save the first page and then calling SaveAdd for subsequent pages? Check.
Make the images bi-tonal and using CCITT4 to reduce file size? Check.
Scale down the image slightly so next text could be written without potentially covering up a part of the faxed document? Check.

Even writing text to the image with GDI+ was (relatively) painless once I understood the basics.

One issue I kept running into, though, was that certain images (typically from fax machines) were coming out somewhat skewed. As I worked through the details of it, I discovered that the horizontal resolution was kicked up to 200-something, while the vertical resolution was only 96. I messed with this for ages and couldn’t quite figure out how to actually APPLY that knowledge in a way that would help my situation.

Quite randomly, during a discussion about thumbnail generation in SharePoint, someone mentioned an issue with aspect ratio of faxed TIFF images. Getting more details, I found out how the horizontal/vertical resolution comes into play.

Originally, I was just shrinking the image’s width/height by a certain percentage and then writing my text to the top of the image. For images with a high horizontal resolution different from the vertical, the end result didn’t look very good. Sometimes the original image seemed alright, but the text looked large and blocky. At other times, I’d end up with even the original image seeming squished or stretched. It was totally my fault, though.

When scaling down the image, what I was originally doing was something along the lines of:
newWidth = sourceWidth * scaleFactor
newHeight = sourceHeight * scaleFactor

Instead, I needed to essentially do something along the lines of:
newWidth = (sourceWidth / sourceHRes) * scaleFactor * newRes
newHeight = (sourceHeight / sourceVRes) * scaleFactor * newRes

For ‘newRes’, I went with whatever the higher value was between HRes and VRes on the source image. The result? A properly scaled image with the same aspect ratio as the original. There’s a small degradation with this, I guess, since a lot of the imaging calls using integers and some of the calculations will get rounded, but it was good enough.