which allows the user to select a .bmp file and rotate the image interactively. Whenever I take pictures with my digital camera, the pressure of my finger on the shutter release tilts the camera and the horizon is no longer level. Here is a way to straighten those pictures out. Press the down arrow key to rotate the image clockwise; press the up arrow key to rotate the image counterclockwise; press the return/enter key to save the rotated image as a file (it now only works with .bmp images -- you can change this to suit).
- Notifies user if debugger is active.
- Added constant #ROT_INCREMENT, the image rotation increment.
- Defined variables fileName$ and result.
- Added input file requester allowing user to select a .bmp image, terminates program if user selects Cancel (null string).
- Variable iBitPlanes now gets its value from ImageDepth() after image is loaded.
- Message requester warns user if window cannot be opened, then terminates program.
- Added keyboard shortcuts.
- Moved two instances of FreeImage() to MergeImage(), just to get them out of the way.
- Reworked event loop. Program jumps to rotateAgain when user rotates image by means of up or down arrow keys.
- Changed variable fRot to float (single) to allow for rotation of image in fractional degrees.
() passes fRot as negative value. Positive values give clockwise rotation; negative values give counterclockwise rotation.
Code: Select all
; TEST - RotateImageFree
EnableExplicit
IncludeFile "RotateImage.pb"
Procedure.i CreateCheckers (iWidth, iHeight)
Protected x, y
Protected nImage, iSize = 12
nImage = CreateImage(#PB_Any, iWidth, iHeight, 24)
If nImage
StartDrawing(ImageOutput(nImage))
Box(0, 0, iWidth, iHeight, $FFFFFF)
While y < iHeight + iSize
While x < iWidth + iSize
Box(x, y, iSize, iSize, $C0C0C0)
Box(x + iSize, y + iSize, iSize, iSize, $C0C0C0)
x + iSize*2
Wend
x = 0
y + iSize*2
Wend
StopDrawing()
EndIf
ProcedureReturn nImage
EndProcedure
Procedure.i MergeImages (nImgCheck, nImgOut)
Protected nImage
nImage = CreateImage(#PB_Any, ImageWidth(nImgCheck), ImageHeight(nImgCheck), 24)
If nImage
StartDrawing(ImageOutput(nImage))
DrawImage(ImageID(nImgCheck), 0, 0)
DrawAlphaImage(ImageID(nImgOut), 0, 0)
StopDrawing()
EndIf
FreeImage(nImgOut)
FreeImage(nImgCheck)
ProcedureReturn nImage
EndProcedure
#WIN = 1
#IMG = 1
#IW = 640
#IH = 480
#ROT_INCREMENT = 0.5
Define iEvent, iTime1, k, nFont
Define nImgSrc, nImgOut
Define nImgCheck, nImgDisp, fileName$, result
; ****************************************************************
; try to change these vars to check out the various combinations *
; ****************************************************************
Define iBitPlanes ;= 32 ; test 24 or 32 bpp image
Define fRot.f = 0 ; angle used for rotation
Define flgAntiAlias = #True ; Antialias (1) or simpler rotation (0)
Define iFillColor = RGB(255,255,255) ; useful for transparent masking using GDI or simply to fill the background
Debug "Disable debugger for maximum performance."
nFont = LoadFont(#PB_Any, "Arial", 12, #PB_Font_Bold)
; nImgSrc = CreateImage(#PB_Any, #IW, #IH, iBitPlanes)
;
; StartDrawing(ImageOutput(nImgSrc))
;
; For k = 0 To 100 Step 20
; Box(0 + k, 0 + k, #IW - k * 2, #IH - k * 2, RGB(k + 50, k + 100, k + 150))
; Next
;
; DrawingMode(#PB_2DDrawing_Transparent)
; DrawingFont(FontID(nFont))
;
; For k = 0 To #IH Step #IH / 10
; DrawText(20, k + 10, "TEXT - " + Str(iBitPlanes) + " BPP IMAGE - TEXT", RGB(k/3, k/2, k/2))
; Next
;
; If iBitPlanes = 24
; DrawingMode(#PB_2DDrawing_Default)
; Circle(#IW - 200, 100, 50, RGB(128,0,0))
; Circle(#IW - 200, #IH - 100, 50, RGB(0,128,0))
; Circle(#IW - 80, #IH/2, 50, RGB(0,0,128))
; Else
; iFillColor = 0
;
; ; make 3 holes
; DrawingMode(#PB_2DDrawing_AlphaChannel)
; Circle(#IW - 200, 100, 50, $00)
; Circle(#IW - 200, #IH - 100, 50, $00)
; Circle(#IW - 80, #IH/2, 50, $00)
;
; ; fill them with semi-transparent circles
; DrawingMode(#PB_2DDrawing_AlphaBlend)
; Circle(#IW - 200, 100, 50, RGBA(128,0,0,100))
; Circle(#IW - 200, #IH - 100, 50, RGBA(0,128,0,100))
; Circle(#IW - 80, #IH/2, 50, RGBA(0,0,128,100))
; EndIf
;
; StopDrawing()
fileName$ = OpenFileRequester("Select a picture file", ".\", "bmp files| *.bmp", 0) ;MODIFY FOR DESIRED FILE TYPE
If fileName$ = "": End: EndIf
nImgSrc = LoadImage(#PB_Any, fileName$)
;;UsePNGImageDecoder()
;;nImgSrc = LoadImage(#PB_Any, "test24.bmp")
;;nImgSrc = LoadImage(#PB_Any, "test32.png")
iBitPlanes = ImageDepth(nImgSrc)
result = OpenWindow(#WIN, 0, 0, 1024, 800, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If result = 0: MessageRequester("Error", "Unable to open window."): End: EndIf
AddKeyboardShortcut(#WIN, #PB_Shortcut_Down, 1)
AddKeyboardShortcut(#WIN, #PB_Shortcut_Up, 2)
AddKeyboardShortcut(#WIN, #PB_Shortcut_Return, 3)
rotateAgain:
iTime1 = ElapsedMilliseconds()
nImgOut = RotateImageFree (nImgSrc, -fRot, flgAntiAlias, iFillColor)
iTime1 = ElapsedMilliseconds() - iTime1
SetWindowTitle(#WIN, "Test " + Str(iBitPlanes) + " bit, AA = " + Str(flgAntiAlias) + ", msec = " + Str(iTime1) + ", deg = " + StrF(fRot,1))
nImgCheck = CreateCheckers(ImageWidth(nImgOut), ImageHeight(nImgOut))
nImgDisp = MergeImages(nImgCheck, nImgOut)
; FreeImage(nImgOut) ;MOVED TO PROCEDURE MergeImages(), JUST BECAUSE
; FreeImage(nImgCheck) ;MOVED TO PROCEDURE MergeImages(), JUST BECAUSE
ImageGadget(#IMG, 0, 0, 0, 0, ImageID(nImgDisp))
Repeat
iEvent = WaitWindowEvent()
Select iEvent
Case #PB_Event_Menu
result = EventMenu()
Select result
Case 1 ;DOWN ARROW KEY PRESSED
fRot + #ROT_INCREMENT
Goto rotateAgain
Case 2 ;UP ARROW KEY PRESSED
fRot - #ROT_INCREMENT
Goto rotateAgain
Case 3 ;ENTER/RETURN KEY PRESSED
SaveImage(nImgDisp, "Rotated.bmp")
MessageRequester("", "Image saved.")
EndSelect
Case #PB_Event_CloseWindow
FreeImage(nImgDisp)
FreeImage(nImgSrc)
FreeFont(nFont)
End
EndSelect
ForEver