Roll your own image inclusion utility.
As an old-school tech guy, I can appreciate all the shiny new widgets we have on our computer applications, but I still usually prefer a command line and being able to fine-tune exactly what's produced rather than just hope it'll work. This is particularly true when it comes to HTML generators and Web page creation tools.
You need only look at the output of Microsoft Word's “Save as HTML” feature to know what I mean. (All right, that's not a fair comparison because it's so bloody ghastly that even the Microsoft people avoid using Word for this purpose.)
It's fair to call me a prolific writer too, and much of what I write is for the on-line world. This gives me the chance to compare different tools, and since I'm <cough> a bit of a perfectionist <cough>, it also lets me see which content creation tools allow fine-tuning and which trap you in the world their developers have created.
In particular, I'm thinking of WordPress, a super-popular open-source blogging utility, versus Movable Type, a more closed development tool that is unfortunately a bit in limbo due to a change in corporate ownership. My main blog, Ask Dave Taylor.com, operates on Movable Type (as does the Huffington Post, among others), whereas the film reviews I write for ScienceFiction.com come through its WordPress system.
WordPress makes it complicated to add images to your articles, and when it does, I find that I invariably switch into the HTML source and tweak the code produced. If nothing else, there's always insufficient padding between the image and the text adjacent, which is something I often puzzle about—how I can be the only person who notices?
Movable Type could have the same issues, but because it doesn't have such a fancy HTML edit widget, it instead has encouraged me to roll my own image inclusion utility, and that's what we're going to examine this month.
The purpose of the utility is to take an image, either in GIF, JPEG or PNG format, calculate its size and produce the HTML necessary to have it properly included in a blog post. To make it more useful, it can automatically scale the image dimensions in the HTML, add image borders if needed and even add captions as specified. Here's a simple example of it at work:
$ scale 1 ../Desktop/test-image.png <center><img src="http://www.askdavetaylor.com/blog-pics/ ↪test-image.png" alt="test image" border="0" width="256" height="384" /></center>
It has lots of smarts, including the knowledge to convert the local image into an equivalent URL that instead references the archive layout on my server, calculates height and width, and even includes an ALT attribute (which is good SEO juju) based on the name of the file.
The 1 in the command invocation says that I want the image to be at its full size (scale=100%). To make it smaller, say 75%, I could invoke it as scale 0.75, and if I wanted to constrain it by a specific pixel width, perhaps because of a page layout issue, I can do that too with scale 200.
The two most important lines in the script are those that invoke the terrific ImageMagick command-line utility identify and parse the image dimensions:
width="$(identify $filename | cut -f3 -d\ | cut -f1 -dx)" height="$(identify $filename | cut -f3 -d\ | cut -f2 -dx)"
Extract a multiplier based on the starting parameter, and it's then straightforward to use bc and get the new dimensions:
width="$(echo "$width * $multiplier" | bc | cut -d. -f1)" height="$(echo "$height * $multiplier" | bc | cut -d. -f1)"
To understand this, imagine we're using the original image with its 256x384 dimensions. If we constrain it to a max of 200 pixels in width, the multiplier can be calculated as:
multiplier="0$(echo "scale=2 ; $maxwidth / $width" | bc)"
Or, if we want to do the math ourselves, 200/256 = 0.78. Calculate both dimensions by that figure and we arrive at the scaled-down image size of 200x300.
If the user specifies a percentile multiplier, say 0.75 for a 25% reduction in image size, then the math is even easier because, we don't have to calculate the multiplier. It already has been specified by the user: 0.75. The resultant image: 192x288. Not rocket science, but darn helpful.
The problem that creeps up here is one that's tied more to search engine optimization and so-called SERP, search engine results placement. In a nutshell, slow-loading pages now are penalized in the search results, and if you're loading up lots of large images and then automatically scaling them down with the attributes in your HTML code, you're hurting your page and its ability to rank well in user searches—not good.
If it's a 10% shrinkage or you're just shaving off a few pixels to make it fit a particular page design (for example, I keep my images to 500 pixels or narrower on my DaveOnFilm.com site), no worries. At that point, the difference in file size is usually negligible.
This brings us to another important task that scale.sh performs: testing and warning if you're going to be scaling an image down to the point where you can experience an SERP penalty. Here's how that's calculated:
sizediff=$(echo "scale=3; ( $width / $owidth ) * 100" | bc | cut -d. -f1)
owidth is the original width, so in the case where we constrained the image to 200 pixels, we'd have the mathematical formula:
sizediff=( 200 / 256) * 100
The cut -d. -f1 is the equivalent of the “floor” mathematical function; it just converts a float back into an integer.
Do the math, and sizediff = 78. That sounds right based on what we calculated earlier with the multiplier. I've set an arbitrary limit so that anything that's more than a 20% reduction in size is worthy of generating a warning message, like this:
if [ $sizediff -lt 80 ] ; then echo "*** Warning: $filename scaled to $sizediff%" echo "" fi
Sure enough, if we run scale.sh with the 200-pixel width constraint, here's what we see:
*** Warning: ../Desktop/test-image.png scaled to 77%
In my next article, I'll dig farther into the script and describe some of the tricks I'm using to generate the best, smartest HTML code I can manage. In the meantime, think about how you are adding images to your own on-line content and whether your method is optimized for both the user experience and the search engines.