Rotate Image

Just starting out? Need help? Post your questions and find answers here.
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Rotate Image

Post 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.
Mike.
(I'm never going to catch up with the improvements to this program)
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Post 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!
Mike.
(I'm never going to catch up with the improvements to this program)
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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:

Code: Select all

DeleteObject_(MyImage)
when you're finished with it or you'll have a memory leak.

http://www.networkmaestro.com/Quarters.dll
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1282
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Post 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
Image Image
User avatar
Paul
PureBasic Expert
PureBasic Expert
Posts: 1282
Joined: Fri Apr 25, 2003 4:34 pm
Location: Canada
Contact:

Post 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
Image Image
User avatar
Thorsten1867
Addict
Addict
Posts: 1372
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Post 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
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Post 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.
Mike.
(I'm never going to catch up with the improvements to this program)
MikeB
Enthusiast
Enthusiast
Posts: 183
Joined: Sun Apr 27, 2003 8:39 pm
Location: Cornwall UK

Post 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)'
Mike.
(I'm never going to catch up with the improvements to this program)
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post 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 :oops:

Terry
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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.
BERESHEIT
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post 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.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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)
BERESHEIT
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

@netmaestro

Thanks, but I'm still failing. Here is my code, maybe you see the error.

[edited: Code now works - :oops: ]

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

Last edited by TerryHough on Sun Nov 26, 2006 3:07 am, edited 2 times in total.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post 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
BERESHEIT
TerryHough
Enthusiast
Enthusiast
Posts: 781
Joined: Fri Apr 25, 2003 6:51 pm
Location: NC, USA
Contact:

Post by TerryHough »

Thanks netmaestro,

If the library is closed, the image is lost.

Laughing at myself. :lol:
Terry
Post Reply