Page 1 of 3
Rotate Image
Posted: Sat Oct 21, 2006 6:36 pm
by MikeB
I need to be able to rotate an image by 90° clockwise and anti-clockwise. It is for a picture viewer for occasions when the picture was taken with the camera rotated.
I fully expected to find this was a command in PB4 but apparently not! I have done a search, but all I have found is a library that dates back a couple of years and produces linker errors.
I feel sure someone must have done this, any pointers to where would be appreciated.
Posted: Sat Oct 21, 2006 9:32 pm
by MikeB
I have written a routine for doing this,
Code: Select all
LoadImage(0,piccy$)
x = ImageWidth(0)
y = ImageHeight(0)
Dim spotty.l(x,y)
If OpenWindow(0,0,0,x,y,"Original")
If CreateGadgetList(WindowID(0))
ImageGadget(0,0,0,x,y,ImageID(0))
EndIf
EndIf
CreateImage(1,y,x)
;
StartDrawing(ImageOutput(0))
For column = 0 To y-1
For strip = 0 To x-1
spotty(strip,column) = Point(strip,column)
Next
Next
StopDrawing()
;
StartDrawing(ImageOutput(1))
For column = 0 To y-1
For strip = 0 To x-1
Plot(column,x-strip,spotty(strip,column))
Next
Next
StopDrawing()
;
If OpenWindow(1,x+10,0,y,x,"copy")
If CreateGadgetList(WindowID(1))
ImageGadget(1,0,0,y,x,ImageID(1))
EndIf
EndIf
Repeat
ev = WaitWindowEvent()
Until ev = #PB_Event_CloseWindow
It works but is a bit slow, what it needs is writing in ASM or using API or both. If anyone knows how, it would be a help to have a routine to rotate the other way as well.
With my PB method the other way is just a case of starting top right and going down instead of bottom left and going up, with the columns going R>L instead of L>R.
At the moment I am about to write the clockwise bit and put them in the program, it will do until/if something faster comes up!
Posted: Mon Oct 23, 2006 9:29 am
by netmaestro
I made a lib for that very purpose a while back. It's coded in API and will be quite a bit faster than what you've got there. You are welcome to use it. It has one command, you call it like this:
Code: Select all
OpenLibrary(0,"Quarters.dll")
MyImage = CallFunction(0,"TurnByQuarters",ImageID(#image), 1)
CloseLibrary(0)
where the last parameter is 1=90 degrees clockwise, 2=180 degrees, 3=90 degrees counterclockwise. If it succeeds, the dll returns an image handle with the rotated image, if it fails the return value is 0. You must pass 1, 2, or 3 as rotation parameters, anything else returns failed.
As a new image is created each time you call the function, you must remember to:
when you're finished with it or you'll have a memory leak.
http://www.networkmaestro.com/Quarters.dll
Posted: Mon Oct 23, 2006 4:33 pm
by Paul
Having to carry along extra DLL's with your app is such a pain
Here is some code I threw together...
Code: Select all
; Image Rotating Code
; by Paul Leischow
; Compiler: PB 3.94
Procedure Image_Rotate(Image.l)
height=ImageHeight()
width=ImageWidth()
If height>width
temp=CreateImage(#PB_Any,height,height)
Else
temp=CreateImage(#PB_Any,width,width)
EndIf
Dim rect.Point(2)
rect(0)\x=height
rect(0)\y=0
rect(1)\x=height
rect(1)\y=width
rect(2)\x=0
rect(2)\y=0
dc=StartDrawing(ImageOutput())
DrawImage(UseImage(Image),0,0)
PlgBlt_(dc,@rect(),dc,0,0,width,height,0,0,0)
StopDrawing()
GrabImage(temp,image,0,0,height,width)
FreeImage(temp)
EndProcedure
LoadImage(1,"picture1.bmp")
Image_Rotate(1) ;rotates image 90 degrees clockwise everytime you call procedure
If OpenWindow(0,0,0,600,500,#PB_Window_ScreenCentered|#PB_Window_SystemMenu,"")
If CreateGadgetList(WindowID(0))
ImageGadget(0,0,0,10,10,UseImage(1))
Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
EndIf
Posted: Mon Oct 23, 2006 4:35 pm
by Paul
and for those who still have problems converting to PB 4.00 ....
Code: Select all
; Image Rotating Code
; by Paul Leischow
; Compiler: PB 4.00
Procedure Image_Rotate(Image.l)
height=ImageHeight(Image)
width=ImageWidth(Image)
If height>width
temp=CreateImage(#PB_Any,height,height)
Else
temp=CreateImage(#PB_Any,width,width)
EndIf
Dim rect.Point(2)
rect(0)\x=height
rect(0)\y=0
rect(1)\x=height
rect(1)\y=width
rect(2)\x=0
rect(2)\y=0
dc=StartDrawing(ImageOutput(temp))
DrawImage(ImageID(Image),0,0)
PlgBlt_(dc,@rect(),dc,0,0,width,height,0,0,0)
StopDrawing()
GrabImage(temp,image,0,0,height,width)
FreeImage(temp)
EndProcedure
LoadImage(1,"picture1.bmp")
Image_Rotate(1) ;rotates image 90 degrees clockwise everytime you call procedure
If OpenWindow(0,0,0,600,500,"",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
If CreateGadgetList(WindowID(0))
ImageGadget(0,0,0,10,10,ImageID(1))
Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
EndIf
Posted: Mon Oct 23, 2006 4:59 pm
by Thorsten1867
Code: Select all
Procedure RotateImg(Image$,opt.b)
hnd1.l = LoadImage(#ImageRotate1,Image$)
bitmap_w = ImageWidth(#ImageRotate1)
bitmap_h = ImageHeight(#ImageRotate1)
hnd2 = CreateImage(#ImageRotate2,bitmap_h, bitmap_w)
source_dc = CreateCompatibleDC_(main_dc) : SelectObject_(source_dc,hnd1)
dest_dc = CreateCompatibleDC_(main_dc) : SelectObject_(dest_dc,hnd2)
ia = bitmap_h
If opt = 1
While ia > 0 ;{ 90° nach rechts
i = 0
While i < bitmap_w
BitBlt_(dest_dc,bitmap_h-ia,i,1,1,source_dc,i,ia,#SRCCOPY)
i + 1
Wend
ia - 1
Wend ;}
Else
While ia > 0 ;{ 90° nach links
i = 0
While i < bitmap_w
BitBlt_(dest_dc,ia,bitmap_w-i,1,1,source_dc,i,ia,#SRCCOPY)
i + 1
Wend
ia - 1
Wend ;}
EndIf
deletedc_(source_dc)
deletedc_(dest_dc)
SaveImage(#ImageRotate2,Image$,#PB_ImagePlugin_JPEG)
EndProcedure
Posted: Mon Oct 23, 2006 7:29 pm
by MikeB
Thanks for the help chaps, I have tried each of the them and they all work well.
I think that the one that is best for my purpose is the one by Thorsten as I have modified it slightly to rotate an already loaded image. I also did not want to save the new (rotated) version.
I can now pass the image number and option, the procedure creates the new rotated image then copies the new one to the original and frees the new one.
Posted: Mon Oct 23, 2006 10:54 pm
by MikeB
After inclusion in my program, I found a slight bug in the routines as the positions on the bitmap go from 0 to x-1 and 0 to y-1, not 1 to x and 1 to y, where x and y are the Image width and Image height. This caused a single pixel black line on the rotated image.
Corrected as follows
Code: Select all
If opt = 1 ; 90° clockwise
While ia >= 0
i = 0
While i < bitmap_w
BitBlt_(dest_dc, bitmap_h-ia-1, i, 1, 1,source_dc, i, ia, #SRCCOPY)
i + 1
Wend
ia - 1
Wend
Else ; 90° anticlockwise
While ia >= 0
i = 0
While i < bitmap_w
BitBlt_(dest_dc, ia, bitmap_w-i-1, 1, 1, source_dc, i, ia, #SRCCOPY)
i + 1
Wend
ia - 1
Wend
EndIf
Added the '=' on the two occurences of 'While ia >= 0' and the -1 in the 'BitBlt_(dest_dc, bitmap_h-ia-1, i, 1, 1,source_dc, i, ia, #SRCCOPY)' and 'BitBlt_(dest_dc, ia, bitmap_w-i-1, 1, 1, source_dc, i, ia, #SRCCOPY)'
Posted: Fri Nov 24, 2006 11:39 pm
by TerryHough
[quote="netmaestro"]I made a lib for that very purpose a while back. It's coded in API...
@netmaestro
Does this routine use PlgBLT API? I'm looking for something useable on Win32 (Win98SE).
I'm not getting a failure, just not getting an image back. A sligthly extended example would probably help me
Terry
Posted: Sat Nov 25, 2006 7:00 am
by netmaestro
The code for that dll is buried on a cd somewhere, I can probably come up with it if necessary but I'm pretty sure it's going to need Win2000/XP. If I were you I'd use gdiplus.dll for this and distribute it with your app. If you need a sample (or the whole thing it's pretty short) I can post it tomorrow. I'm not sure what your non-gdiplus 9x alternatives are, but if you do it this way it'll work on W9x and go blazing fast.
Posted: Sat Nov 25, 2006 4:06 pm
by TerryHough
I was trying to use it on WinXPPro. I think I am confused between handles and image ID.
So, if you have a more complete example available I would appreciate it.
Posted: Sat Nov 25, 2006 5:05 pm
by netmaestro
Code: Select all
OpenLibrary(0,"Quarters.dll")
MyImage = CallFunction(0,"TurnByQuarters",ImageID(#image), 1)
CloseLibrary(0)
SetGadgetState(#img, MyImage)
; later when you're finished with it
DeleteObject_(MyImage)
Posted: Sat Nov 25, 2006 5:46 pm
by TerryHough
@netmaestro
Thanks, but I'm still failing. Here is my code, maybe you see the error.
[edited: Code now works -

]
Code: Select all
Pgm$ = "Image rotation test"
ExamineDesktops()
#Window=0
If OpenWindow(#Window,0,0,DesktopWidth(0),DesktopHeight(0) - 33,Pgm$,#PB_Window_SystemMenu)
CreateGadgetList(WindowID(#Window))
dc = StartDrawing(WindowOutput(0)) ; Change to the desired output
Box(0,0, WindowWidth(0), WindowHeight(0),#White) ; Set the image to background color
Image = LoadImage(#PB_Any,"\purebasic_4\purebasic.bmp")
ImageGadget(2, 0, 0,ImageWidth(Image), ImageHeight(Image), ImageID(Image)) ; show the image
ImageGadget(3, 200, 200, 200, 200, ImageID(Image)) ; show the image
While WindowEvent():Wend
Delay(2000) ; wait 2 seconds then rotate the image
If OpenLibrary(0,"Quarters.dll")
MyImage = CallFunction(0,"TurnByQuarters",ImageID(Image), 1)
SetGadgetState(3, MyImage)
While WindowEvent():Wend
DeleteObject_(MyImage)
CloseLibrary(0)
Else
MessageRequester("Debug","Could not open the library",#MB_ICONERROR)
EndIf
Repeat
event = WaitWindowEvent()
Until event = #PB_Event_CloseWindow
EndIf
End
Posted: Sat Nov 25, 2006 6:04 pm
by netmaestro
Try this test prog:
Code: Select all
Image = LoadImage(#PB_Any,"\purebasic_4\purebasic.bmp")
OpenWindow(0,0,0,320,240,"",$CF0001)
CreateGadgetList(WindowID(0))
ImageGadget(0,50,20,0,0,ImageID(image))
ButtonGadget(1,100,210,80,20,"flip")
Repeat
ev = WaitWindowEvent()
If ev=#PB_Event_Gadget
If EventGadget()=1
OpenLibrary(0,"quarters.dll")
MyImage = CallFunction(0,"TurnByQuarters",ImageID(image),1)
SetGadgetState(0, MyImage)
CloseLibrary(0)
EndIf
EndIf
Until ev= #WM_CLOSE
If MyImage
DeleteObject_(MyImage)
EndIf
Posted: Sun Nov 26, 2006 3:08 am
by TerryHough
Thanks netmaestro,
If the library is closed, the image is lost.
Laughing at myself.
Terry