Passage Quadrangle à rectangle

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Passage Quadrangle à rectangle

Message par graph100 »

Ce code permet de passer d'un quadrangle (quelconque par définition) à un rectangle.
L'image ainsi modifiée n'a pas de "trous" puisque les pixels sont pris directement au bon endroit.

Je n'ai pas mis d'interpolation pour le moment, mais si le résultat que je voulais obtenir n'est pas correct je le rajouterai pour voir.

[edit] : finalement j'ai mis l'interpolation... [Espace] pour passer en mode interpolé

Code : Tout sélectionner

;{ interface
WD = OpenWindow(#PB_Any, 0, 0, 800, 600, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CanvasGadget(0, 0, 0, 800, 600, #PB_Canvas_Keyboard)

AddKeyboardShortcut(wd, #PB_Shortcut_Escape, 0)

AddKeyboardShortcut(wd, #PB_Shortcut_1, 1)
AddKeyboardShortcut(wd, #PB_Shortcut_2, 2)
AddKeyboardShortcut(wd, #PB_Shortcut_3, 3)
AddKeyboardShortcut(wd, #PB_Shortcut_4, 4)

AddKeyboardShortcut(wd, #PB_Shortcut_Space, 5)
;}

;{ procedures

Structure PointD
	x.d
	y.d
EndStructure

Procedure CalculD(Array a.PointD(1), Array b.PointD(1), Array c.PointD(1))
	Protected m.PointD
	
	min.pointD\x = Infinity()
	max.PointD\x = -Infinity()
	
	min\y = Infinity()
	max\y = -Infinity()
	
	For i = 0 To 3
		j = (i+1)%4
		
		b(i)\x = (a(i)\x + a(j)\x) / 2
		b(i)\y = (a(i)\y + a(j)\y) / 2
		
		m\x + a(i)\x
		m\y + a(i)\y
		
		If b(i)\x < min\x : min\x = b(i)\x : EndIf
		If b(i)\y < min\y : min\y = b(i)\y : EndIf
		If b(i)\x > max\x : max\x = b(i)\x : EndIf
		If b(i)\y > max\y : max\y = b(i)\y : EndIf
	Next
	
	m\x / 4
	m\y / 4
	
	;{ autre définition du rectangle
	; 		h = Sqr((b(0)\x - b(2)\x) * (b(0)\x - b(2)\x) + (b(0)\y - b(2)\y) * (b(0)\y - b(2)\y))
	; 		w = Sqr((b(1)\x - b(3)\x) * (b(1)\x - b(3)\x) + (b(1)\y - b(3)\y) * (b(1)\y - b(3)\y))
	; 	
	; 		c(0)\x = m\x - w / 2
	; 		c(0)\y = m\y - h / 2
	; 		
	; 		c(1)\x = m\x + w / 2
	; 		c(1)\y = m\y - h / 2
	; 		
	; 		c(2)\x = m\x + w / 2
	; 		c(2)\y = m\y + h / 2
	; 		
	; 		c(3)\x = m\x - w / 2
	; 		c(3)\y = m\y + h / 2
	;}
	
	c(0)\x = min\x
	c(0)\y = min\y
	
	c(1)\x = max\x
	c(1)\y = min\y
	
	c(2)\x = max\x
	c(2)\y = max\y
	
	c(3)\x = min\x
	c(3)\y = max\y
	
EndProcedure

Procedure QuadrangleImage(x, y, Array a.PointD(1), Array c.PointD(1))
	Protected cible.PointD, coord.pointD, w, h, x1, y1
	
	u.PointD\x = a(1)\x - a(0)\x
	u.PointD\y = a(1)\y - a(0)\y
	
	v.PointD\x = a(3)\x - a(0)\x
	v.PointD\y = a(3)\y - a(0)\y
	
	u1.PointD\x = a(2)\x - a(3)\x
	u1.PointD\y = a(2)\y - a(3)\y
	
	w = Round(c(1)\x - c(0)\x, #PB_Round_Up)
	h = Round(c(2)\y - c(0)\y, #PB_Round_Up)
	
	For x1 = 0 To w Step 32
		For y1 = 0 To h Step 32
			COORD\x = x1 / W
			COORD\y = y1 / h
			
			cible\x = a(0)\x + COORD\x * (1 - COORD\y) * u\x + COORD\y * v\x + COORD\y * COORD\x * u1\x
			cible\y = a(0)\y + COORD\x * (1 - COORD\y) * u\y + COORD\y * v\y + COORD\y * COORD\x * u1\y
			
			If x1 < w / 2
				If y1 < h / 2
					Circle(cible\x, cible\y, 2, #Red)
				Else
					Circle(cible\x, cible\y, 2, #Green)
				EndIf
			Else
				If y1 < h / 2
					Circle(cible\x, cible\y, 2, #Blue)
				Else
					Circle(cible\x, cible\y, 2, #Gray)
				EndIf
			EndIf
			
		Next
	Next
	
	
	For x1 = 0 To w
		For y1 = 0 To h
			COORD\x = x1 / W
			COORD\y = y1 / h
			
			cible\x = a(0)\x + COORD\x * (1 - COORD\y) * u\x + COORD\y * v\x + COORD\y * COORD\x * u1\x
			cible\y = a(0)\y + COORD\x * (1 - COORD\y) * u\y + COORD\y * v\y + COORD\y * COORD\x * u1\y
			
			
			If cible\x > 0 And cible\x < OutputWidth() - 1 And cible\y > 0 And cible\y < OutputHeight() - 1
				If x + x1 > -1 And x + x1 < OutputWidth() And y + y1 > -1 And y + y1 < OutputHeight()
					Plot(x + x1, y + y1, Point(cible\x, cible\y))
				EndIf
			Else
				If x + x1 > -1 And x + x1 < OutputWidth() And y + y1 > -1 And y + y1 < OutputHeight()
					Plot(x + x1, y + y1, #Green)
				EndIf
			EndIf
			
		Next
	Next
	
EndProcedure

Procedure QuadrangleImage_interpolation(x, y, Array a.PointD(1), Array c.PointD(1))
	Protected cible.PointD, coord.pointD, w, h, x1, y1, x_frac.d, x_int, y_int, y_frac.d, red.d, green.d, blue.d
	
	u.PointD\x = a(1)\x - a(0)\x
	u.PointD\y = a(1)\y - a(0)\y
	
	v.PointD\x = a(3)\x - a(0)\x
	v.PointD\y = a(3)\y - a(0)\y
	
	u1.PointD\x = a(2)\x - a(3)\x
	u1.PointD\y = a(2)\y - a(3)\y
	
	w = Round(c(1)\x - c(0)\x, #PB_Round_Up)
	h = Round(c(2)\y - c(0)\y, #PB_Round_Up)
	
	For x1 = 0 To w Step 32
		For y1 = 0 To h Step 32
			COORD\x = x1 / W
			COORD\y = y1 / h
			
			cible\x = a(0)\x + COORD\x * (1 - COORD\y) * u\x + COORD\y * v\x + COORD\y * COORD\x * u1\x
			cible\y = a(0)\y + COORD\x * (1 - COORD\y) * u\y + COORD\y * v\y + COORD\y * COORD\x * u1\y
			
			If x1 < w / 2
				If y1 < h / 2
					Circle(cible\x, cible\y, 2, #Red)
				Else
					Circle(cible\x, cible\y, 2, #Green)
				EndIf
			Else
				If y1 < h / 2
					Circle(cible\x, cible\y, 2, #Blue)
				Else
					Circle(cible\x, cible\y, 2, #Gray)
				EndIf
			EndIf
			
		Next
	Next
	
	
	For x1 = 0 To w
		For y1 = 0 To h
			COORD\x = x1 / W
			COORD\y = y1 / h
			
			cible\x = a(0)\x + COORD\x * (1 - COORD\y) * u\x + COORD\y * v\x + COORD\y * COORD\x * u1\x
			cible\y = a(0)\y + COORD\x * (1 - COORD\y) * u\y + COORD\y * v\y + COORD\y * COORD\x * u1\y
			
			
			If cible\x > 1 And cible\x < OutputWidth() - 2 And cible\y > 1 And cible\y < OutputHeight() - 2
				If x + x1 > -1 And x + x1 < OutputWidth() And y + y1 > -1 And y + y1 < OutputHeight()
					
					x_int = Int(cible\x)
					y_int = Int(cible\y)
					
					x_frac = cible\x - x_int
					y_frac = cible\y - y_int
					
					color = Point(x_int, y_int)
					red = Red(color) * (1-x_frac) * (1-y_frac)
					green = Green(color) * (1-x_frac) * (1-y_frac)
					blue = Blue(color) * (1-x_frac) * (1-y_frac)
					
					color = Point(x_int + 1, y_int)
					red = red + Red(color) * x_frac * (1-y_frac)
					green = green + Green(color) * x_frac * (1-y_frac)
					blue = blue + Blue(color) * x_frac * (1-y_frac)
					
					color = Point(x_int, y_int + 1)
					red = red + Red(color) * (1-x_frac) * y_frac
					green = green + Green(color) * (1-x_frac) * y_frac
					blue = blue + Blue(color) * (1-x_frac) * y_frac
					
					color = Point(x_int + 1, y_int + 1)
					red = red + Red(color) * x_frac * y_frac
					green = green + Green(color) * x_frac * y_frac
					blue = blue + Blue(color) * x_frac * y_frac
					
					
					Plot(x + x1, y + y1, RGB(red, green, blue))
				EndIf
			Else
				If x + x1 > -1 And x + x1 < OutputWidth() And y + y1 > -1 And y + y1 < OutputHeight()
					Plot(x + x1, y + y1, #Green)
				EndIf
			EndIf
			
		Next
	Next
	
EndProcedure



Dim pti.PointD(3)
Dim pt_milieux.PointD(3)
Dim pt_rect.PointD(3)

;{ init des points

dev = 220
screen12.POINT\x = 400
screen12.POINT\y = 300

With pti(0)
	\x = -400 + dev + screen12\x
	\y = -300 + dev + screen12\y
EndWith

With pti(1)
	\x = 400 - dev + screen12\x
	\y = -300 + dev + screen12\y
EndWith

With pti(2)
	\x = 400 - dev + screen12\x
	\y = 300 - dev + screen12\y
EndWith

With pti(3)
	\x = -400 + dev + screen12\x
	\y = 300 - dev + screen12\y
EndWith
;}


Macro DessinARRAY(a, mod, couleur)
	LineXY(a(i)\x, a(i)\y, a((i + 1)%mod)\x, a((i + 1)%mod)\y, couleur)
	Circle(a(i)\x, a(i)\y, 4, couleur)
EndMacro

CalculD(pti(), pt_milieux(), pt_rect())

mode = 1

;}


Repeat
	
	event = WaitWindowEvent(50)
	
	;{ Déplacements des points, et clavier
	If event = #PB_Event_Menu
		Select EventMenu()
			Case 0
				event = #PB_Event_CloseWindow
				
			Case 1 To 4
				pti(EventMenu() - 1)\x = WindowMouseX(wd)
				pti(EventMenu() - 1)\y = WindowMouseY(wd)
				
				CalculD(pti(), pt_milieux(), pt_rect())
				
			Case 5
				mode = - mode
				
		EndSelect
	EndIf
	;}
	
	;{ dessin
	
	StartDrawing(CanvasOutput(0))
		
		Box(0, 0, OutputWidth(), OutputHeight(), 0)
		
		For i = 0 To 3
			DrawText(pti(i)\x, pti(i)\y, Str(i + 1))
			
			DessinARRAY(pti, 4, #Red)
			DessinARRAY(pt_milieux, 4, #Green)
			DessinARRAY(pt_rect, 4, #Blue)
		Next
		
		LineXY(pt_milieux(0)\x, pt_milieux(0)\y, pt_milieux(2)\x, pt_milieux(2)\y, RGB(0, 200, 0))
		LineXY(pt_milieux(1)\x, pt_milieux(1)\y, pt_milieux(3)\x, pt_milieux(3)\y, RGB(0, 200, 0))
		
		
		If mode = 1
			QuadrangleImage(0, 0, pti(), pt_rect())
			DrawText(0, OutputHeight() - 40, "[Espace] : Normal")
		Else
			QuadrangleImage_interpolation(0, 0, pti(), pt_rect())
			DrawText(0, OutputHeight() - 40, "[Espace] : Interpolé")
		EndIf
		
		DrawText(0, OutputHeight() - 20, "Appuyer sur la touche 1, 2, 3 ou 4, pour déplacer le point correspondant")
	StopDrawing()
	
	;}
	
	
	
Until event = #PB_Event_CloseWindow

End
Dernière modification par graph100 le jeu. 25/avr./2013 5:24, modifié 2 fois.
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Demivec
Messages : 91
Inscription : sam. 18/sept./2010 18:13

Re: Passage Quadrangle à rectangle

Message par Demivec »

Excellent! :)
Avatar de l’utilisateur
MLD
Messages : 1124
Inscription : jeu. 05/févr./2009 17:58
Localisation : Bretagne

Re: Passage Quadrangle à rectangle

Message par MLD »

@ salut graph100
Tu fais un concour avec LSI :?: :mrgreen:
Bon courage il est fort le bougre :lol: :lol:
Avatar de l’utilisateur
graph100
Messages : 1318
Inscription : sam. 21/mai/2005 17:50

Re: Passage Quadrangle à rectangle

Message par graph100 »

Non, j'ai juste un projet en cours pour un logiciel de scans d'image, et j'ai eu besoin de cette transformation.
Il s'est trouvé que je l'ai codé et posté juste après LSI :lol:

Mais profitez en !
_________________________________________________
Mon site : CeriseCode (Attention Chantier perpétuel ;))
Répondre