RotateBitmap III

Category: Rotation

Date: 03-28-2012

Return to Index


 
'Compiler Comments:
'This code is written to compile in PBWin10. To compile in PBWin9, split pt
'into pt.x and pt.y as arguments wherever the PtInRect() API is used (3 places).
 
'Compilable Example:
#Compiler PBWin 10
#Compile EXE
#Dim All
#Include "win32api.inc"
#Resource "gbsnippets.pbr"
 
Type gbPoint
   x  As Long      'new x position
   y As Long       'new y position
   col As Long     'color of pixel
End Type
 
   %IDC_Graphic = 501
   %IDC_LabelA  = 502
   %IDC_LabelB  = 503
   %IDC_Button1 = 504
   %IDC_Button2 = 505
   %IDC_Button3 = 506
 
   Global hDlg,hBMP As Dword, ImageH, ImageW As Long, trc As Rect
   Global ContainerW, ContainerH, XCenter, YCenter As Long
 
Function PBMain() As Long
   Dialog New Pixels, 0, "Rotate Image",300,300,375,300, %WS_SysMenu, 0 To hDlg
   Control Add Label, hDlg, %IDC_LabelA, "<timer results>", 10,10,100,20
   Control Add Label, hDlg, %IDC_LabelB, "", 10,260,200,20
   Control Add Button, hDlg, %IDC_Button1,"Set Pixel", 10,70,80,20
   Control Add Button, hDlg, %IDC_Button2,"CVL / MKL", 10,100,80,20
   Control Add Button, hDlg, %IDC_Button3,"Pointer", 10,130,80,20
   Control Add Graphic, hDlg, %IDC_Graphic,"", 125,10,200,200
   Dialog Show Modal hDlg Call DlgProc
End Function
 
CallBack Function DlgProc() As Long
   Local T As Quad, i As Long
   Static theta As Single
   Select Case Cb.Msg
      Case %WM_InitDialog
         'put Resource image into memory bitmap - get WxH of the image
         Graphic Bitmap Load "cowgirl", 0, 0 To hBMP
         Graphic Attach hBMP, 0
         Graphic Get Client To ImageW,ImageH
         'get size of graphic control (must be big enough to hold rotated image)
         Graphic Attach hDlg, %IDC_Graphic
         Graphic Get Client To ContainerW, ContainerH      'HxW of graphic control
         XCenter = ContainerW/2 : YCenter = ContainerH/2   'center of rotation in graphic control
         theta = 0.3
         trc.nleft = 0 : trc.nright = ImageW-1 : trc.ntop = 0  : trc.nbottom = ImageH-1   'orig image boundaries
 
      Case %WM_LButtonDblClk
         Graphic Attach hDlg, %IDC_Graphic
         Graphic Clear
 
      Case %WM_MouseWheel
         Select Case Hi(Integer,Cb.WParam)    'note the use of Integer
            Case > 0 : theta = theta + 0.2 : Graphic Attach hDlg, %IDC_Graphic,ReDraw : Graphic Clear : RotateImageC(theta)
            Case < 0 : theta = theta - 0.2 : Graphic Attach hDlg, %IDC_Graphic,ReDraw : Graphic Clear : RotateImageC(theta)
         End Select
 
      Case %WM_Command
         Select Case Cb.Ctl
            Case %IDC_Button1 : Tix T : RotateImageA(theta) : Tix End T : Control Set Text hDlg, %IDC_LabelA, Format$(T, "###,###,###")
            Case %IDC_Button2 : Tix T : RotateImageB(theta) : Tix End T : Control Set Text hDlg, %IDC_LabelA, Format$(T, "###,###,###")
            Case %IDC_Button3 : Tix T : RotateImageC(theta) : Tix End T : Control Set Text hDlg, %IDC_LabelA, Format$(T, "###,###,###")
         End Select
   End Select
End Function
 
Sub RotateImageA(theta As Single)
   Local x1,x2,y1,y2,x,y As Long, sintheta, costheta As Single
   Local BoundW, BoundH, XStart, YStart, iColor As Long, pt as Point
 
   'pre-calculate some values
   sintheta = Sin(theta) : costheta = Cos(theta)
 
   'get size of rectangle that will bound the rotated image
   BoundW = ImageW*Abs(Costheta) + ImageH*Abs(Sintheta)
   BoundH = ImageH*Abs(Costheta) + ImageW*Abs(Sintheta)
 
   'calculate coordinates of the bounding box (enclosing the rotated points)
   x1 =(ContainerW-BoundW)/2   :    y1 =(ContainerH-BoundH)/2
   x2 = x1 + BoundW - 1        :    y2 = y1 + BoundH - 1
 
   For x = x1 To x2
      For y = y1 To y2
         XStart = XCenter + (x - XCenter) * Costheta - (y - YCenter) * Sintheta   'unrotated x
         YStart = YCenter + (x - XCenter) * Sintheta + (y - YCenter) * Costheta   'unrotated y
         Graphic Attach hBMP, 0, Redraw
         Graphic Get Pixel (XStart-XCenter/2,YStart-YCenter/2) To iColor
         Graphic Attach hDlg, %IDC_Graphic, Redraw
         pt.x = XStart-XCenter/2 : pt.y = YStart-YCenter/2
         Graphic Set Pixel (x,y), IIF(PtInRect(trc, pt), iColor, %RGB_LightBlue)
      Next y
   Next x
   Graphic Box (x1-1,y1-1)-(x2+1,y2+1),, %Red
   Graphic ReDraw
   Control Set Text hDlg, %IDC_LabelB, str$(ImageW) + str$(ImageH) + str$(ContainerW) + str$(ContainerH) + str$(BoundW) + str$(BoundH) + str$(x1) + str$(y1) + str$(x2) + str$(y2)
End Sub
 
Sub RotateImageB(theta As Single)
   Local x1,x2,y1,y2,x,y As Long, sintheta, costheta As Single
   Local BoundW, BoundH, XStart, YStart, iColor As Long, pt as Point
   Local bmp_source$, bmp_target$
 
   'pre-calculate some values
   sintheta = Sin(theta) : costheta = Cos(theta)
 
   'get size of rectangle that will bound the rotated image
   BoundW = ImageW*Abs(Costheta) + ImageH*Abs(Sintheta)
   BoundH = ImageH*Abs(Costheta) + ImageW*Abs(Sintheta)
 
   'calculate coordinates of the bounding box (enclosing the rotated points)
   x1 =(ContainerW-BoundW)/2   :    y1 =(ContainerH-BoundH)/2
   x2 = x1 + BoundW - 1        :    y2 = y1 + BoundH - 1
 
   'work with bit strings from each image
   Graphic Attach hBMP, 0, Redraw            : Graphic Get Bits To bmp_source$
   Graphic Attach hDlg, %IDC_Graphic, Redraw : Graphic Get Bits To bmp_target$
 
   For x = x1 To x2
      For y = y1 To y2
         XStart = XCenter + (x - XCenter) * Costheta - (y - YCenter) * Sintheta   'unrotated x
         YStart = YCenter + (x - XCenter) * Sintheta + (y - YCenter) * Costheta   'unrotated y
         iColor = Cvl(bmp_source$, ((yStart-YCenter/2)*ImageW+(xStart-XCenter/2))*4+8 )
         pt.x = XStart-XCenter/2 : pt.y = YStart-YCenter/2
         Mid$(bmp_target$,(y*ContainerW+x)*4+8,4) = IIF$(PtInRect(trc,pt),Mkl$(iColor),Mkl$(BGR(%RGB_LightGray)))
      Next y
   Next x
   Graphic Set Bits bmp_target$
   Graphic Box (x1-1,y1-1)-(x2+1,y2+1),, %Red
   Graphic ReDraw
   Control Set Text hDlg, %IDC_LabelB, str$(ImageW) + str$(ImageH) + str$(ContainerW) + str$(ContainerH) + str$(BoundW) + str$(BoundH) + str$(x1) + str$(y1) + str$(x2) + str$(y2)
End Sub
 
Sub RotateImageC(theta As Single)
   Local x1,x2,y1,y2,x,y As Long, sintheta, costheta As Single
   Local BoundW, BoundH, XStart, YStart, iColor As Long
   Local bmp_source$, bmp_target$, pt as Point
   Local PixelPTR_source, PixelPTR_target As Long PTR, iSource, iTarget As Long
 
   'pre-calculate some values
   sintheta = Sin(theta) : costheta = Cos(theta)
 
   'get size of rectangle that will bound the rotated image
   BoundW = ImageW*Abs(Costheta) + ImageH*Abs(Sintheta)
   BoundH = ImageH*Abs(Costheta) + ImageW*Abs(Sintheta)
 
   'calculate coordinates of the bounding box (enclosing the rotated points)
   x1 =(ContainerW-BoundW)/2   :    y1 =(ContainerH-BoundH)/2
   x2 = x1 + BoundW - 1        :    y2 = y1 + BoundH - 1
 
   'work with bit strings from each image
   Graphic Attach hBMP, 0, Redraw             : Graphic Get Bits To bmp_source$
   Graphic Attach hDlg, %IDC_Graphic, Redraw  : Graphic Get Bits To bmp_target$
   PixelPTR_source = StrPtr(bmp_source$) + 8  : iSource = PixelPTR_source
   PixelPTR_target = StrPtr(bmp_target$) + 8  : iTarget = PixelPTR_target
 
   For x = x1 To x2
      For y = y1 To y2
         XStart = XCenter + (x - XCenter) * Costheta - (y - YCenter) * Sintheta   'unrotated x
         YStart = YCenter + (x - XCenter) * Sintheta + (y - YCenter) * Costheta   'unrotated y
         PixelPTR_source = iSource + ((YStart-YCenter/2)*ImageW+(XStart-XCenter/2))*4
         PixelPTR_target = iTarget + (y * ContainerW + x ) * 4
         pt.x = XStart-XCenter/2 : pt.y = YStart-YCenter/2
         @PixelPTR_target = IIf(PtInRect(trc,pt) , @PixelPTR_source, Bgr(%RGB_Moccasin))
      Next y
   Next x
   Graphic Set Bits bmp_target$
   Graphic Box (x1-1,y1-1)-(x2+1,y2+1),, %Red
   Graphic ReDraw
   Control Set Text hDlg, %IDC_LabelB, str$(ImageW) + str$(ImageH) + str$(ContainerW) + str$(ContainerH) + str$(BoundW) + str$(BoundH) + str$(x1) + str$(y1) + str$(x2) + str$(y2)
End Sub
 
'gbs_00911
'Date: 03-10-2012


created by gbSnippets
http://www.garybeene.com/sw/gbsnippets.htm