Rotating Images
datagenetics.com
datagenetics.com
http://www.cipprs.org/papers/VI/VI1986/pp077-081-Paeth-1986....
While most explanations of the algorithm follow this blog post and imply that it is a three pass algorithm, if one carefully reads Paeth's paper, one realizes that the algorithm can be implemented as a one pass algorithm.
[1] slides: http://acko.net/files/fullfrontal/fullfrontal/webglmath/onli...
[2] video: http://www.youtube.com/watch?v=GNO_CYUjMK8
A one pass Paeth algorithm produces identical results to the typical three pass implementation, because there is only one round of trigonometry up front, so there is only one round of round-off. Once the shear amounts are calculated, the rest is just integer pixel shears.
The way the algorithm works, for each pixel, the amount of shear horizontally and vertically can be calculated up front, before "moving" the pixel.
So to make a one pass algorithm, allocate a second image of sufficient size to hold the rotated original (the size of this second image can also be calculated before any pixel "movement"). Then, for each pixel, calculate its horizontal shift, followed by its vertical shift, followed by its final horizontal shift. You now have its destination coordinates, so store it into the second image buffer at the destination coordinates.
The algorithm becomes essentially:
foreach pixel source_coord do
dest_coord = transform(source_coord)
dest_image(dest_coord) = source_image(source_coord)
done
where transform()
performs the Horiz/Vert/Horz transformation of the input coordinate.Lots of good articles in that issue, and the whole thing is available on-line at the Internet Archive [2].
[1] Daniel H. H. Ingalls. The Smalltalk Graphics Kernel. BYTE 6(8), August, 1981, pp. 168--94.
[2] http://archive.org/stream/byte-magazine-1981-08/1981_08_BYTE...
And for only $600.
I was surprised to see that this software actually shipped, according to Wikipedia. [2] Alas, it was not the last piece of software that people ever needed to use, apparently.
[1] http://archive.org/stream/byte-magazine-1981-08/1981_08_BYTE...
Why not simply use Bresenham's line drawing algorithm to "draw" a reverse-rotated rectangle over your image, but rather than drawing, you'd read pixels and write them to the destination image. You'll need to only rotate the corners of the image once and everything else is simple integer math.
¹ preposterous for the kind of device where doing it any other way is too slow
Edit: replaced stars with dots for multiplication because stars make italic text
If implemented as a three pass algorithm, yes.
If implemented as a one pass algorithm, no.
Trivia: this is how Wing Commander worked. Nobody was concerned about filtering or gamma correction in those days, needless to say!
Bresenham point-sampling is an example of a 'forward transform', where you look at each pixel in the source image and decide where it goes in the destination image. You can also use conventional texture mapping to rotate an image, which is a case of an 'inverse transform' where you traverse each pixel in the destination image and figure out what texel(s) contribute to it.
Inverse transforms are much simpler -- Bresenham sampling has some ugly complexities, especially if you want to scale the image as well as rotate it -- but they aren't as efficient if the image has a lot of transparency.
If you need to rotate by 179, first rotate by 180, then by -1.
The reason the triple-sheared images look crappy is because the three shears themselves are subject to pixel aliasing. Still pretty cool.
This method is as simple to code and doesn't suffer from the missing-pixel aliasing problem of the simple method of the article, and is also capable of higher quality results than the shearing method.
In the event that the destination buffer is much larger than the source, that additional computation is trivial (it's the same calculation that's already being done for each and every pixel). As it only needs to be additionally done on the corners, not per-pixel, the additional time spent should be quite minimal.
The shearing method in the article is genuinely clever and totally cool, but I just can't shake the feeling that even on 1980s hardware, this method would be better. On modern hardware, there's no question, it's still used to this day. Nowhere near as cool, though.
as far as i can see it's replacing the interpolation in 2d with multiple interpolations in 1d. but perhaps i am missing something.
[edit] ok, after skimming the paper, it seems that they approximate the interpolation (using nearest neighbour). which makes it very fast. so really it's a neat way of working out what nearest neighbour is in 2d by doing it in 1d multiple times.
http://i.imgur.com/itniCWR.png
Left is my area mapping algorithm and right is adobe photoshop bilinear rotation.
Angle = 27°
result = 1/(cos Angle )^2 = 1.25961
which is rounded to 126%
If you express such a complex number as a 2x2 matrix (there is a unique 2x2 matrix for each complex number, such that the complex number a + ib becomes the matrix
[ a, b
-b, a ]
you'll notice that the matrix form of our unitary (magnitude 1) complex number is just a rotation matrix like the one discussed in the article.