Reverse Antialiasing for Image Scaling

When enlarging screen images, for example using screen magnifier utilities such as KDE’s KMag, the antialiasing used for rendering text becomes very visible (see left image). To limit the effect, simple pixel replication is not suited, but a different scaling algorithm needs to be used. The simplest of those algorithms is the bilinear filtering method, which is quite fast, but has the disadvantage of blurring the result.

More advanced methods, such as the Mitchell filter, obtain better results, but are slower to compute and introduce new kinds of artifacts, called ringing. For more information about the kind of artifacts linear scaling methods introduce, please refer to this interpolation introduction.

Image Scaling Comparison

Several methods for non-linear image scaling were proposed, some of them especially fast, some of them optimized for pixel art, others using several megabytes of trained neuronal networks etc. There is always a trade off you have to make between the image quality, and the speed you get.

While the source code for the neuronal network-based scaler is available (as well as the trained data), it was out of scope for a simple screen magnifier, such as KMag. The algorithm should be fast (maybe the speed of a bicubic scaler), and work without additional data, so that it can be used for KMag.

Again, I was not satisfied with the methods that were previously freely available, so I developed my own version of a scaling algorithm. This time it is optimized for scaling antialiased text or rasterized vector graphics, because it effectively reverses the antialiasing process. The quality is certainly not perfect, especially when faced with thin diagonal lines, but I consider it good and fast enough to be useful in KMag. It should also be quite useful as a resolution doubler for high-resolution (“Retina”) displays, and GPU implementations should be simple.

On the right image, you can see my result, using some text and some graphics from the Oxygen team (unscaled image here). To get an impression how it looks as a screen magnifier, here is a screenshot of a Dolphin window (made by Peter Penz), and its resolution doubled version.

A description of the algorithm will follow later. Just be a bit patient, I am still learning TeX ๐Ÿ™‚

17 thoughts on “Reverse Antialiasing for Image Scaling”

  1. Wow, the scaled up dolphin screenshot is quite impressive.

    How well does it play together with the various subpixel hinting types?

  2. @ben, what do you mean? The algorithm does not handle subpixel antialiasing differently, so it can, for example, not convert between different subpixel layouts. If the original image is using a wrong layout, the scaled version will also be wrong.

  3. Yes, using LyX here, but it does not really help with TikZ graphics; you have to use inline raw TeX for that, or I did not see the obvious…

  4. Thanks, it works. I’m amazed by some results. I intend to understand the logic behind it and try to make a gpu shader some day…

  5. Nice work! Doesn’t look good as a pixel art scaler, though ๐Ÿ™‚

    Sorry, I didn’t yet have time to improve my TikZ skills, and I feel that without some graphics, it is not easy understand. I wish there was a program that converts handwritten notes/graphics to a nice document ๐Ÿ˜›

  6. No need for tex. Just write some txt with these ideas! ๐Ÿ˜›

    I’m coming here every day to see any update. ๐Ÿ˜ฆ

  7. Oh my! More than a year since it was released!

    Please, provide us an explanation about this algorithm. How did you got the formula (7*(b+c) – 3*(a+d)+8)/16?

    I’ve already tried to reach that formula, but couldnt.

  8. The way sharpening is done using these coefficients is not much different compared to other higher-order interpolation algorithms. I tried varying the coefficients, and to me these values looked best to get a relatively sharp picture. In other words, the coefficients are arbitrary, as long as they sum to 0.5, as stated in the source.

    The actual “magic” (reverse antialiasing) is accomplished by the “min(abs(2b), abs(2c))” limiting, but yes, this really ought to be explained via some graphs and linear arithmetic formulas. Sorry for lacking the time :/

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s