« | » Main « | »

I hate browser-scaled images

Saturday 31 May 2008

When adding images to a web page, it's good practice to specify their height and width explicitly, like so:

<img src='pix/nedsimpson.png' width='372' height='375'/>

Me as a Simpson, natural size

Providing the height and width means that the img tag can be properly laid out before the image itself is loaded, so the page won't jump and wiggle as images are pulled in.

The problem is that you might have the width and height wrong. If you specify them different than the actual width and height of the image, the browser will stretch or squash the image to fit the specified size, but it may not do it well:

Me as a Simpson, reduced

Browser check: In Firefox 2 this looks pixellated, in Safari it looks nice. IE 6 and 7 are bad. Firefox 3 is still pixellated, but less so than FF2. For those with superior browsers, here's what that image looks like to the majority:

Screengrab of bad browser scaling

Sometimes, changing the shape is what you want — this is often done with 1-pixel transparent gifs, or abstract textures. But for genuine images, browser scaling is always bad. It gives the images a noisy scrunched-up look. There's a few reasons the size could be wrong:

  • They used to be right, but the artwork changed, and the tag wasn't updated
  • They are hand-coded, and the src attribute is programmatically generated
  • Simple error

Whatever the reason, it can be hard to see that these sorts of mistakes have crept into your site, especially if you are using a newer browser that does a good job scaling images.

This JavaScript function will highlight images which have been scaled in the browser:

function checkImageSizes() {
    // Find images which have width or height different than their natural
    // width or height, and give them a stark and ugly marker, as well
    // as a useful title.
    var imgs = document.getElementsByTagName("img");
    for (i = 0; i < imgs.length; i++) {
        var img = imgs[i];
        if (img.naturalWidth) {
            if ((img.naturalWidth != 1) && (img.naturalHeight != 1)) {
                // For each image with a natural width which isn't
                // a 1x1 image, check its size.
                var wrongWidth = (img.width != img.naturalWidth);
                var wrongHeight = (img.height != img.naturalHeight);
                if (wrongWidth || wrongHeight) {
                    img.style.border = "3px red dotted";
                    img.style.margin = "-3px";
                    img.style.background = "yellow";
                    img.title = "Forced to wrong size: " +
                        img.width + "x" + img.height + ", natural is " +
                        img.naturalWidth + "x" + img.naturalHeight + "!";
                }
            }
        }
    }
}

If you run this function on page load, bad images will pop out with a red and yellow dotted border. Alternately, you can run it as a Greasemonkey script: scaled_images.user.js. If you have Greasemonkey installed, clicking the link will install it, then you can use the Show Scaled Images menu pick to reveal the bad images.

Chris Pederick's Web Developer Firefox extension also provides an option to outline images with adjusted dimensions, though I find his 1-pixel red border to be too subtle.

However you find the bad ones, do yourself and your visitors a favor and be sure not to browser-scale your images.

I love RadioShack

Tuesday 27 May 2008

Yesterday, our VCR finally got dirty enough to need a head cleaning, and no amount of turning the house upside-down revealed our VCR head cleaner. (Before you chuckle at my maintaining technology as old as a VCR, I encourage you to compare the robustness and ease-of-use of VHS tapes with DVDs. My autistic son has no problem starting VHS movies, but is easily lost in the menus DVDs blithely present upon insertion. We'll get him used to DVDs eventually, but for now, we need to clean the VCR.)

I called a number of stores and examined a number of web sites: Blockbuster, Staples, CVS, Best Buy, Walgreens. None had anything that would help. Asking at each store, the clerk suggested another option I had already tried, until someone finally said RadioShack.

Sure enough, RadioShack stocks VHS head cleaners, and their web site knew that my local store had one in stock. 30 minutes later, we were cleaning the heads, and now the movies are playing again.

Last summer, when we went to Colorado, we left behind a charger, I think for a cell phone. We found a RadioShack in Crested Butte, which had the charger, no problem. This winter, when we stayed in a nice hotel in Puerto Rico, we witnessed a concierge rush into the lobby and present a well-dressed guest with a replacement phone charger. The bag she pulled it from? RadioShack.

RadioShack is not the coolest store, or the largest, or the cheapest. But it is true to its roots — they still have a section devoted to resistors and breadboards, for example. They do a great job stocking the odds and ends of technology that no one wants to shop for, but when you need them, you need them. Time and again, RadioShack is the place I go not because I am psyched to make a purchase, but because if they don't have it, I am screwed.

I don't know if that is a good niche to occupy in business. I know accessories are very profitable, so maybe it bodes well for RadioShack. They seem to be healthy, even having an iPod display in the store.

I'll try to think of RadioShack first more often. More than once they have helped me to pull my bacon out of the fire.

Rex Parker does the NYT crossword puzzle

Monday 26 May 2008

I stumbled across an unlikely blog: Rex Parker Does the NYT Crossword Puzzle. The title is not ironic. It is a daily entry by Rex Parker describing his completion of the New York Times crossword puzzle. Rex is a very serious cruciverbalist, apparently the 55th best solver in the universe, working seven to ten daily puzzles and four Sunday puzzles.

His descriptions of doing the puzzle are long and detailed, but surprisingly readable and interesting. He peppers them with illustrations of the answers, bits of trivia, opinions on the construction of the puzzle, and so on. And his blogroll points off to other crossword puzzle blogs, a gateway to an entire subculture of the blogosphere.

Ratatouille and Pixar technology

Sunday 25 May 2008

I finally saw Ratatouille the other night (having older children means not seeing it in the theaters, and having doting in-laws means the kids will first see it on a night when I am out).

I liked the movie, but not nearly as much as Finding Nemo or The Incredibles. I thought the plot was a little hard to relate to, and I didn't like the ending. It seemed mean (after a great conversion to light, Anton Ego's career is demolished and mentioned almost as an afterthought) and inexplicable (Gusteau's closes because of rats, then they open a new restaurant full of rats anyway).

As always, the look of the movie is remarkable. Most Pixar movies have a signature challenge: Monster's Inc had fur, Finding Nemo had water, The Incredibles had clothing and hair. Ratatouille has food. In each case, the goal is to model a familiar component of the real world well enough that it can add to the story telling rather than detract from it. Meeting those challenges is a huge technical achievement, and going behind the scenes to see the effort is eye-opening.

Pixar maintains an online library of technical papers explaining some of their technology. Some are single pages, others are 100-page course notes. Browsing through them, you get a sense of the obsessive details that have to be dealt with. As an unexpected example, the kitchen scenes in Ratatouille are filled with cooks chopping food. One approach would be to assign some junior animators to animate the process of slices peeling off a zucchini. Another is to procedurally model a cutting object which can deform and remodel another object. Pixar chose this last approach both for its greater fidelity, and also to free the animator to focus on the storytelling.

The papers in the library offer glimpses of the amount of work required to make a movie like this. Traditional animation required legions of artists to draw everything. CGI animation also requires enormous effort, but finely sliced into different disciplines: animators to imbue objects with life, modelers to create those objects in ways that simplify the animators' jobs, and technical staff to create the universe in which the movie takes place.

Cog 2.1 and newline detection

Saturday 24 May 2008

Since working full-time in Python, I haven't needed to use my code generator Cog much, but Alexander Belchenko has. He's prodded me to add one more feature to it, and graciously and pro-actively kept the Russian docs up to date.

The new feature is a way to get Unix line endings in the output file, even when running on Windows. When Alexander first brought this up, my inclination was to change the code so that the line ending style of the input file would determine the style of the output file. This has a certain elegance and symmetry. It would mean that a Windows file with \r\n endings could be cog'ged on Unix, and the output file would have \r\n endings.

In Python, if you open a file in 'rU' mode, it is treated as a text file, and all data is presented with \n line ending, but the file object has a newlines property which is a string or tuple of all the line ending styles seen in the file. This seemed perfect for my needs. As the output file was being written, it could examine the newlines property of the input file to determine what style endings to write. I was willing to ignore the engineer's obsessive corner case of a file with mixed line endings, and simply say that if a \r\n had been encountered in the input, the lines would be written with \r\n, otherwise, they would get \n.

Alas, this didn't quite work out. Turns out that after reading one line from a Windows file, newlines has no information in it:

>>> f = open('sample.txt', 'rU')     # open the file...
>>> f.newlines                       #  ..nothing in newlines yet
>>> f.readline()                     # read the first line...
'This is the first line\n'
>>> f.newlines                       #  ..still nothing in newlines!
>>> f.readline()                     # read the second line...
'This is the second line\n'          
>>> f.newlines                       #  ..*now* something in newlines :(
'\r\n'

As a result, my code worked great, except that the first line of output always ended with a \n, while the rest of the file followed the lead of the input file.

Fixing that would have meant re-working a lot of code to buffer everything. It would have been possible, but to gain what? The code as it stands handles the case I really care about: preserving Unix line endings when processing files on Windows. To make that happen, I only had to open the output file in binary mode, since all the internal text handling uses \n endings. Handling the opposite case, preserving Windows endings on Unix, simply wasn't important enough to warrant the effort.

In any case, thanks Alexander for moving Cog forward!

Bad web type: georgia's numerals

Thursday 22 May 2008

Typography is an ancient and fascinating subject, with many facets: artistic, historic, and technological. At the intersection of these is how technology has shaped the art over time. The design of typefaces has always been shaped both by what the technology was capable of, and what the technology required.

As new typographic technology is introduced, there's a general trend:

  • imitate the old technology,
  • discover the possibilities of the new technology,
  • develop a new set of norms,
  • restore some parts of the old technology in the new.

When Gutenberg first carved type into steel punches to make movable type, he made a number of different versions of each letter to reproduce the variation found in manuscripts. Eventually uniformity became the norm, with sophisticated variant forms later re-introduced as an advanced option.

The web is no different: type on the web is limited by HTML, by ASCII, and by browser support. For example, straight apostrophes and quotes are a compromise required by the limitations of typewriter and computer keyboards. Curly quotes are the return of previous quality, but require a little more work.

Sometimes, though, the old high-quality touches are still inappropriate. I realized one of these in the comments to yesterday's post about patch. Simon Brunning helpfully provided this snippet:

patch -p0 -i my.patch      # ABC0123456789XYZ

except that instead of the monospace code font I just used, it was in Georgia:

patch -p0 -i my.patch # abc0123456789xyz

See the problem? Georgia's numerals (or figures) are one of those advanced touches, known as old-style or lowercase figures. In the full range of type possibilities, there are a number of ways of designing figures. Old-style are like lowercase letters: they have a variety of heights, some with ascenders and some with descenders, as the Georgia sample shows. The alternative is called lining, or uppercase figures, which all extend from the baseline to the cap-height, just as uppercase letters do. The monospace font has these, as do most typefaces.

BTW: There's another way figures can vary: tabular or proportional, which doesn't affect this discussion, but for the full details, have a look at the FontFeed's OSF, LF, and TF Explained.

The problem here is that Georgia's old-style figures make it impossible to distinguish a zero and a lowercase o. Of course, with lining figures, it would be difficult to distinguish a zero and an uppercase O, and don't get me started on the whole l/1/I (ell/one/Eye) thing. Maybe the problem here is setting code samples in a proportional face in the first place.

Typographers would tell you that typefaces have to be chosen carefully for their intended use. The FontFeed article above makes clear that the choice of old-style or lining figures depends on what numbers you are setting: in running text, best to use old-style, in tables use lining. No mention of Unix commands!

So what's a web designer to do? In this case, it is especially complicated, because comments can contain any kind of content at all, with minimal markup limited by the tools, and provided by the commenter. Even if my comment form provided a <code> tag, readers would have to know to use it, and remember to use it each time they provided a code sample.

No typeface is going to be right for all uses, and the choices are limited by having to consider cross-platform browser issues. Georgia is at least one of the web-safe fonts, so I can be reasonably certain I know what my readers are seeing.

Georgia's old-style figures are a nice touch, a whiff of the high-craft past in our sterile modern times. The title of this post is a bit harsh: they aren't bad. But using them indiscriminately in web content isn't always a good thing. The best answer may be yet more technology, finding ways to guide the use of the old tools appropriately for new contexts.

How to apply patches

Wednesday 21 May 2008

Occasionally I write things here simply so that I won't forget them, here's one of them. Applying patches is something I do infrequently enough that I have to re-figure it out each time.

If you have a patch file called my.patch that looks like this (in part):

=== modified file 'cogapp/cogapp.py'
--- cogapp/cogapp.py 2005-12-04 20:27:41 +0000
+++ cogapp/cogapp.py 2008-05-21 09:00:08 +0000
@@ -37,6 +37,7 @@
                     A %s in the CMD will be filled with the filename.
     -x          Excise all the generated output without running the generator
     -z          The [[[end]]] marker can be omitted, and is assumed at eof.
+    -N          Write the output as binary file (with LF line-endings).
     -v          Print the version of cog and exit.
     -h          Print this help.
 """

then to apply the patch, cd to the directory that has cogapp in it, and use this command:

patch -p0 < my.patch

The patch command is one of those inscrutable Unix-culture tools which does not behave as I expect. In this case, there seems to be no syntax that names my.patch explicitly, only an input redirect works. And zero seems not to be the default for the -p switch, so it needs to be specified, but the help text doesn't mention the default value, so I'm not sure what it is.

Max: stop-motion for French, and Apple Boston

Saturday 17 May 2008

Two cool posts this week on my son Max's blog.

The first was a stop-motion animated movie he made as an assignment for French class with his friend Alice. It highlights the oppression of women in Algeria, and I think it is wonderful, both in its compassion and its technical skill. He made it with iStopMotion, a clever Mac tool that overlays successive frames with the current live view from the camera so that you can carefully animate your models.

On Thursday, he was at the Boston Apple store opening, getting a green monster t-shirt and special edition iPod sock. He's got lots of pictures of the event in his gallery.

Water + laptop = ok

Thursday 15 May 2008

This past weekend, someone accidentally spilled about half a cup of water onto my laptop keyboard. I actually shouted "Agghhh!" like a cartoon character, and we all burst into action, grabbing paper towels, mopping up water, moving books, etc.

When I picked up the laptop, water came dribbling out the other side of it, making a puddle on the table. It was not the kind of thing you want to see involving your laptop. The screen started flashing and going into video conniptions, so I flipped the computer over and removed both batteries.

Max searched Google for what to do, and found a page recommending opening every part you could, and blow-drying on the coolest setting. So I got a screwdriver and started opening panels. When I got the hard drive out after 20 seconds and three screws, Max (a hardcore Apple devotee) exclaimed, "Wow, you can get it out just like that!?" I was a little pleased to have at least a small advantage go to the PC.

Max also found the service manual for my model laptop, so we could get under the keyboard and other hard-to-reach places. The scary thing was that no matter where I looked, I saw droplets of water, except on the RAM.

Over the course of two hours, we blow-dried it a few times, marveled at the insides, and discovered new places to poke paper towels to get the last of the moisture out. Finally, I put it all back together, put in the batteries, and booted it up. With a sigh of relief, I saw that it was going to be fine.

Once it was all over, my computer was cleaner, and I learned something to add to my Middle-Aged Man repertoire of minor but useful knowledge.

Blu's Muto

Tuesday 13 May 2008

Blu is a street artist from Argentina. He's taken graffiti to a whole new level, creating animations on walls and sidewalks. His latest is Muto which is both a technical tour de force and an eye-opening creepy animation.

Not only did he work in the less-than-ideal environment of the sidewalk, but it meant that he couldn't have more than one frame in existence at a time, with no possibility of reworking old frames or sketching out new ones. Once the frame was shot, the work was destroyed. Amazing.

Boy vs. girl

Monday 12 May 2008

Here's a short but complicated question: if grown men object to being called "boy", why don't grown women object to being called "girl"?

I was raised in New York City in the 1970's by a radical lesbian feminist, and to my ears, "girl" is completely wrong. I'm always a little thown by hearing adults referred to as girl. It seems demeaning, but plenty of women refer to themselves that way. Am I completely out of touch? Are they?

So that happened... (digg, slashdot, and webfaction)

Tuesday 6 May 2008

Last Thursday, I posted the animated CSS Homer, and it was a big hit. Friday morning, it was popular on Digg (over 3000 diggs). The resulting Digg effect was enough for my hosting provider to shut off my site.

I was a cheapskate when I bought my hosting plan from TotalChoice Hosting, looking only for low cost. Their reaction seemed aggravatingly uninformed. The support guy kept referring to the traffic spike as "an attack". I tried to explain that it was in fact a success, and that they had failed to help me deal with that success. I could understand needing to protect their widely shared servers, but at least they could speak knowledgeably about the event.

He also called it a DDOS, which it was, but only if it stands for Distributed Desirability Of Stuff.

Further angering me was the fact that my email was unavailable, since they simply shut off my entire account. Also, there was a misconfiguration in the 403 page they were serving, so the traffic logs showed every request resulting in another request for a non-existent 403.shtml page. TotalChoice will be the first to point out that they are not the right service for a high-traffic site, but they should at least be conversant in the language of their newly disappointed customers, and know how to correctly shut off accounts.

Saturday morning, the traffic had subsided and the site was reactivated, and I figured I could spend some time researching options for a new provider. Slicehost seemed good if I wanted to go the VPS route, though sysadmin is not my interest or forte, so I was leery of taking on all the responsibility for the machine, however virtual it was.

WebFaction seemed the best choice of the shared providers, with supported Django, and many Django sites hosted.

I was away for the weekend, so I wasn't actively working on the problem. My site was up, I could now plan my next move.

At least, until I got slashdotted. Now the site was really shut down, and TotalChoice wasn't too pleased. The only way back online was with a new provider. WebFaction got the gig, because I don't need complete control over a machine. A shared account with shell access and supported Django would be great. I looked in their forum for Digg effect issues, and saw intelligent conversation. I had dropped them a line outlining my situation, and they made clear that they had dealt with it before and would work with me if such good fortune arose again, but that they would shut down sites if it was the only way to protect the shared servers. In a way, that last caveat reassured me. If they had made a blanket claim that their servers were Digg-proof, it would have smelled of naive or dishonest admins.

Monday I signed up, switched over my domains nameservers, re-uploaded my site, and I was back online. After getting TotalChoice to reactivate my old site, I transfered the blog comments, and now everything should be back as good as new.

It would have been nice to survive the Digg and Slashdotting. Maybe with WebFaction I will next time. I've got a new appreciation for slimming down the server needs of my blog. The avatars in comments are something to think about: the Homer post has 70 comments, meaning each page load also generates 70 image requests. One possibility is to offload the image to another service.

The irony in all this is that although I started with TotalChoice because of how inexpensive they were, I'm not paying much more for the WebFaction account.

NeoCube

Saturday 3 May 2008

The NeoCube is an astonishing toy made of 216 high-strength magnetic ball bearings. The movie shows an array of surprising transformations:

I'm mesmerized by the shifts from one form to another, especially when it pops from a flat net to a Platonic solid all by itself.

Seems like a fun toy to have around, except for the part where those little ball bearings could zap your disks or credit cards if they get too close...

TV and social surplus

Friday 2 May 2008

Clay Shirky has a knack for putting his finger on it. In Gin, Television, and Social Surplus (subtitled by the slug as Looking for the Mouse), he points a finger squarely, humorously, and accurately at television as a huge time sink that people don't even realize they are a part of. You should read the whole thing because it is wise and entertaining, but here's the quantitative eye-opener: he figures that all of Wikipedia represents 100 million hours of work, which is a huge amount, but that in the U.S. we watch 200 billion hours of TV each year. In other words, if we stopped watching TV, not only would we have plenty of time to create Wikipedia, we could create 2000 of them every year!

I've often had people ask me how I have the time to do whatever side project I'm working on at the moment. Then the lunch table goes back to the usual discussions: did you see the game? how about last night's episode of E.R.? Those are fine ways to spend time, but at least don't be surprised that others have found other ways. I'm not trying to sound like a Luddite (named for a fellow Ned), I like TV too. I look forward to 30 Rock like nobody's business.

But if I sit and watch for too long, I get antsy, I want to be doing something. This is Shirky's second point: that TV is a one-way medium, and that computers and the internet have shown us the power of two-way interaction.

It's a great essay — turn off the TV and go read it, then write something.

« | » Main « | »