Page 2 sur 2

Re: [Resolu] Pivoter une image de son point central

Publié : jeu. 03/oct./2019 11:37
par Zorro
et voici le code d'Ulix (de Psychophanta en realité) corrigé du bug qui faisait planter au bout de quelques rotations

Code : Tout sélectionner



UseJPEGImageDecoder()
UsePNGImageDecoder()
UseGIFImageDecoder()
Enumeration
		#f1
		#Image
		#GadgetImage
EndEnumeration



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

Procedure Rotation(Image.l, Angle.l)
		
		;code By Psychophanta in 2007-06-21
		;srcfile$="tigre.bmp"
		;angle.f=#PI/6;        30° for example
		;destfile$="destination.bmp"
		;Source Bitmap:
		;srcNumber.l=LoadImage(#PB_Any,srcfile$);,#PB_Image_DisplayFormat)
		srcNumber.l=ImageID(Image)
		srcWidth.l=ImageWidth(Image); <- get the length of a row of the image (in pixels)
		srcHeight.l=ImageHeight(Image); <- get the length of a column of the image (in pixels)
		srcDepth.l=ImageDepth(Image); <- 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(Image),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=AllocateMemory(*srcBmpi\bmiHeader\biSizeImage)
		
		;get the bits:
		GetDIBits_(ScreenDC,ImageID(Image),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=AllocateMemory(*destBmpi\bmiHeader\biSizeImage)
		
		;Set bits in destination buffer (perform the rotation):
		For y.l=0 To destHeight-1
				For x.l=0 To destWidth-1
						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)
		
		ProcedureReturn destNumber
EndProcedure




;============================================================================================================================

;Programme de test de Rotation d'une image
;LoadImage(#Image, "tigre.bmp")      ;chargement d'une image BMP

im$=OpenFileRequester("open jpg","c:\","*.jpg",0)
;im$="D:\Dobro\Mes_Photos\Nouveau dossier\Sv101107.jpg"
LoadImage ( #image , im$ ) ;<----- path of the picture


ResizeImage(#Image, 400, 300)      ;pas trop grande, sinon resize

If OpenWindow(#f1, 0 ,0, 800, 600, "", #PB_Window_ScreenCentered| #PB_Window_SystemMenu   );
		CreateGadgetList(WindowID(#f1))
		ImageGadget(#GadgetImage, 0 ,0, 800, 600, ImageID(#Image))
		CreatePopupMenu(0)
		MenuItem(0, "Close")
		MenuItem(1, "Affichage Normal")
		MenuItem(2, "Aide : bouton gauche pivoter")
		
		degres=0
		Repeat
				Select WaitWindowEvent()
						Case #PB_Event_CloseWindow      :       Break
						Case #WM_RBUTTONUP
								DisplayPopupMenu(0, WindowID(#f1))
								
						Case #PB_Event_Menu
								Select EventMenu()
										Case 0            :      Break
										Case 1            :      ;position
												Id.l=Rotation(#Image,0)
												SetGadgetState(#GadgetImage, ImageID(id))
								EndSelect
								
						Case #WM_LBUTTONUP
								degres+1
								Id.l=Rotation(#Image,degres)
								SetGadgetState(#GadgetImage, ImageID(id))
								
				EndSelect
		ForEver
		End
EndIf



Re: [Resolu] Pivoter une image de son point central

Publié : ven. 04/oct./2019 3:39
par Ollivier
Peut-être rajouter le contexte :

x86/x64 : x86
Windows/Mac/Linux : Windows
Avec ou sans API : Avec API