Rotate Image
- netmaestro
- PureBasic Bullfrog
- Posts: 8451
- Joined: Wed Jul 06, 2005 5:42 am
- Location: Fort Nelson, BC, Canada
-
- Enthusiast
- Posts: 781
- Joined: Fri Apr 25, 2003 6:51 pm
- Location: NC, USA
- Contact:
@netmaestro
Thanks for your help.
FYI, your dll does not work with Win98SE as you suspected. To bad, as that is what I really need. Loads of users with old machines who just have no real reason to upgrade.
Also, the rotated image is not quite correct. Look closely at the results of the corrected code I posted above. You will notice a black line at the bottom of the rotated image, approximately 1-2 pixels high. The top of the image is trimmed approximately the same amount. I didn't notice it myself at first with the Purebasic.bmp, but when I rotated the images I actually planned to use it was apparent.
Here is an example of the original and rotated image.

Thanks for your help.
FYI, your dll does not work with Win98SE as you suspected. To bad, as that is what I really need. Loads of users with old machines who just have no real reason to upgrade.
Also, the rotated image is not quite correct. Look closely at the results of the corrected code I posted above. You will notice a black line at the bottom of the rotated image, approximately 1-2 pixels high. The top of the image is trimmed approximately the same amount. I didn't notice it myself at first with the Purebasic.bmp, but when I rotated the images I actually planned to use it was apparent.
Here is an example of the original and rotated image.

Terry, take a look at http://www.leunen.com/cbuilder/rotbmp.html (5. Rotating bitmaps using DIBs). That code (converted to PB) works on Win98. 

What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
-
- Enthusiast
- Posts: 781
- Joined: Fri Apr 25, 2003 6:51 pm
- Location: NC, USA
- Contact:
Before you go through the translation process, you can verify the code will work on your Win98 machines by using this test app I threw together. 
The .exe size is ~415KB due to the inclusion of the 4 PB image decoders.

The .exe size is ~415KB due to the inclusion of the 4 PB image decoders.

What goes around comes around.
PB 5.21 LTS (x86) - Windows 8.1
PB 5.21 LTS (x86) - Windows 8.1
rotate image in degres
picture for test :

picture for test :

Code: Select all
;Rotate image
; codé par Dobro
; en purebasic 4.00
Declare rotate_image(id,x,Y,degres)
UseJPEGImageDecoder ()
InitSprite ()
#dobro =1
#Police =1
#Sprite =1
#image1 =1
#image2 =2
Structure image
x.l[1024]
Y.l[768]
EndStructure
Global Dim image.image(360)
Global Dim tabl1(1024,768 )
; ***********************************
FontID = LoadFont ( #Police , "arial" , 50, #PB_Font_Bold )
EcranX = GetSystemMetrics_ ( #SM_CXSCREEN ): ;=largeur de l'ecran
EcranY = GetSystemMetrics_ ( #SM_CYSCREEN ): ;=hauteur de l'ecran
WindowID = OpenWindow (1, 0, 0, EcranX, EcranY, "hello" , #PB_Window_BorderLess |#PB_Window_ScreenCentered )
WindowID = WindowID (1)
Result = OpenWindowedScreen ( WindowID ,0,0, EcranX, EcranY, 1, 0,0)
; principe de rotation
;x1 = coordonée x du point rotationé
;Y1= coordonée y du point rotationé
; a = angle de rotation
; x1 = x * Cos(a) + Y * Sin(a);
; y1 = -x * Sin(a) + Y * Cos(a)
LoadImage ( #image1 , "logo2.jpg" ) ;<----- path of the picture
largeur = ImageWidth(#image1)
hauteur = ImageHeight(#image1)
CreateImage ( #image2 ,largeur,hauteur )
; ******* mise en tableau de l'image **********
StartDrawing ( ImageOutput ( #image1 ) )
For Y=1 To hauteur
For x=1 To largeur
tabl1(x,Y)= Point (x,Y)
Next x
Next Y
StopDrawing ()
;*****************************************************
Resultat = InitMouse ()
Repeat
ExamineMouse ()
Event= WindowEvent ()
Delay (2)
angle_degres=angle_degres+1 :If angle_degres>360:angle_degres=1:EndIf
rotate_image(#image2,largeur, hauteur, angle_degres)
; ****** **on affiche l'image ********
StartDrawing ( ScreenOutput ())
DrawImage ( ImageID ( #image2 ), 1, 1)
StopDrawing ()
; *******************************
FlipBuffers (): ; affiche l'ecran
ClearScreen ( RGB (0, 0, 0)) : ;efface l'ecran
Event= WindowEvent ()
;}
If MouseButton (2)
End
EndIf
Until Event= #PB_Event_CloseWindow
Procedure rotate_image(id,x2,y2,degres)
;id = id picture
;x2=Width
;y2=Height
;degres=rotation in degres
StartDrawing ( ImageOutput ( id ) )
For Y=1 To y2
For x=1 To x2
; ********* voici la formule de la rotation d'image *********
image(degres)\x[x]= x * Cos (degres* #PI /180) + Y* Sin (degres* #PI /180)
image(degres)\Y[Y]= -x * Sin (degres* #PI /180) + Y* Cos (degres* #PI /180)
;*****************************************************
; *** on evite que les coordonée sorte du tableau dim ****
If image(degres) \Y[Y] <0 : image(degres) \Y[Y]=y2-image(degres) \Y[Y] : EndIf
If image(degres)\Y[Y] >y2 : image(degres) \Y[Y] =0+image(degres)\Y[Y] -y2: EndIf
If image(degres)\x[x]>x2 : image(degres)\x[x]=0+image(degres)\x[x]-x2: EndIf
If image(degres)\x[x]<1 : image(degres)\x[x]=x2-image(degres)\x[x]: EndIf
; *****************************************
Plot (x,Y,tabl1( image(degres)\x[x],image(degres)\Y[Y])) ; on dessine l'image rotaté a l'aide du tableau de points : D
Next x
Next Y
StopDrawing ()
EndProcedure
- Psychophanta
- Always Here
- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
For those interested i've translated the C++ Builder source at http://www.leunen.com/cbuilder/rotbmp.html (section 5. Rotating bitmaps using DIBs) to PB 4.10b2.
So then the Sparkie program source core is something like this here:
So then the Sparkie program source core is something like this here:
Code: Select all
;Rotate an image bitmap.
;Translated from C++Builder code from http://www.leunen.com/cbuilder/rotbmp.html (section 5. Rotating bitmaps using DIBs)
;By Psychophanta in 2007-06-21
Procedure.f MinF(n1.f,n2.f)
If n1<n2:ProcedureReturn n1:EndIf:ProcedureReturn n2
EndProcedure
Procedure.f MaxF(n1.f,n2.f)
If n1>n2:ProcedureReturn n1:EndIf:ProcedureReturn n2
EndProcedure
srcfile$="source.bmp"
angle.f=#PI/6; 30° for example
destfile$="destination.bmp"
;Source Bitmap:
srcNumber.l=LoadImage(#PB_Any,srcfile$);,#PB_Image_DisplayFormat)
srcWidth.l=ImageWidth(srcNumber); <- get the length of a row of the image (in pixels)
srcHeight.l=ImageHeight(srcNumber); <- get the length of a column of the image (in pixels)
srcDepth.l=ImageDepth(srcNumber); <- get the length of a pixel of the image (in bits)
cosine.f=Cos(angle)
sine.f=Sin(angle)
Point1x.f=-srcHeight*sine
Point1y.f=srcHeight*cosine
Point3x.f=srcWidth*cosine
Point3y.f=srcWidth*sine
Point2x.f=Point1x+Point3x
Point2y.f=Point1y+Point3y
minx.f=MinF(0,MinF(Point1x,MinF(Point2x,Point3x)))
miny.f=MinF(0,MinF(Point1y,MinF(Point2y,Point3y)))
maxx.f=MaxF(0,MaxF(Point1x,MaxF(Point2x,Point3x)))
maxy.f=MaxF(0,MaxF(Point1y,MaxF(Point2y,Point3y)))
destWidth.l=Round(maxx-minx,1)
destHeight.l=Round(maxy-miny,1)
destDepth.l=srcDepth
;Destination bitmap:
destNumber.l=CreateImage(#PB_Any,destWidth,destHeight,destDepth)
;create DIB For SrcBitmap:
*srcBmpi.BITMAPINFO=AllocateMemory(SizeOf(BITMAPINFO)):ZeroMemory_(*srcBmpi,SizeOf(BITMAPINFO))
;init BitmapInfo struct:
*srcBmpi\bmiHeader\biSize=SizeOf(BITMAPINFOHEADER)
*srcBmpi\bmiHeader\biWidth=srcWidth
*srcBmpi\bmiHeader\biHeight=srcHeight
*srcBmpi\bmiHeader\biPlanes=1
*srcBmpi\bmiHeader\biCompression=#BI_RGB
If srcDepth=24 Or srcDepth=32:*srcBmpi\bmiHeader\biBitCount=srcDepth:EndIf
;Each row is zero padded so that the number of bytes per row is divisible by 4
srcNumberOfBytesPerRow.l=((srcWidth**srcBmpi\bmiHeader\biBitCount+31)&~31)/8
;use screen DC For GetDIBits:
ScreenDC.l=GetDC_(#Null)
;get image size:
GetDIBits_(ScreenDC,ImageID(srcNumber),0,*srcBmpi\bmiHeader\biHeight,#Null,*srcBmpi,#DIB_RGB_COLORS)
;If the driver didn't give the size, calculate it yourselves:
If *srcBmpi\bmiHeader\biSizeImage=0:*srcBmpi\bmiHeader\biSizeImage=srcNumberOfBytesPerRow*srcHeight:EndIf
;Allocate memory for the bits:
*srcbits.b=AllocateMemory(*srcBmpi\bmiHeader\biSizeImage)
;get the bits:
GetDIBits_(ScreenDC,ImageID(srcNumber),0,*srcBmpi\bmiHeader\biHeight,*srcbits,*srcBmpi,#DIB_RGB_COLORS)
;create DIB for DestBitmap:
*destBmpi.BITMAPINFO=AllocateMemory(SizeOf(BITMAPINFO)):ZeroMemory_(*destBmpi,SizeOf(BITMAPINFO))
;init BitmapInfo struct:
*destBmpi\bmiHeader\biSize=SizeOf(BITMAPINFOHEADER)
*destBmpi\bmiHeader\biWidth=destWidth
*destBmpi\bmiHeader\biHeight=destHeight
*destBmpi\bmiHeader\biPlanes=1
*destBmpi\bmiHeader\biCompression=#BI_RGB
*destBmpi\bmiHeader\biBitCount=*srcBmpi\bmiHeader\biBitCount
;Each row is zero padded so that the number of bytes per row is divisible by 4:
destNumberOfBytesPerRow.l=((destWidth**destBmpi\bmiHeader\biBitCount+31)&~31)/8
;get image size:
GetDIBits_(ScreenDC,ImageID(destNumber),0,*destBmpi\bmiHeader\biHeight,#Null,*destBmpi,#DIB_RGB_COLORS)
;If the driver didn't give the size, calculate it ourselves:
If *destBmpi\bmiHeader\biSizeImage=0:*destBmpi\bmiHeader\biSizeImage=destNumberOfBytesPerRow*destHeight:EndIf
;Allocate memory for the bits:
*destbits.b=AllocateMemory(*destBmpi\bmiHeader\biSizeImage)
;Set bits in destination buffer (perform the rotation):
For y.l=0 To destHeight
For x.l=0 To destWidth
SrcBitmapx.l=(x+minx)*cosine+(y+miny)*sine
SrcBitmapy.l=(y+miny)*cosine-(x+minx)*sine
If SrcBitmapx>=0 And SrcBitmapx<srcWidth And SrcBitmapy>=0 And SrcBitmapy<srcHeight
CopyMemory(*srcbits+SrcNumberOfBytesPerRow*SrcBitmapy+SrcBitmapx**srcBmpi\bmiHeader\biBitCount/8+i,*destbits+DestNumberOfBytesPerRow*y+x**srcBmpi\bmiHeader\biBitCount/8+i,*srcBmpi\bmiHeader\biBitCount/8)
EndIf
Next
Next
;Set the bits in destination bitmap:
SetDIBits_(ScreenDC,ImageID(destNumber),0,*destBmpi\bmiHeader\biHeight,*destbits,*destBmpi,#DIB_RGB_COLORS)
SaveImage(destNumber.l,destfile$,#PB_ImagePlugin_BMP)
rotate image 90, 180, 270
What must be change, to rotate the image in 180 and 270 grad?
(Sorry for my bad English.)
hth
(Sorry for my bad English.)
hth
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
3 coordinates to the destination
top-left, top-right and bottom-left
top-left, top-right and bottom-left
Code: Select all
; 180 degrees
; rect(0)\x=width
; rect(0)\y=height
; rect(1)\x=0
; rect(1)\y=height
; rect(2)\x=width
; rect(2)\y=0
; 270 degrees
; rect(0)\x=0
; rect(0)\y=height
; rect(1)\x=0
; rect(1)\y=0
; rect(2)\x=width
; rect(2)\y=height
-
- User
- Posts: 39
- Joined: Fri Mar 26, 2004 1:47 pm
- Location: London, UK
- Contact:
270 degrees should be
Code: Select all
rect(0)\x=0
rect(0)\y=width
rect(1)\x=0
rect(1)\y=0
rect(2)\x=height
rect(2)\y=width
Why don't you just use the "search" function above?
Here's some code you'll be able to find : http://www.purebasic.fr/english/viewtop ... t=rotation
Here's some code you'll be able to find : http://www.purebasic.fr/english/viewtop ... t=rotation
Re: Rotate Image Clockwise and Counter-Clockwise
Paul, your original Image Rotating Code is exactly what I needed for my application. I have been able to use it for both clockwise, and simulating counter-clockwise rotation (run the clockwise code 3 times...). But I was wondering if you could suggest a more elegant solution to provide -90 degree rotation (counter-clockwise) with a single call. My PB Kung Fu is not yet strong Master...Paul wrote: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
PB: 6.00 LTS (x86) OS: Windows 10
-
- Always Here
- Posts: 6426
- Joined: Fri Oct 23, 2009 2:33 am
- Location: Wales, UK
- Contact:
Re: Rotate Image
Take a look at Luis's code:
Image Rotation routines for 24/32 bit with optional AA
Image Rotation routines for 24/32 bit with optional AA
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
If it sounds simple, you have not grasped the complexity.