Page 1 sur 1

Passage Quadrangle à rectangle

Publié : jeu. 25/avr./2013 1:35
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

Re: Passage Quadrangle à rectangle

Publié : jeu. 25/avr./2013 1:48
par Demivec
Excellent! :)

Re: Passage Quadrangle à rectangle

Publié : jeu. 25/avr./2013 15:00
par MLD
@ salut graph100
Tu fais un concour avec LSI :?: :mrgreen:
Bon courage il est fort le bougre :lol: :lol:

Re: Passage Quadrangle à rectangle

Publié : jeu. 25/avr./2013 21:53
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 !