need to rotate a pixmap with smooth filtering

BlitzMax Forums/BlitzMax Programming/need to rotate a pixmap with smooth filtering

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

One Eyed Jack: You don't have to use my code by any means, but I was thinking about the different kinds of rotates and how you might make use of them.

There are two kinds: Either you touch every pixel in the destination viewport horizontally and vertically, and at each pixel lookup the rotated coordinates of a pixel in the source image which you copy over ... sort of a `read from` rotation. Then there is the one where you go through the source image horizontally and vertically and copy each pixel to a rotated destination coordinate, sort of a `write to` operation.

The code above is the first type where all pixels in the viewport are assessed for whether they contain valid source coordinates, and currently only draws those pixels that are within the source image, nothing outside it.

It ocurred to me that a better algorithm would be a scaline algorithm like a polygon fill routine, where you do a whole row at a time. Then it occurred to me that the above routine is very close to that. It is actually drawing horizontal scanlines.

So my idea is, for each object that you want to draw, basically give its own `rotation viewport`, the size of which is a bounding box just large enough to contain all of its rotated pixels (and you can re-size it as it rotates). Then use the above routine to draw that pixmap rotated within that viewport. Because the whole thing fits into the viewport at the rotated angle you'll know that you can see all of it, and because it clips to only draw the source pixels whose coordinates are within the source pixmap you'll know it's only drawing those pixels and not anything outside it. To the end user it will *LOOK LIKE* the same results you'd get from a routine that is the other way around - ie reading source data horizontally/vertically and drawing to rotated coords, except the reading and writing of the destination is horizontally/vertically aligned. I think it actually would be faster this way because you have to READ the dest buffer to do an alpha blend as well as write the final values to it, and these two accesses would be more efficient when you're going across a whole row rather than trying to splatter the screen with diagonal lines which might miss some pixels and leave holes.

Then to draw the next object you just work out the new bounding box which is your new viewport into rotation space, and call the rotation routine again with that viewport.

You might be able to optimize through some kind of math, the skipping of pixels that are outside the source pixmap when it is rotated, ie trace diagonal lines until it collides with the edge of the pixmap without having to do every pixel on the line. But otherwise I think this should be fairly quick.

The reason this demo is slow is mainly because of DrawPixmap() which is slow. I'm not sure how you're going to get around that for a software renderer unless you are opening your own display and getting direct access to video mem.

So anyway, I am not going to work on this any more, gotta get back to my game project. But good luck with it. I think filtering should be an easy addition - store the variables of the previous pixel loop for the next one and then use a combination of those pixels with the current pixel, the ratio of which is the decimal part of the coordinates and the inverse of that. [EDIT] ie, if for example the rotation routine says that the current pixel is read from 27.41,12.13, then you know take the value of that pixel and multiply it by .41, then take the value of the pixel next to it and multiply that by the inverse 1.0-.41=.59, and add them together. Do the same in Y (little bit trickier to code) where you take .13 of the current pixel and .87 of the next pixel (current pixel is the blended pixel you just worked out) and then add those together. All together you then divide by 4 (shr 2) to get the average color for each component. Something like that.

Good luck with it. Or just use some other code ;-D