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.

You are welcome. I am helpful because I am generous and I like to be of service and when somebody has a need and I know something that can help I like to share it in a teaching sort of capacity. It makes me feel good. Giving is receiving.

I have learned from the code also, you see, because by trying to teach someone something and share something you also become a student.

Truth be told I was curious to see it work as well because it was sort of where I left off with my Mildred graphics library so I was curious to see it working in Max.

I didn't originally author the code/algorithm, truth be told, ie the actual rotation part. I didn't know how to do it and had to ask some chaps on an old Amiga IRC channel who came up with the basic loops and formulas. I think I now understand it better than I did back then. I'm still a bit miffed that my SourcePixel= line only works in debug mode and not regular mode but ReadPixel() isn't too much slower and works with debug off. Maybe you can fix it.

It's really fairly simple, all you are doing is almost the same thing as a non-rotated copy of all the pixels from one pixmap to another. The only difference is that instead of finding the next pixel right to the right of the current one, you have to go up or down a bit of a slope. From what you know of using Cos() and Sin() to draw a circle, ie X=Radius*Cos(Angle) and Y=Radius*Sin(Angle), all it's doing is using this to change what would be a horizontal read into reading from a pixel that is at a given angle. Of course, to accomodate that you have to have a separate pair of X and Y variables to define the pixel, which is why it has four variables to handle the loop rather than just X and Y. The X loop which proceeds from left to right in the source image, instead of assuming that Y=whatever the Y loop currently is, has to also increment/decrement its own Y counter so that it moves on a diagonal. And the same with the Y loop, to move on a diagonal rather than straight down assuming X=0 you have to add an extra X counter to it. So you end up with an outside loop that has an X and Y counter with an adder value for each, and an inner loop that has the same. It's fairly simple really. The alphablend is pretty basic, just split the color into its components and multiply by alpha and combine with the dest components multiplied by the inverse of that alpha.

Nice thing is you can handle rectangular pixmaps. Sometimes rotozoomers used to only handle powers of 2 and would wrap around. This code could be easily enough adapted to wrap around the source texture so that the entire viewport is always full with repeated copies of the pixmap ... just add something like `XPos:Mod OpWidth` and `YPos:Mod OpHeight` just after they are set within the loop, and you'll get your pixmap repeated to fill the whole viewport.

You can also add an extra multiply to the Alpha component, with a `Fade:Float` value from 0 to 1.0, ie `Alpha:*Fade` after reading the Alpha pixel value and before multiplying the components by it. This will let you fade the source pixmap in and out like a `global alphablend` applied to the whole image that simulataneously alphablends the individual pixels based on their alpha values. But that wouldn't be a direct feature replacement for Max2D as Max2D can't do that.

Another feature you could add is very easily done - have an XMagnification and a YMagnification instead of just one mag for both. If these differ, you can stretch the image horizontally and/or vertically by different amounts at the same time as zooming and rotating. I think Max2D should have that feature, it would be easy enough to add a paramter to SetScale, but alas. :-D

The reason that it is detecting presses of the spacebar is because on the Mac with a one-button mouse you don't have a right mouse button to press ;-D

Let us know how you get on.