Here is code to rotate an image in software:
As from this thread about it (refer there if you find any issues)
http://www.blitzbasic.com/Community/posts.php?topic=59342
Feel free to use as you wish. I used ReadPixel to read the bitmap but otherwise am writing using direct pointer access which is probably the fastest way. There might possibly be faster algorithms out there but this is pretty reasonable and runs at several frames per second on my machine. Note that a lot of the time, however, is taken to do DrawPixmap(). That command is only to let you look at what has been output and is not needed for rotating the pixmap. To test speed, take that out and call the routine a number of times checking the millisecs elapsed.
You don't need the background pixmap - it's just pasting a background image into the pixmap before drawing the rotate image on top of it.
It supports alpha blending using the alpha channel and also doubles as a zoom operation - just like the oldschool `rotozoomers`! The only thing it doesn't do is antialiasing. You could render it at twice the size to a pixmap and then do your own simple `filtering`, combining the contents of a 2x2 pixel area and average it into one destination color.
Btw in OpenGL if your screen is 32-bit with an alpha channel you CAN read the backbuffer's alpha channel, so long as when you draw the object you only use SOLIDBLEND (ie no blending or masking or alphablend) and writing to the destination alpha is enabled. I use writing to the alpha channel in my blobby-objects engine.
'Software rotation demo Strict SetGraphicsDriver(GLMax2DDriver()) Graphics 640,480,0 'Prepare pixmaps Local BackgroundPixmap:TPixmap=LoadPixmap("Background.jpg") If PixmapFormat(BackgroundPixmap)<>PF_RGBA8888 Then BackgroundPixmap=ConvertPixmap(BackgroundPixmap,PF_RGBA8888) Local SourcePixmap:TPixmap=LoadPixmap("RotoZoom.jpg") If PixmapFormat(SourcePixmap)<>PF_RGBA8888 Then SourcePixmap=ConvertPixmap(SourcePixmap,PF_RGBA8888) Local DestPixmap:TPixmap=CreatePixmap(640,480,PF_RGBA8888,4) Local SourcePixelsPerRow=PixmapPitch(SourcePixmap)/4 Local DestPixelsPerRow=PixmapPitch(DestPixmap)/4 Local OpWidth:Int=PixmapWidth(SourcePixmap) 'Width of operation Local OpHeight:Int=PixmapHeight(SourcePixmap) 'Height of operation Local OpWidth2:Int=OpWidth/2 Local OpHeight2:Int=OpHeight/2 Local XCenter:Int'=OpWidth/2 Local YCenter:Int'=OpHeight/2 'Dummy alpha values For Local aa:Int=0 To OpHeight-1 For Local bb:Int=0 To OpWidth-1 WritePixel(SourcePixmap,bb,aa,(ReadPixel(SourcePixmap,bb,aa)&$00FFFFFF)|(Int(bb*(256.0/OpWidth)) Shl 24)) 'Make alpha to see effect if image doesn't have one Next Next 'Set up variables Local PixmapWin:TPixmap=CreateStaticPixmap(PixmapPixelPtr(DestPixmap,0,0),OpWidth-1,OpHeight-1,SourcePixelsPerRow*4,PF_RGBA8888) Local Angle:Float=0 Local Magnification:Float=1.0 Local Y_UAdd:Float,Y_VAdd:Float,X_UAdd:Float,X_VAdd:Float Local Y_U:Float,Y_V:Float,X_U:Float,X_V:Float Local SourceBase:Int Ptr=Int Ptr(PixmapPixelPtr(SourcePixmap,0,0)) Local DestBase:Int Ptr Local SourcePixel:Int,DestPixel:Int Local Xpos:Int,YPos:Int Local Red:Int,Green:Int,Blue:Int Local Alpha:Float Local AlphaMask:Int=$000000FF 'Demo Repeat 'Interaction/autorotate If MouseDown(1) Then Magnification:+0.01 If MouseDown(2) Or KeyHit(KEY_SPACE) Then Magnification:-0.01 Angle:+1 If Angle>=360 Then Angle:-360 If Angle<0 Then Angle:+360 'Setup Y_UAdd=Cos(Angle+90)*Magnification Y_VAdd=Sin(Angle+90)*Magnification X_UAdd=Cos(Angle)*Magnification X_VAdd=Sin(Angle)*Magnification XCenter=MouseX() YCenter=MouseY() Y_U=-(Y_UAdd*OpHeight2)-(X_UAdd*OpWidth2) Y_V=-(Y_VAdd*OpHeight2)-(X_VAdd*OpWidth2) 'Draw it PixmapWin.Paste(BackgroundPixmap,0,0) 'Draw background DestBase=Int Ptr(PixmapPixelPtr(DestPixmap,0,0)) 'reset top left For Local Y:Int=0 To OpHeight-1 X_U=Y_U X_V=Y_V For Local X:Int=0 To OpWidth-1 XPos=XCenter+Int(X_U) YPos=YCenter+Int(X_V) If XPos>=0 And XPos<OpWidth 'clip x If YPos>0 And YPos<OpHeight 'clip y 'SourcePixel=( SourceBase + XPos + (YPos*SourcePixelsPerRow) )[0] 'Read full pixel, clipped SourcePixel=ReadPixel(SourcePixmap,Xpos,Ypos) SourcePixel=(SourcePixel Shl 8) | (SourcePixel Shr 24) 'Convert ARGB to RGBA if using ReadPixel() Alpha=(SourcePixel & AlphaMask)/256.0 Red=(SourcePixel Shr 24) * Alpha Green=((SourcePixel Shl 8) Shr 24) * Alpha Blue=((SourcePixel Shl 16) Shr 24) * Alpha Alpha=1.0-Alpha DestPixel=DestBase[X] 'Read full pixel Red:+((DestPixel Shr 24) * Alpha) Green:+(((DestPixel Shl 8) Shr 24) * Alpha) Blue:+(((DestPixel Shl 16) Shr 24) * Alpha) DestBase[X]=(Red Shl 24) | (Green Shl 16) | (Blue Shl 8) 'Plot RGBA EndIf EndIf X_U:+X_UAdd X_V:+X_VAdd Next DestBase:+DestPixelsPerRow 'next row Y_U:+Y_UAdd Y_V:+Y_VAdd Next DrawPixmap PixmapWin,0,0 Flip 1 Until KeyHit(KEY_ESCAPE)
As from this thread about it (refer there if you find any issues)
http://www.blitzbasic.com/Community/posts.php?topic=59342
Feel free to use as you wish. I used ReadPixel to read the bitmap but otherwise am writing using direct pointer access which is probably the fastest way. There might possibly be faster algorithms out there but this is pretty reasonable and runs at several frames per second on my machine. Note that a lot of the time, however, is taken to do DrawPixmap(). That command is only to let you look at what has been output and is not needed for rotating the pixmap. To test speed, take that out and call the routine a number of times checking the millisecs elapsed.
You don't need the background pixmap - it's just pasting a background image into the pixmap before drawing the rotate image on top of it.
It supports alpha blending using the alpha channel and also doubles as a zoom operation - just like the oldschool `rotozoomers`! The only thing it doesn't do is antialiasing. You could render it at twice the size to a pixmap and then do your own simple `filtering`, combining the contents of a 2x2 pixel area and average it into one destination color.
Btw in OpenGL if your screen is 32-bit with an alpha channel you CAN read the backbuffer's alpha channel, so long as when you draw the object you only use SOLIDBLEND (ie no blending or masking or alphablend) and writing to the destination alpha is enabled. I use writing to the alpha channel in my blobby-objects engine.