X-Face format

X-Face is an odd little graphics format, designed around 1990 as a standard way to include your picture/icon/avatar in the email messages you send. It’s not exactly a file format; it’s a special string of text that can be included in email headers.

A number of email applications supported it, and maybe some still do. But all the software I’ve seen is based on the same C source code: the original compface software by James Ashton. I haven’t found any technical documentation about the format, and I suspect none was ever written.

While the images it encodes are primitive (48×48 pixels, bi-level black and white), the format seems almost hilariously over-engineered. It uses arithmetic coding, which is a fairly sophisticated kind of data compression. It uses octrees, and large hardcoded prediction tables that were optimized by sampling real-world icons.

Even without data compression, an image of this type would add less than 400 bytes to an email. That’s not a lot, though I acknowledge that it’s not a trivial amount for an email header, especially in those days. So, some effort was made to reduce the size.

Implementation error?

FFmpeg is a modern multimedia processing application, and for some reason it supports X-Face format. Here’s a bit of its source code (version 4.01, libavcodec/xface.c and xface.h):

#define XFACE_WIDTH  48
#define XFACE_HEIGHT 48

    for (j = 0; j < XFACE_HEIGHT; j++) {
        for (i = 0; i < XFACE_WIDTH; i++) {
            switch (i) {
            case 1:
            case 2:
            case XFACE_WIDTH - 1:
            case XFACE_WIDTH:

It's possible that I'm missing something, but it sure looks like there's a problem here. The case XFACE_WIDTH code is unreachable, because i is always less than XFACE_WIDTH.

Here’s what I think is going on:

  • Every “case” is off by 1. This is a programming error in the original compface code, copied to all other software that supports X-Face.
  • It can’t be fixed, because that would change the format, causing existing X-Face images to be unreadable.
  • You could, however, delete the unreachable case XFACE_WIDTH code, and the data tables associated with it.
  • The consequences, presumably, are that the compression is not quite as good as it should be. It still works, but maybe the first two pixels, and the last two pixels, of each row are not predicted in the way that was intended.

I guess there’s a cautionary tale here. If you’re going to design a portable format, it really ought to have at least two independent software implementations, programmed by different people. Otherwise, the tiniest programming error can easily get baked into the format forever.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s