## Image Rotation

General FreeBASIC programming questions.
axipher
Posts: 891
Joined: Dec 27, 2005 16:37
Location: Sudbury,Ontario
Contact:

### Image Rotation

Well here's what I have so far

Code: Select all

`#include "fbgfx.bi"# if __FB_LANG__ = "fb"using FB# endifconst PI = 4 * atn(1)sub multiput(xmid as integer,ymid as integer,src as any ptr,rot as double)  dim as integer sx,sy,nx,ny  dim as double ang,dist  sx = cptr(image ptr,src)->width  sy = cptr(image ptr,src)->height  for cy as double = 0 to (sy - 1) step 0.5    for cx as double = 0 to (sx - 1) step 0.5      ang = atan2(cy - (sy / 2),cx - (sx / 2))      dist = sqr(((cx - (sx / 2)) ^ 2) + ((cy - (sy / 2)) ^ 2))      nx = xmid + (cos(ang + rot) * dist)      ny = ymid + (sin(ang + rot) * dist)      pset (nx,ny),point(cx,cy,src)    next  nextend sub`

If I make the For...Next integers, the rotated image gets holes in it, but with doubles, it's damn slow with only 4 sprites. Can anyone help me?
counting_pine
Posts: 6173
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs
You won't get holes if you go the other way:
Instead of going through each pixel in the source image and working out where to Put it, go through all the (possible) pixel positions in the destination image, and work out what pixel to Put there.
for x, y in source image
work out where to put the pixel (dx, dy)
put it at (dx, dy)

Do:
for x, y in destination image
work out what pixel (if any) from the source image to put here
put it at (x, y)

It's slightly more complicated, because unless you want to check each and every pixel in the destination, you have to work out the area in the destination where pixels might get Put. It's not too hard though.

The working out bit in the loop isn't much harder either, you just reverse the transformation.
Richard
Posts: 2958
Joined: Jan 15, 2007 20:44
Location: Australia
You are using trigonometry. Better to do vector rotation which is a complex multiply. It is much faster. This will speed it up but not fill in the holes.

dim as double (all but loop counter)

To rotate by a radian angle rot, firstly
rotx = cos(rot) ' convert angle to a unity vector
roty = sin(rot)

thent get coordinates of the centre of rotation
mx = ?
my = ?

These can be precomputed before the following loop

for every point on image
x = x - mx ' translate to origin
y = y - my
nx = x*rotx - y*roty ' complex multiply
ny = x*roty + y*rotx
nx = nx + mx ' restore translation
ny = ny + my
next point

done
axipher
Posts: 891
Joined: Dec 27, 2005 16:37
Location: Sudbury,Ontario
Contact:
I tried and failed:

Code: Select all

`#include "fbgfx.bi"# if __FB_LANG__ = "fb"using FB# endifconst PI = 4 * atn(1)sub multiput(xmid as integer,ymid as integer,src as any ptr,rot as double)  dim as double rotx,roty,nx,ny,dx,dy,x,y  dim as integer sx,sy  sx = cptr(image ptr,src)->width  sy = cptr(image ptr,src)->height  rotx = cos(rot)  roty = sin(rot)  for cy as integer = 0 to (sy - 1)    for cx as integer = 0 to (sx - 1)      x = x - xmid      y = y - ymid      nx = (x * rotx) - (y * roty) + xmid      ny = (x * roty) + (y * rotx) + ymid      pset (nx,ny),point(cx,cy,src)    next  nextend sub`
Richard
Posts: 2958
Joined: Jan 15, 2007 20:44
Location: Australia
you have not assigned values of cx and cy to x and y inside the loop
D.J.Peters
Posts: 7838
Joined: May 28, 2005 3:28
' from a paper rotate.txt by Karl Lager

Code: Select all

`sub rotate(byval sx   as double,byval sy   as double, _           byval dx   as double,byval dy   as double, _           byval minx as double,byval maxx as double, _           byval miny as double,byval maxy as double, _           byval angle as double)  dim as double c=cos(angle)  dim as double s=sin(angle)  dim as uinteger col  for y as integer= miny to maxy    dim as double srcx = (minx-sx) * c + (y   -sy) * s + sx    dim as double srcy = (y   -sy) * c - (minx-sx) * s + sy    for x as integer = minx to maxx       ' test first here if srcx and srcy in image bondary       if srcx>=minx and srcx<=maxx and _          srcy>=miny and srcy<=maxy then          col=point(srcx,srcy)       else          col=0       end if       pset (x+dx,y+dy),col       srcx += c       srcy -= s    next  nextend sub'' main'screenres 640,480,32for y as integer = 0 to 127  for x as integer = 0 to 127     pset(x,y),rgb(x*x,y*y,x+y)  nextnextdim as double anglewhile inkey=""  screenlock  rotate 63.5,63.5,320-64,240-64,0,127,0,127,angle  screenunlock  angle+=0.1wendsleep`
h4tt3n
Posts: 686
Joined: Oct 22, 2005 21:12
Location: Denmark
The same thing can be done much, much faster like this...

Code: Select all

`''                        rotating algorithm''                    coded by Michael S. Nissen''                        jernmager@yahoo.dkOption Explicit Type Pixel  As Double X, Y  As Integer CEnd Type ''  dim varsDim As String X_Clicked = Chr(255)+"k"Dim as Ubyte R, G, BDim as Ushort Img_Hgt, Img_WidDim as Short Img_Lft, Img_Rgt, Img_Top, Img_Btm, X, YDim as Integer scrn_wid, scrn_hgtDim As Double Rot_X, Rot_Y, Angle, Cos_Ang, Sin_Ang, Xdist, Ydist, Rot_Fac_X, Rot_Fac_Y'ScreenInfo scrn_wid, scrn_hgtscrn_wid = 640scrn_hgt = 480screenRes scrn_wid, scrn_hgt, 32Dim As Uinteger Ptr Sptr = ScreenptrRot_X = scrn_wid\2Rot_Y = scrn_hgt\2Cos_Ang = Cos(Angle)Sin_Ang = Sin(Angle)''  dimensions of image to be rotatedImg_Wid = 256Img_Hgt = 256Img_Rgt = Img_Wid\2Img_Lft = -Img_RgtImg_Btm = Img_Hgt\2Img_Top = -Img_BtmDim Pixel(Img_Lft to Img_Rgt, Img_Top to Img_Btm) as Pixel''  draw strange geometric pattern to imageFor Y = Img_Top to Img_Btm  For X = Img_Lft to Img_Rgt    With Pixel(X, Y)      .X = Rot_X+X      .Y = Rot_Y+Y      R = Sqr((X-Img_Lft)^2+(Y-Img_Top)^2)*0.705 and Sqr((X-Img_Rgt)^2+(Y-Img_Top)^2)*0.705      G = Sqr((X-Img_RGT)^2+(Y-Img_Btm)^2)*0.705 and Sqr((X-Img_Lft)^2+(Y-Img_Btm)^2)*0.705      B = R or G      .C = RGB(R, G, B)    End With   Next XNext Y''  main program loopDo    ''  rotate left/right with leftarrow/rightarrow  If Multikey(77) Then     Angle -= 0.01    Cos_Ang = Cos(Angle)    Sin_Ang = Sin(Angle)  ElseIf Multikey(75) Then     Angle += 0.01    Cos_Ang = Cos(Angle)    Sin_Ang = Sin(Angle)  End If    ScreenLock        ''  rotate & scale    For Y = Img_Top to 0      For X = Img_Lft to -1        Xdist = Pixel(X, Y).X-Rot_X        Ydist = Pixel(X, Y).Y-Rot_Y        Rot_Fac_X = Xdist*Cos_Ang-Ydist*Sin_Ang        Rot_Fac_Y = Xdist*Sin_Ang+Ydist*Cos_Ang        If Rot_Fac_X < Img_Lft Or Rot_Fac_X > Img_Rgt Then Continue For        If Rot_Fac_Y < Img_Top Or Rot_Fac_Y > Img_Btm Then Continue For        Sptr[ (Rot_X+X) + ((Rot_Y+Y) * scrn_wid) ] = Pixel(Rot_Fac_X, Rot_Fac_Y).C        Sptr[ (Rot_X-X) + ((Rot_Y-Y) * scrn_wid) ] = Pixel(-Rot_Fac_X, -Rot_Fac_Y).C        Sptr[ (Rot_X+Y) + ((Rot_Y-X) * scrn_wid) ] = Pixel(Rot_Fac_Y, -Rot_Fac_X).C        Sptr[ (Rot_X-Y) + ((Rot_Y+X) * scrn_wid) ] = Pixel(-Rot_Fac_Y, Rot_Fac_X).C      Next X    Next Y      ScreenUnlock  Loop Until Multikey(1) or Inkey = X_Clickedend`
h4tt3n
Posts: 686
Joined: Oct 22, 2005 21:12
Location: Denmark
Rotation algorithms are fun to tamper with in themselves, but now I actually need one to rotate a .bmp file. So what's the best way to go around it?

To load the .bmp into a Dim'ed array and then manipulate it? How is this done anyway?

Or to load load the .bmp into an Imagecreate'd memory block and then manipulate it. And how would that be done?

Or something else?