There are other examples here on the forum that will do that but they were either too complex for my liking or not cross platform.
I have written a procedure that uses only native PureBasic code.
The code is simple and reasonably fast.
The image is rotated in place once it is copied into a square temporary image.
After rotation if the original image was not square there will be empty space either on top or along the left side of the temporary image.
GrabImage() is used to recover the relevant portion of the rotated image.
2.17.2014
edit: now supports 32 bit as well as 24 bit images.
Code: Select all
; Rotate image +/- 90 degrees
; by BasicallyPure
; 2.18.2014
; supports 24 and 32 bit depth
; cross platform
EnableExplicit
Procedure ROTATE_90(image, dir)
; rotate image +/- 90 deg.
; 'image' is the number of the image to rotate
; if 'dir' <> 0 then rotate right else rotate left
Protected a,b,c,e,f,h,s,w,x,y,ym,xm,tempImg,depth
If IsImage(image) = 0 : ProcedureReturn 0 : EndIf
StartDrawing(ImageOutput(image))
w = OutputWidth()
h = OutputHeight()
f = DrawingBufferPixelFormat() & $7F
StopDrawing()
If f = #PB_PixelFormat_32Bits_RGB Or f = #PB_PixelFormat_32Bits_BGR
depth = 32
ElseIf f = #PB_PixelFormat_24Bits_RGB Or f = #PB_PixelFormat_24Bits_BGR
depth = 24
Else
ProcedureReturn 0
EndIf
If w > h : s = w : Else : s = h : EndIf ; find the largest dimension
tempImg = CreateImage(#PB_Any,s,s,depth) ; make a square working area
StartDrawing(ImageOutput(tempImg))
If depth = 32 : DrawingMode(#PB_2DDrawing_AllChannels) : EndIf
DrawImage(ImageID(image),0,0)
ym = s/2-1 ; max y loop value
xm = s/2-(s!1&1) ; max x value, subtract 1 if 's' is even
s-1
If dir <> 0 ; rotate right
For y = 0 To ym
For x = 0 To xm
e = Point(x,y)
a = s-x : Plot(x,y,Point(y,a))
b = s-y : Plot(y,a,Point(a,b))
c = s-a : Plot(a,b,Point(b,c))
Plot(b,c,e)
Next x
Next y
Else ; rotate left
For y = 0 To ym
For x = 0 To xm
e = Point(x,y)
a = s-y : Plot(x,y,Point(a,x))
b = s-x : Plot(a,x,Point(b,a))
c = s-a : Plot(b,a,Point(c,b))
Plot(c,b,e)
Next x
Next y
EndIf
StopDrawing()
If dir <> 0
GrabImage(tempImg,image,s-h+1,0,h,w) ; right
Else
GrabImage(tempImg,image,0,s-w+1,h,w) ; left
EndIf
FreeImage(tempImg)
ProcedureReturn 1
EndProcedure
; Demo
UseJPEGImageDecoder() : UsePNGImageDecoder()
If OpenWindow(0,0,0,800,600,"",#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)
Define Pattern$ = "image (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp|image *.*|*.*"
Define F$, T$, Path$ = GetHomeDirectory() + "My Pictures\"
CompilerIf #PB_Compiler_OS = #PB_OS_Linux
Path$ = GetHomeDirectory() + "Pictures/"
CompilerEndIf
CreateStatusBar(0,WindowID(0))
AddStatusBarField(#PB_Ignore)
ImageGadget(0,110,10,1,1,0)
ButtonGadget(1,10,010,90,25,"Load Image")
ButtonGadget(2,10,070,90,25,"Rotate Right")
ButtonGadget(3,10,100,90,25,"Rotate left")
ButtonGadget(4,10,150,90,25,"Quit")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow : Break
Case #PB_Event_Gadget
Select EventGadget()
Case 1 : F$ = OpenFileRequester("Select image", Path$, Pattern$, 0)
If F$ : LoadImage(0,F$)
If IsImage(0)
T$ = F$ + " | (" + ImageWidth(0)
T$ + " x " + ImageHeight(0) + ")"
StatusBarText(0, 0, T$)
SetGadgetState(0,ImageID(0))
EndIf
EndIf
Case 2 : If ROTATE_90(0,1) : SetGadgetState(0,ImageID(0)) : EndIf
Case 3 : If ROTATE_90(0,0) : SetGadgetState(0,ImageID(0)) : EndIf
Case 4 : Break
EndSelect
EndSelect
ForEver
EndIf