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.

Here is the working rotozoomer. However, I had to remove my own speedier `read` of the source pixmap because in debug mode it works fine, in non-debug mode it crashes. It's something to do with maybe it's reading outside of the pixmap, but I have put a clip in place to prevent that, so I'm not sure what the bug is.

Still ... this version should work.... alphablended rotozoomer. Left mouse button zooms out, right mouse button or space bar zooms in.

'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)