[cairo] Re: fix pixel offsets in rotated image sources
Bill Spitzak
spitzak at d2.com
Fri Sep 16 17:53:52 PDT 2005
Bertram Felgenhauer wrote:
> It does not. The filters implemented in pixman (and the Xserver, too)
> look like this right now for a single pixel:
>
> Nearest: Bilinear:
> ^ ^
> | |
> 1|----+ 1 +
> | | /|\
> | | / | \
> | | / | \
> | | / | \
> --+----|----+---- --+----|----+--
> -1 0 1 -1 0 1
>
> In a way, nearest filtering already samples at the center of the pixel,
> because it truncates the coordinates. Bilinear filtering needs an
> additional adjustment.
You are right, "nearest" is really doing a "floor" operation to figure
out the pixel to sample. I thought it was rounding to the nearest
integer, which would center the rectangle you drew around zero.
The matrix must still be manipulated as it still is assuming the
integers in the output surface are in the centers of the pixels. I found
that the following code adjusts the matrix correctly for the nearest filter:
xtransform.matrix[0][2] +=
(xtransform.matrix[0][0]+xtransform.matrix[0][1]/*-0x10000*/)>>1;
xtransform.matrix[1][2] +=
(xtransform.matrix[1][0]+xtransform.matrix[1][1]/*-0x10000*/)>>1;
This is the same except as for the filtered case except for a difference
of .5 (the old offset is commented out here).
My opinion now is that this is definately a bug in XRender and the
"nearest" algorithim should be fixed, as it does not match what anybody
would expect "nearest" to do and makes the image shift as you change
filters. It can be fixed by adding .5 to the input image coordinate just
before you truncate it to an integer.
Since it is likely that this will break programs that are using the
nearest filter, you might as well fix the other case as well and break
everything at once. As you mention, it will actually fix programs that
did not compensate for this, which may be the majority.
>>Unfortunately /2 rounds toward zero, which is equally broken.
>
> Hmm. I'm not sure if it matters on the 1/65536 pixel/source pixel scale
> but yes, that's ugly.
It does matter when it truncates the result to the nearest integer. I
have generally found that I can *never* use /2 in any GUI position
calculations as it will always encounter negative numbers and result in
very annoying wobbly movement or misalignment of things that should
align, and always use >>1 for this.
More information about the cairo
mailing list