Everything2
Near Matches
Ignore Exact
Full Text
Everything2

ClearType

created by abentley

(idea) by abentley (7.6 y) (print)   ?   (I like it!) Sat Nov 13 1999 at 9:48:49

Cleartype is a way of improving the horizontal resolution of LCD Displays by 300 percent. It starts from these observations: a pixel on an LCD monitor is composed of three sub-pixels. LCD sub-pixels have a specific physical location.

Therefore, it is possible to address sub-pixels directly. You also have to do some smoothing to correct colour fringing, which is why sub-pixel rendering looks like anti-aliasing.

(idea) by yerricde (8.7 mon) (print)   ?   (I like it!) 1 C! Thu Jan 10 2002 at 4:49:34

ClearType™ refers to Microsoft's technology that exploits the inherent misregistration in some computer display devices to draw the lines and curves of text and graphics to sub-pixel accuracy. The Apple II family had used a very similar technique two decades earlier.

Normal software treats computer displays as containing square white pixels. On the other hand, actual pixels on a color LCD are tall rectangles of red, green, and blue, and the hardware can generally address the individual components of a pixel separately. A 4x3 pixel section of a display:

+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
|R|G|B|R|G|B|R|G|B|R|G|B|
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
|R|G|B|R|G|B|R|G|B|R|G|B|
+-+-+-+-+-+-+-+-+-+-+-+-+
| | | | | | | | | | | | |
|R|G|B|R|G|B|R|G|B|R|G|B|
+-+-+-+-+-+-+-+-+-+-+-+-+

Thus, if software treats RGB as a single unit, an image of all red pixels will be offset 1/3 pixel to the left of an image of all green pixels, and an image of all blue pixels will be offset 1/3 pixel to the right.

To start, apply a low-pass filter (the 5-tap FIR filter [1 3 4 3 1]/12 works well) to the image to avoid color fringing caused by beats with the color subcarrier. Then sample alternately red, green, and blue components of successive pixels to produce a final image at nearly triple the horizontal resolution of an ordinary image.

Implementation

Patent? So what? Here's a little program I wrote to do ClearType processing on an arbitrary bitmap. Most LCDs are RGB, but some (such as Game Boy Advance and some iBook models) are BGR; you can specify the assumed pixel ordering on the command line. (The choice of RGB or BGR depends largely on endianness differences between the computer and the display hardware.) The software uses the Allegro library (http://alleg.sourceforge.net/) for bitmap file loading and saving.

/*

clearize.c
Applies a 3-to-1 horizontal scaling with color component
misregistration, similar to Microsoft's ClearType

Copyright (c) 2002 Damian Yerrick

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE

*/


#include <allegro.h>
#include <stdio.h>

typedef struct DEEP_RGB
{
  unsigned short r, g, b, a;
} DEEP_RGB;


/* ct_filter() *************************
   Filter a scanline as follows:
   1. Apply the low-pass FIR filter [1 3 4 3 1].
   2. Combine adjacent red, green, and blue samples to produce
      a final sample.
   This filter has a gain of 12x image amplitude.
*/
void ct_filter(DEEP_RGB *src, DEEP_RGB *dst, size_t width)
{
  int i, i3, c;

  for(i = 0, i3 = 0;
      i < width;
      ++i, i3 += 3)
  {
    /* do red */
    if(i == 0)
      c = 4 * src[0].r;
    else
      c = src[i3 - 2].r + 3 * src[i3 - 1].r;
    c += 4 * src[i3].r + 3 * src[i3 + 1].r + src[i3 + 2].r;
    dst[i].r = c;

    /* do green */
    if(i == 0)
      c = src[0].g;
    else
      c = src[i3 - 1].g;
    c += 3 * src[i3].g + 4 * src[i3 + 1].g + 3 * src[i3 + 2].g;
    if(i == width - 1)
      c += src[i3 + 2].g;
    else
      c += src[i3 + 3].g;
    dst[i].g = c;

    /* do blue */
    c = src[i3].b + 3 * src[i3 + 1].b + 4 * src[i3 + 2].b;
    if(i == width - 1)
      c += 4 * src[i3 + 2].b;
    else
      c += 3 * src[i3 + 3].b + src[i3 + 4].b;
    dst[i].b = c;
  }
}


const char help_text[] = 
"Performs misregistration anti-aliasing (commonly called ClearType)\n"
"with 3x horizontal reduction on an image file.\n"
"usage: clearize [options] infile outfile\n\n"
"options:\n"
"  -b            Use BGR instead of RGB\n"
"  -?            Display this help\n\n"
"infile can be *.bmp, *.pcx, *.lbm, *.tga\n"
"outfile is a 24-bit bitmap and can be *.bmp, *.pcx, *.tga\n";

int main(int argc, const char **argv)
{
  int inf_idx = -1, outf_idx = -1;
  BITMAP *in_bmp, *out_bmp;
  size_t width;
  int arg;
  char bgr = 0, need_help = 0;
  unsigned int y;
  DEEP_RGB *rgb_src, *rgb_dst;

  if(argc < 3)
  {
    fputs(help_text, stderr);
    return 1;
  }

  for(arg = 1; arg < argc; arg++)
  {
    if(argv[arg][0] == '-')
    {
      if(!strcmp(argv[arg], "-b"))
      {
        bgr = 1;
      }
      else if(!strcmp(argv[arg], "--help") ||
              !strcmp(argv[arg], "-?"))
      {
        /* -? puts help text on stdout instead of stderr */
        fputs(help_text, stdout);
        return 0;
      }
      else
      {
        /* couldn't recognize the option so print an error message
           followed by usage info */
        fputs("Unrecognized option: ", stderr);
        fputs(argv[arg], stderr);
        fputc('\n', stderr);
        need_help = 1;
        break;
      }
    }
    else
    {
      if(inf_idx == -1)
        inf_idx = arg;
      else if(outf_idx == -1)
        outf_idx = arg;
      else
      {
        /* couldn't recognize the extra arguments
           so print an error message followed by usage info */
        fputs("Too many arguments\n", stderr);
        need_help = 1;
        break;
      }
    }
  }
  if(need_help)
  {
    fputs(help_text, stderr);
    return 1;
  }

  install_allegro(SYSTEM_NONE, &errno, atexit);

  set_color_depth(24);

  in_bmp = load_bitmap(argv[inf_idx], NULL);
  if(!in_bmp)
  {
    fputs("Could not load bitmap ", stderr);
    perror(argv[inf_idx]);
    return 1;
  }

  width = in_bmp->w / 3;
  out_bmp = create_bitmap(width, in_bmp->h);
  rgb_src = malloc(width * 3 * sizeof(DEEP_RGB));
  rgb_dst = malloc(width * sizeof(DEEP_RGB));
  if(!out_bmp || !rgb_src || !rgb_dst)
  {
    perror("Could not allocate memory for bitmaps");
    destroy_bitmap(out_bmp);
    destroy_bitmap(in_bmp);
    free(rgb_src);
    free(rgb_dst);
    return 1;
  }

  for(y = 0; y < in_bmp->h; y++)
  {
    unsigned int x, x3;

    for(x = 0; x < width * 3; x++)
    {
      int c = getpixel(in_bmp, x, y);

      if(bgr)
      {
        rgb_src[x].b = getr(c);
        rgb_src[x].g = getg(c);
        rgb_src[x].r = getb(c);
      }
      else
      {
        rgb_src[x].r = getr(c);
        rgb_src[x].g = getg(c);
        rgb_src[x].b = getb(c);
      }
    }

    ct_filter(rgb_src, rgb_dst, width);
    for(x = 0; x < width; x++)
    {
      if(bgr)
        putpixel(out_bmp, x, y,
                 makecol((rgb_dst[x].b + 6) / 12,
                         (rgb_dst[x].g + 6) / 12,
                         (rgb_dst[x].r + 6) / 12));
      else
        putpixel(out_bmp, x, y,
                 makecol((rgb_dst[x].r + 6) / 12,
                         (rgb_dst[x].g + 6) / 12,
                         (rgb_dst[x].b + 6) / 12));
    }
  }

  destroy_bitmap(in_bmp);
  free(rgb_src);
  free(rgb_dst);

  if(save_bitmap(argv[outf_idx], out_bmp, NULL))
  {
    fputs("Could not save bitmap ", stderr);
    perror(argv[outf_idx]);
    destroy_bitmap(out_bmp);
    return 1;
  }
  destroy_bitmap(out_bmp);
  return 0;
}

Additional Resources

  • Sub-Pixel Font Rendering Technology (http://www.grc.com/cleartype.htm): A more thorough explanation of the technique and its history, including a freely downloadable binary demo for Windows computers.

Copyright © 2002 Damian Yerrick. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the writeup entitled "GNU Free Documentation License".


printable version
chaos

MP3s sound like shit full-scene anti-aliasing Sub-pixel anti-aliasing
God can create a stone so heavy even he can't lift it I like my coffee the way I like my women Microsoft Reader Steve Wozniak
TrueType Windows XP Grade E meat Low-pass filter
Beowulf typecast Green Acres The Hitchhiker's Guide to the Galaxy
em Uncle Xanth George W. Bush's 2004 State of the Union Address
First Day Cover George Washington's 1791 State of the Union Address puppy FireWire
Y'know, if you log in, you can write something here, or contact authors directly on the site. Create a New User if you don't already have an account.
  Epicenter
Login
Password

password reminder
register

Everything2 Help

Cool Staff Picks
Things you could have written:
Stephen Foster
My mother, a flowergirl
Born with the gift of laughter, and a sense that the world was mad
cultural anarchy
Prisoner's Dilemma
The Reformation
Galapagos Hawk
David Bohm
Benford's Law
The Second Noble Truth of Buddhism
Tell me a story about clouds
Tips for driving in the Middle East
Los Alamos National Laboratory
New Writeups
SubSane
Making Love to a 9-Foot Woman(person)
Ouzo
Thoughts(idea)
antigravpussy
I fall silent, listening. The breadcrumbs are talking about us(person)
calgon
Buffalo Bill by the pool(poetry)
gate
Anarchy is Order(idea)
ushdfgakjasgh
Scribeling(thing)
XWiz
Trism(review)
artman2003
Briefcase Full of Souls - Part I(fiction)
Dreamvirus
Alan Ladd(person)
waverider37
Harold Holt(person)
The Debutante
Until death do us part(fiction)
Ysardo
a brother to a sister(personal)
antigravpussy
your warm whispers(personal)
Clarke
Multiculturalism(idea)
aneurin
Earl of Landaff(person)
This affordable entertainment brought to you by The Everything Development Company