[cairo] nearest neighborhood or bilinear interpolation

Bill Spitzak spitzak at d2.com
Mon Oct 30 10:22:48 PST 2006

Jeff Muizelaar wrote:
> On Fri, Oct 27, 2006 at 08:45:13PM -0200, Carlos Eduardo Rodrigues Diógenes wrote:
>> Hi,
>> It's possible to select what cairo will use when making scale
>> transformations in imagens (nearest neighborhood or bilinear
>> interpolation)?
> Yes.
> Have a look at the poorly documented cairo_pattern_set_filter().
> http://www.cairographics.org/manual/cairo-Patterns.html#cairo-pattern-set-filter

I'm curious about exactly the reason this is wanted. Often people who 
request this actually want a specific subset, and it would be much 
better to implement this specific subset.

1. Actual impulse filtering (often called "nearest neighbor") results in 
very poor image quality if the scale is anything other than an integer 
or if any rotation is done. I kind of doubt this is wanted by anybody, 
unless the desperately need to emulate the output of some other software.

2. However the result of impulse filtering when scaling by an integer is 
often what the programmer wants and expects, which is that each pixel 
turns into an n*n square of pixels identical to the original. At 
non-integers above a certain size many people prefer impulse filtering, 
this size depends on the viewer and the image, and is the point at which 
the difference in widths of the pixel columns and rows becomes 
unobjectionable, this can vary from 2 to 10 or so.

3. A much less common reason is that no scaling or rotation is being 
done, but the picture is being translated by a non-integer. What is 
really wanted is that the translation be rounded to the nearest integer.

I very much suspect that #2 is the real request, and that the original 
poster either does not care about, or actually does not want, the 
results when the picture is scaled by less than 2 or rotated.

Because of this I think the proper solution is to fix #2 and leave 
filtering working for other transformations, and even make this the 
default behavior of Cairo. One way is to do something I have only seen 
OS/X do, which is to ignore sampling theory and scale images up by using 
a box filter that gets smaller than 1. An equivalent would be to 
impulse-filter scale the picture up to the next larger integer and then 
filter that down to the result. Another way to look at it is that the 
image really is fully antialiased squares the size of each pixel. This 
has the advantage that not only integer scales work, but that 
non-integer scales greater than 1 blend smoothly into them. The big 
disadvantage is that no hardware renderer works this way.

#3 is a totally seperate problem. It may make sense to do that if 
antialiasing (which otherwise does not effect images) is turned off. 
Since drawing a rectangle with antialiasing off shifts the rectangle to 
the nearest integer, it may make sense to shift the translation of the 
image to the nearest integer so it remains matching. Then again this may 
be a bad idea if antialiasing is being used to seam together several 
texture-mapped rectangles.

More information about the cairo mailing list