Wednesday, 17 February 2010

Do I Look Fat In These Pixels?

As I mentioned in my A New Year’s (Image) Resolution post, I’ve had a side project that requires dealing with images that come in at varying resolutions. Regardless of resolution, though, they all have the same basic requirements. I need to be able to “stamp” the pages with a dynamic header text, the quality needs to remain high enough that they can be viewed/printed, and — ideally — I need to have the header text be relatively the same size once it’s scaled on the screen or printed.

I think I’m a little closer to where I want to be, but it’s still not quite ideal.

I have a font object that’s 10-point bold “Courier New”. I use a Generic Typographic string format with No Clip and Word Trimming. I then use the MeasureString method on my graphics object to store the string size. Once I have that, I basically just subtract the height of that object from the width and height of my target rectangle and offset my starting position of DrawImage accordingly.

What I had hoped it would do is, if writing my header required 4mm of height, I’d scale the image down enough to give me 4mm of room on both sides (to keep the same aspect ratio) and write the header text. Similarly, if the header text somehow required an inch of height, it’d scale down so there was an inch of room.

It does seem to work, but just not as good as I had hoped. On some images, the header text was very close to the original fax text (which I want). In others, though, the spacing was a bit more pronounced and I’m not quite sure why just yet.

Ideally, what I want to do next, is have a way to determine the ideal font size based on the image. If I’m dealing with a basic image at 1275×1755 (at 96dpi H-Res and 96dpi V-Res), I would need a different size font than if I was working with a 1728×1052 image (at 203dpi H-Res and 98dpi V-Res).

I just haven’t quite figured out how I’ll actually DO that… yet :)

Actually, I take that back… my true ideal solution is to toss the text on the top or bottom of the page in a spot that isn’t being used a not have to mess with the scaling at all. But that’s more of a Phase-II plan…

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.

Monday, 21 September 2009

Dear Sir/Madam: Your Website Sucks. Love, Kevin.

Sent this to Citi’s customer service department.. after yet another horrible experience while using their website to manage my credit card.

Let users choose their own security questions. And don’t put any silly limits on it (i.e. asking a pet’s name and then complaining because the name wasn’t as long as what the system thinks should be a minimum length).

The current system security questions/answers is completely asinine.

I was just prompted with a security question asking what date my youngest child was born. Are you kidding me…? I’m 28 and don’t have any kids. If I have to put some bogus information in there (that I then can’t remember, of course), how is that considered effective security?

The second security question I was prompted with asked who my arch-nemesis was in elementary school. Let me say that again just for emphasis. ARCH…. NEMESIS…. Who do you issue credit cards to, Spider Man and the members of X-Men?!?!?

Please fix this system. Offer as many pre-made questions as you like, but give the option to let us choose our own questions and answers.

–Kevin Fairchild

Tuesday, 17 March 2009

Missing Posts

As some of you may have noticed, I had to restore my blog off backups recently. Was teaching a friend of mine how to do some stuff on MySQL and I must not have isolated things well enough *shakes head* The downside of running too many sites on the same host, I’m afraid.

So I’ve lost about a year’s worth of posts. On the bright side, I haven’t updated the blog in a while thanks to a slight addiction to StackOverflow.com ;) So it actually isn’t THAT much content. Mostly just little stuff here or there.

Push comes to shove, I should have most of my screenshots and sample code stored on another system, so it won’t be that difficult if I need to recreate a few of the major posts.

Saturday, 26 April 2008

Close Enough

I was able to finally get the table structure the way I wanted it.

Since my source data is all plain text, I identify the URLs and then add in the HREF data with the url as the link text as well as the location. Add in basic tags for displaying the images I want next to the next and — BAM! — now I have a grid showing the posts/pictures for each user.

Once that was in place, I did something similar for usernames.

Last but not least, I hijacked the DocumentCompleted event of the browser control to add an OnClick event for each link… That event lets me selectively perform actions based on what I need… So clicking on a normal URL will open up a new browser window displaying what’s needed. Clicking on the image link (the user pic) performs some stuff on the client side to allow replying to that person’s post.

It’ll make a bit more sense once I post some pics…