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