cs_barbichette
Messages postés220Date d'inscriptionlundi 30 octobre 2000StatutMembreDernière intervention15 juillet 2013 13 oct. 2008 à 11:30
ah, juste un point, j'avais pas regardé en détail...
Dans ce genre de transformation, il vaut mieux faire les calculs à l'envers.
Parcourir tous les pixels de l'image finale et regarder où il est dans l'image initiale.
ainsi, on est sur qu'il n'y a pas de trou et c'est avec ce calcul qu'on utilise mon interpolation.
Je vais essayer de retrouver l'algo en inversant les calculs.
cs_barbichette
Messages postés220Date d'inscriptionlundi 30 octobre 2000StatutMembreDernière intervention15 juillet 2013 13 oct. 2008 à 11:10
histoire de mettre mon grain de sel. J'avais fait la même chose, mais avec des calculs en réel et non dans les entiers.
Ainsi, quand tu cherche le pixel de l'image de départ, tu peux "facilement" faire une interpolation des couleurs, surtout si on étire l'image.
Sinon, c'est bien foutu..
barbichette
cs_cantador
Messages postés4720Date d'inscriptiondimanche 26 février 2006StatutModérateurDernière intervention31 juillet 202113 9 oct. 2008 à 20:59
@Spatul:
j'avais coché "verification des limite" dans un autre programme et l'avais conservé..
cela dit, tu devrais définir les deux paramètres du tableau à deux demensions.
SetLength(TSLFinal, BmpFinal.Height);
sinon ça marche, quelques soucis de saturation et d'aliasing..
original 8/10.
bon courage
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 201610 9 oct. 2008 à 19:00
Ah excusez-moi j'avais pas vidé le cache, mes messages n'étaient pas apparents.
Cordialement, Bacterius !
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 201610 9 oct. 2008 à 19:00
Pourquoi tous mes messages sont supprimés ? D'abord sur l'horloge binaire, maintenant ici ?
Est-ce moi qui bug ?
Cordialement, Bacterius !
blueperfect
Messages postés234Date d'inscriptionmardi 13 novembre 2007StatutMembreDernière intervention21 novembre 2013 9 oct. 2008 à 18:15
Et plus que quatre points ?
Bacterius
Messages postés3792Date d'inscriptionsamedi 22 décembre 2007StatutMembreDernière intervention 3 juin 201610 9 oct. 2008 à 17:52
Pas mal !
Un petit peu d'anti-aliasing sur les bords et c'est nikel !
D'ailleurs ça serait particulièrement simple vu que tu connais les côtés à lisser ... Un petit flou léger sur les bords :)
Cordialement, Bacterius !
blueperfect
Messages postés234Date d'inscriptionmardi 13 novembre 2007StatutMembreDernière intervention21 novembre 2013 9 oct. 2008 à 17:49
Pour le recto verso : 2 TBitmap qui sont dessinés l'un derriere l'autre !
Pour le transparent : en 24 bits, il suffit d'utiliser une transparent color avec une constant que tu définis...Je suis sur Embarcadero (newsgroup) pour la définir...
DH
Spatul
Messages postés12Date d'inscriptionmercredi 21 août 2002StatutMembreDernière intervention 9 octobre 2008 9 oct. 2008 à 17:01
Merci CIREC, j'ai mis à jour la source d'après tes conseils d'optimisation (je n'avais pas pensé à regrouper les calculs redondants).
Je serai intéressé par le 32bits, ça me permettrai de dessiner l'image déformé en mode "transparent". en ce qui concerne les pointeurs à la place des tableaux, il faudrait que je me penche un peu plus dessus :-)
j'ai modifié le code pour éviter des calcules répétitifs et inutiles:
function Distorsion(AQuadrangle:TQuadrangle; ABitmap:TBitmap; BkColor:TColor):TBitmap;
var
TabScanLine, TSLFinal : array of pRVBArray;
BmpOrigin : TBitmap;
BmpFinal : TBitmap;
v, u, x, y, xd, yd : integer;
RQWidth, RQHeight : integer;
TauxY, TauxX : real;
DistAB, DistDC, PosXAB, PosXDC, TmpX : real;
DistAD, DistBC, PosYAD, PosYBC, TmpY : real;
begin
//--calcul de la zone rectangle (rectangle maitre) contenant le quadrangle
Ox := min(min(AQuadrangle.A.X,AQuadrangle.B.X),min(AQuadrangle.C.X,AQuadrangle.D.X));
Oy := min(min(AQuadrangle.A.Y,AQuadrangle.B.Y),min(AQuadrangle.C.Y,AQuadrangle.D.Y));
Fx := max(max(AQuadrangle.A.X,AQuadrangle.B.X),max(AQuadrangle.C.X,AQuadrangle.D.X));
Fy := max(max(AQuadrangle.A.Y,AQuadrangle.B.Y),max(AQuadrangle.C.Y,AQuadrangle.D.Y));
RQWidth := Fx-Ox;
RQHeight := Fy-Oy;
//--création du bitmap final qui sera transféré à "result"
BmpFinal := TBitmap.Create;
BmpFinal.HandleType := bmDIB;
BmpFinal.PixelFormat := pf24Bit;
BmpFinal.Height := RQHeight;
BmpFinal.Width := RQWidth;
BmpFinal.Canvas.Brush.Color := BkColor;
BmpFinal.Canvas.FillRect(rect(0,0,RQWidth,RQHeight));
//--mise à l'échelle du bitmap d'origine par rapport au rectangle maitre
BmpOrigin.Canvas.StretchDraw(rect(0,0,RQWidth,RQHeight),ABitmap);
//--définir la taille des tableaux dynamiques
SetLength(TabScanLine,BmpOrigin.Height);
SetLength(TSLFinal,BmpFinal.Height);
// transférer les données (pixels) dans chaque tableau
For v:=0 to RQHeight-1 do
begin
// transférer les information de l'image dans les tableaux
TabScanLine[v] := BmpOrigin.ScanLine[v];
TSLFinal[v] := BmpFinal.ScanLine[v];
end;
//--Transférer les pixels au bon endroit
DistAD := AQuadrangle.D.Y-AQuadrangle.A.Y;
DistBC := AQuadrangle.C.Y-AQuadrangle.B.Y;
DistAB := AQuadrangle.B.X-AQuadrangle.A.X;
DistDC := AQuadrangle.C.X-AQuadrangle.D.X;
{Pour chaque pixel, calcule le taux de positionnement de x et y}
For v:=1 to BmpOrigin.Height-1 do
begin
TauxY := v / BmpOrigin.Height;
PosYAD := AQuadrangle.A.Y-OY+(DistAD*TauxY);
PosYBC := AQuadrangle.B.Y-OY+(DistBC*TauxY);
For u := 1 to BmpOrigin.Width-1 do
begin
TauxX := u / BmpOrigin.Width;
PosXAB := AQuadrangle.A.X-OX+(DistAB*TauxX);
PosXDC := AQuadrangle.D.X-OX+(DistDC*TauxX);
le redu est bon mais le code pour y arriver peut et même doit être modifier dans un souci de rapidité mais surtout pour éviter de grosses fuites de mémoire ce qui est malheureusement le cas pour l'instant.
Tu as choisi, dans ta fonction, de créer, en guise de paramètre de sortie, un Bitmap que tu ne libères jamais !!!
Donc chaque appel à "Distorsion" crée un Bitmap qui reste en mémoire à la fin du programme.
pour éviter ces fuites il faut modifier comme suit:
{déformation & rendu de l'image}
procedure TForm1.Render;
var aBMP: TBitmap;
begin
...
// deformation //
aBMP := Distorsion(Quadrangle,Image,clWhite);
try
RenderBuffer.Canvas.Draw(OX,OY, aBMP);
finally
aBMP.Free;
end;
...
end;
Rapidement:
comme tu ne changes pas les valeurs RGB des pixels il n'est pas utile de les affecter individuellement
{transfère les pixels au bon emplacement}
TSLFinal[y,x].rgbtRed := TabScanLine[v,u].rgbtRed;
TSLFinal[y,x].rgbtGreen := TabScanLine[v,u].rgbtGreen;
TSLFinal[y,x].rgbtBlue := TabScanLine[v,u].rgbtBlue;
peut être remplacer par:
{transfère les pixels au bon emplacement}
TSLFinal[y,x] := TabScanLine[v,u];
c'est valable aussi pour les deux suivants:
if (x0) then
TSLFinal[y,x+1] := TabScanLine[v,u];
et
if (y0) then
TSLFinal[y+1,x] := TabScanLine[v,u];
j'en reste là pour l'instant ;)
Spatul
Messages postés12Date d'inscriptionmercredi 21 août 2002StatutMembreDernière intervention 9 octobre 2008 9 oct. 2008 à 11:41
BLUEPERFECT : pour un recto/verso ? si c'est juste pour inverser/retourner l'image, on peut le faire comme ça :
// Mirroir vertical ou horizontal du bitmap
procedure Flip(ABmp:TBitmap; Sens:TSensFlip);
begin
if Sens=fVertical then ABmp.Canvas.StretchDraw(Rect(0,ABmp.height-1,ABmp.width,-1),ABmp);
if Sens=fHorizontal then ABmp.Canvas.StretchDraw(Rect(ABmp.width-1,0,-1,ABmp.Height),ABmp);
end;
CANTADOR : Je vais vérifier l'erreur. Ça se déclenche dans quelles conditions ?
SIMONPELLOQUIN : Je vais rajouter cette option dans la prochaine mise à jour du source.
Merci à vous en tout cas !
sp40
Messages postés1276Date d'inscriptionmardi 28 octobre 2003StatutContributeurDernière intervention 3 juillet 201515 9 oct. 2008 à 09:47
Salut,
Vraiment pas mal du tout... Si tu pouvais juste ajouter de quoi charger et enregistrer une image transformée, ça serait tip-top !
Simon
cs_cantador
Messages postés4720Date d'inscriptiondimanche 26 février 2006StatutModérateurDernière intervention31 juillet 202113 9 oct. 2008 à 09:46
Bonjour,
un petit souci sur :
SetLength(TSLFinal, BmpFinal.Height);
et
TSLFinal[y, x].rgbtRed := TabScanLine[v, u].rgbtRed;
->> erreur d'étendue..
blueperfect
Messages postés234Date d'inscriptionmardi 13 novembre 2007StatutMembreDernière intervention21 novembre 2013 8 oct. 2008 à 22:47
Au fait, tu ferais comment pour un recto/verso ?
blueperfect
Messages postés234Date d'inscriptionmardi 13 novembre 2007StatutMembreDernière intervention21 novembre 2013 8 oct. 2008 à 21:41
13 oct. 2008 à 11:30
Dans ce genre de transformation, il vaut mieux faire les calculs à l'envers.
Parcourir tous les pixels de l'image finale et regarder où il est dans l'image initiale.
ainsi, on est sur qu'il n'y a pas de trou et c'est avec ce calcul qu'on utilise mon interpolation.
Je vais essayer de retrouver l'algo en inversant les calculs.
13 oct. 2008 à 11:10
Ainsi, quand tu cherche le pixel de l'image de départ, tu peux "facilement" faire une interpolation des couleurs, surtout si on étire l'image.
Sinon, c'est bien foutu..
barbichette
9 oct. 2008 à 20:59
j'avais coché "verification des limite" dans un autre programme et l'avais conservé..
cela dit, tu devrais définir les deux paramètres du tableau à deux demensions.
SetLength(TSLFinal, BmpFinal.Height);
sinon ça marche, quelques soucis de saturation et d'aliasing..
original 8/10.
bon courage
9 oct. 2008 à 19:00
Cordialement, Bacterius !
9 oct. 2008 à 19:00
Est-ce moi qui bug ?
Cordialement, Bacterius !
9 oct. 2008 à 18:15
9 oct. 2008 à 17:52
Un petit peu d'anti-aliasing sur les bords et c'est nikel !
D'ailleurs ça serait particulièrement simple vu que tu connais les côtés à lisser ... Un petit flou léger sur les bords :)
Cordialement, Bacterius !
9 oct. 2008 à 17:49
Pour le transparent : en 24 bits, il suffit d'utiliser une transparent color avec une constant que tu définis...Je suis sur Embarcadero (newsgroup) pour la définir...
DH
9 oct. 2008 à 17:01
Je serai intéressé par le 32bits, ça me permettrai de dessiner l'image déformé en mode "transparent". en ce qui concerne les pointeurs à la place des tableaux, il faudrait que je me penche un peu plus dessus :-)
9 oct. 2008 à 16:19
j'ai modifié le code pour éviter des calcules répétitifs et inutiles:
function Distorsion(AQuadrangle:TQuadrangle; ABitmap:TBitmap; BkColor:TColor):TBitmap;
var
TabScanLine, TSLFinal : array of pRVBArray;
BmpOrigin : TBitmap;
BmpFinal : TBitmap;
v, u, x, y, xd, yd : integer;
RQWidth, RQHeight : integer;
TauxY, TauxX : real;
DistAB, DistDC, PosXAB, PosXDC, TmpX : real;
DistAD, DistBC, PosYAD, PosYBC, TmpY : real;
begin
//--calcul de la zone rectangle (rectangle maitre) contenant le quadrangle
Ox := min(min(AQuadrangle.A.X,AQuadrangle.B.X),min(AQuadrangle.C.X,AQuadrangle.D.X));
Oy := min(min(AQuadrangle.A.Y,AQuadrangle.B.Y),min(AQuadrangle.C.Y,AQuadrangle.D.Y));
Fx := max(max(AQuadrangle.A.X,AQuadrangle.B.X),max(AQuadrangle.C.X,AQuadrangle.D.X));
Fy := max(max(AQuadrangle.A.Y,AQuadrangle.B.Y),max(AQuadrangle.C.Y,AQuadrangle.D.Y));
RQWidth := Fx-Ox;
RQHeight := Fy-Oy;
//--création d'une copie du bitmap d'origine
BmpOrigin := TBitmap.Create;
BmpOrigin.HandleType := bmDIB;
BmpOrigin.PixelFormat := pf24Bit;
BmpOrigin.Height := RQHeight;
BmpOrigin.Width := RQWidth;
//--création du bitmap final qui sera transféré à "result"
BmpFinal := TBitmap.Create;
BmpFinal.HandleType := bmDIB;
BmpFinal.PixelFormat := pf24Bit;
BmpFinal.Height := RQHeight;
BmpFinal.Width := RQWidth;
BmpFinal.Canvas.Brush.Color := BkColor;
BmpFinal.Canvas.FillRect(rect(0,0,RQWidth,RQHeight));
//--mise à l'échelle du bitmap d'origine par rapport au rectangle maitre
BmpOrigin.Canvas.StretchDraw(rect(0,0,RQWidth,RQHeight),ABitmap);
//--définir la taille des tableaux dynamiques
SetLength(TabScanLine,BmpOrigin.Height);
SetLength(TSLFinal,BmpFinal.Height);
// transférer les données (pixels) dans chaque tableau
For v:=0 to RQHeight-1 do
begin
// transférer les information de l'image dans les tableaux
TabScanLine[v] := BmpOrigin.ScanLine[v];
TSLFinal[v] := BmpFinal.ScanLine[v];
end;
//--Transférer les pixels au bon endroit
DistAD := AQuadrangle.D.Y-AQuadrangle.A.Y;
DistBC := AQuadrangle.C.Y-AQuadrangle.B.Y;
DistAB := AQuadrangle.B.X-AQuadrangle.A.X;
DistDC := AQuadrangle.C.X-AQuadrangle.D.X;
{Pour chaque pixel, calcule le taux de positionnement de x et y}
For v:=1 to BmpOrigin.Height-1 do
begin
TauxY := v / BmpOrigin.Height;
PosYAD := AQuadrangle.A.Y-OY+(DistAD*TauxY);
PosYBC := AQuadrangle.B.Y-OY+(DistBC*TauxY);
For u := 1 to BmpOrigin.Width-1 do
begin
TauxX := u / BmpOrigin.Width;
PosXAB := AQuadrangle.A.X-OX+(DistAB*TauxX);
PosXDC := AQuadrangle.D.X-OX+(DistDC*TauxX);
TmpX := PosXAB+(PosXDC-PosXAB)*TauxY;
TmpY := PosYAD+(PosYBC-PosYAD)*TauxX;
x := round(Int(TmpX));
y := Round(Int(TmpY));
xd := Round(Frac(TmpX));
yd := Round(Frac(TmpY));
{transfère les pixels au bon emplacement}
TSLFinal[y,x] := TabScanLine[v,u];
//pour lever les "trous..."
if (xd>0) and (x0) and (y<BmpOrigin.Height-2) then
TSLFinal[y+1,x] := TabScanLine[v,u];
end;
end;
//--assigne le bitmap final au "result"
result := TBitmap.create;
Result.Assign(bmpFinal);
bmpFinal.Free;
BmpOrigin.free;
end;
mais on peut faire mieux en utilisant des pointeurs à la place des tableaux et en passant en 32bits
9 oct. 2008 à 16:15
A quelle ligne de code et dans quelles conditions apparait l'erreur d'étendue ?
Pour un recto/verso ? Retourner l'image ?
9 oct. 2008 à 15:47
le redu est bon mais le code pour y arriver peut et même doit être modifier dans un souci de rapidité mais surtout pour éviter de grosses fuites de mémoire ce qui est malheureusement le cas pour l'instant.
Tu as choisi, dans ta fonction, de créer, en guise de paramètre de sortie, un Bitmap que tu ne libères jamais !!!
Donc chaque appel à "Distorsion" crée un Bitmap qui reste en mémoire à la fin du programme.
pour éviter ces fuites il faut modifier comme suit:
{déformation & rendu de l'image}
procedure TForm1.Render;
var aBMP: TBitmap;
begin
...
// deformation //
aBMP := Distorsion(Quadrangle,Image,clWhite);
try
RenderBuffer.Canvas.Draw(OX,OY, aBMP);
finally
aBMP.Free;
end;
...
end;
Rapidement:
comme tu ne changes pas les valeurs RGB des pixels il n'est pas utile de les affecter individuellement
{transfère les pixels au bon emplacement}
TSLFinal[y,x].rgbtRed := TabScanLine[v,u].rgbtRed;
TSLFinal[y,x].rgbtGreen := TabScanLine[v,u].rgbtGreen;
TSLFinal[y,x].rgbtBlue := TabScanLine[v,u].rgbtBlue;
peut être remplacer par:
{transfère les pixels au bon emplacement}
TSLFinal[y,x] := TabScanLine[v,u];
c'est valable aussi pour les deux suivants:
if (x0) then
TSLFinal[y,x+1] := TabScanLine[v,u];
et
if (y0) then
TSLFinal[y+1,x] := TabScanLine[v,u];
j'en reste là pour l'instant ;)
9 oct. 2008 à 11:41
// Mirroir vertical ou horizontal du bitmap
procedure Flip(ABmp:TBitmap; Sens:TSensFlip);
begin
if Sens=fVertical then ABmp.Canvas.StretchDraw(Rect(0,ABmp.height-1,ABmp.width,-1),ABmp);
if Sens=fHorizontal then ABmp.Canvas.StretchDraw(Rect(ABmp.width-1,0,-1,ABmp.Height),ABmp);
end;
CANTADOR : Je vais vérifier l'erreur. Ça se déclenche dans quelles conditions ?
SIMONPELLOQUIN : Je vais rajouter cette option dans la prochaine mise à jour du source.
Merci à vous en tout cas !
9 oct. 2008 à 09:47
Vraiment pas mal du tout... Si tu pouvais juste ajouter de quoi charger et enregistrer une image transformée, ça serait tip-top !
Simon
9 oct. 2008 à 09:46
un petit souci sur :
SetLength(TSLFinal, BmpFinal.Height);
et
TSLFinal[y, x].rgbtRed := TabScanLine[v, u].rgbtRed;
->> erreur d'étendue..
8 oct. 2008 à 22:47
8 oct. 2008 à 21:41
DH