 'bitmap rotate tool
 'programmed by
 'Ben Jimenez
 'Feb 2012
 'Open Source- feel free to improve
 'and repost


nomainwin
WindowWidth=800
WindowHeight=600
menu #main, "File","Open BMP",[openBMP],|,"Save",[saveBMP],|,"Exit",[exit]
menu #main, "Rotate","Angle",[angle],"Increment By",[incBy],"Width",[Width],"Height",[height],|,"Rotate!",[rotate]

open "Bitmap Rotate Tool" for graphics_nsb as #main
hWnd=hwnd(#main)
hDC=GetDC(hWnd)
#main,"trapclose [exit]"
angle=0
wait

[Width]
prompt "Enter New BMP Width: ";Width$
Width=val(Width$)
wait

[height]
prompt "Enter New BMP Height: ";Height$
Height=val(Height$)
wait

[openBMP]
if bmpHwnd<>0 then
    unloadbmp "bmp"
    #main,"cls"
end if
filedialog "open BMP","*.bmp",openBMP$
if openBMP$<>"" then
loadbmp "bmp",openBMP$
bmpHwnd=hbmp("bmp")
null=GetBMPInfo("bmp")
#main,"drawbmp bmp ";(WindowWidth/2)-(BITMAP.bmWidth.struct/2);" ";(WindowHeight/2)-(BITMAP.bmHeight.struct/2)
print #main,"up;goto 10 20;down;\Width: ";BITMAP.bmWidth.struct;" Height: ";BITMAP.bmHeight.struct
#main,"flush"
end if
wait

[saveBMP]
 filedialog "Save BMP","*.bmp",saveBMP$
 if saveBMP$<>"" then
 bmpsave "savebmp",saveBMP$
 end if
 Notice saveBMP$;" Saved."
wait
[angle]
if Width=0 or Height=0 then
notice "Please set Width and Height of new BMP"
wait
end if
 prompt "Enter Starting Angle (not greater then 360)";angle$
 sangle=val(angle$)
 #main,"cls"
 if sangle>360 or sangle<0 then sangle=0
 call rotate hDC,bmpHwnd,sangle,(WindowWidth/2)-(100/2),(WindowHeight/2)-(100/2),Width,Height,BITMAP.bmWidth.struct,BITMAP.bmHeight.struct,0
wait

[incBy]
prompt "Enter Increment Value (not greater then 360)";i$
inc=val(i$)
if inc>360 or inc<0 then inc=0
wait

[rotate]
if Width=0 or Height=0 then
notice "Please set Width and Height of new BMP"
wait
end if

#main,"cls"
xpos=0
ypos=0
angle=sangle
i=inc
t=int(360/i)
for x=1 to t
    call rotate hDC,bmpHwnd,angle,xpos,ypos,Width,Height,BITMAP.bmWidth.struct,BITMAP.bmHeight.struct,0
    angle=angle+i
    xpos=xpos+Width+5
    if xpos>700 then
        ypos=ypos+Height+5
        xpos=0
    end if
next x

'kill rotation
call rotate hDC,bHwnd,0,0,0,0,0,0,0,1  '1=kill rotation
if bmpflag=1 then
unloadbmp "savebmp"
bmpflag=0
end if
#main,"getbmp savebmp 0 0 ";WindowWidth-35;" ";WindowHeight-75
#main,"drawbmp savebmp 0 0"
#main,"flush"
bmpflag=1
wait

[exit]
close #main
end


'subs------------------------------------------------------------------------------

sub rotate hDC,bHwnd,angle,xPos,yPos,w,h,bwidth,bheight,k


   if tempDCs=0 then
        sourceDC=CreateCompatibleDC(hDC)
        destDC=CreateCompatibleDC(hDC)
        tempDCs=1
   end if

   if k=1 then
        null=DeleteDC(sourcDC)
        null=DeleteDC(destDC)
        tempDCs=0
   end if

   if k=0 then

   pi=3.14159265 'constant
   radians=(2*pi*angle)/360 'convert to radians
   cosine=cos(radians) 'asign values
   sine=sin(radians)   'asign values


   newBitmap=CreateCompatibleBitmap(hDC,w,h)'make new bmp image
   hbmOldDest=SelectObject(destDC,newBitmap)'new bmp into destDC
   hbmOldSource=SelectObject(sourceDC,bHwnd)'bitmap into source

   null=SetGraphicsMode(destDC,2)'set to rotate

   struct xform,eM11 as ulong,eM12 as ulong,eM21 as ulong,eM22 as ulong,eDx as ulong,eDy as ulong
   'fill rotation values
   xform.eM11.struct=toFloat(cosine)
   xform.eM12.struct=toFloat((-1*sine))
   xform.eM21.struct=toFloat(sine)
   xform.eM22.struct=toFloat(cosine)

   'setup to rotate on bitmap center x and y
   centerX=int(bwidth/2)
   centerY=int(bheight/2)

   xform.eDx.struct=toFloat(centerX-cosine*centerX+(-1*sine)*centerY+int((w-(centerX*2))/2))
   xform.eDy.struct=toFloat(centerY-cosine*centerY-(-1*sine)*centerX+int((h-(centerY*2))/2))
   'rotate world
   r=SetWorldTransform(destDC,xform)
   'put our source bitmap into our dest dc
   null=BitBlt(destDC,0,0,w,h,sourceDC, 0 ,0 , _SRCCOPY)
   'release new rotated bitmap
   null=SelectObject(destDC,hbmOldDest)
   'put rotated bitmap into sourceDC
   hbmOldSource=SelectObject(sourceDC,newBitmap)
   'draw rotated bitmap onto screen into our dest dc
   null=BitBlt(hDC,int(xPos),int(yPos),w,h,sourceDC, 0 ,0 , _SRCCOPY)
   null=DeleteObject(newBitmap)
   end if

end sub

Function GetBMPInfo(bmp$)

    bitmapHwnd=hbmp(bmp$) 'get bmp handle

    'create struct for bmp info
    struct BITMAP,_
    bmType As long,_
    bmWidth As long,_
    bmHeight As long,_
    bmWidthBytes As long,_
    bmPlanes As word,_
    bmBitsPixel As word,_
    bmBits As long

    structSize=Len(BITMAP.struct)'get the size of the struct:

    CallDLL #gdi32, "GetObjectA",_
    bitmapHwnd As ulong,_   'handle of bitmap
    structSize As long,_      'size of struct
    BITMAP As struct,_   'name of struct
    GetBMPInfo As long

End Function


Function CreateCompatibleDC(hDC)
    CallDLL #gdi32, "CreateCompatibleDC", _
        hDC as Ulong, _
        CreateCompatibleDC as Ulong
End Function
Function CreateCompatibleBitmap(hDC, wMem, hMem)
    CallDLL #gdi32, "CreateCompatibleBitmap", _
        hDC as Ulong, _
        wMem as Long, _
        hMem as Long, _
        CreateCompatibleBitmap as Ulong
End Function
Function SelectObject(hDC, hPic)
    CallDLL #gdi32, "SelectObject", _
        hDC as Ulong, _
        hPic as Ulong, _
        SelectObject as Ulong
End Function
Function BitBlt(hdcDest, xDest, yDest, wDest, hDest, hdcSource, xSource, ySource, ROP)
    CallDLL #gdi32, "BitBlt", _
        hdcDest as Ulong, _
        xDest as Long, _
        yDest as Long, _
        wDest as Long, _
        hDest as Long, _
        hdcSource as Ulong, _
        xSource as Long, _
        ySource as Long, _
        ROP as Ulong, _
        result as Boolean
End Function

Function toFloat( R8 )
  Open "oleaut32" For DLL As #oleaut32
'-- Converts a 64-bit Double to a 32-bit number.
    Struct local1, R4 As ULong
    CallDLL #oleaut32, "VarR4FromR8", _
        R8 As Double, local1 As Struct, _
        ret As Long
    toFloat = local1.R4.struct
    close #oleaut32
End Function


Function DeleteObject(objHandle)
    CallDll #gdi32,"DeleteObject",_
        objHandle as Ulong,_
        DeleteObject as long
End Function
Function SetWorldTransform(hdc,xform)
    CallDLL #gdi32, "SetWorldTransform",_
        hdc As ULong,_
        xform As struct,_
        SetWorldTransform As Long
End Function

Function SetGraphicsMode(hdc,iMode)
CallDll #gdi32,"SetGraphicsMode",_
    hdc as Ulong,_
    iMode as ulong,_
    SetGraphicsMode as long
End Function

Function GetDC(handle)
    CallDLL #user32, "GetDC", _
        handle As Ulong, _
        GetDC as Ulong
End Function

Function ReleaseDC(handle, hDC)
    CallDLL #user32, "ReleaseDC", _
        handle As Ulong, _
        hDC As Ulong, _
        ReleaseDC As Long
End Function

Function DeleteDC(hDC)
    CallDLL #gdi32, "DeleteDC", _
        hDC as Ulong, _
        result as Boolean
End Function
