DÉFORMER UNE IMAGE AUX DIMENSIONS D'UN QUADRANGLE QUELCONQUE

Messages postés
237
Date d'inscription
mardi 13 novembre 2007
Statut
Membre
Dernière intervention
21 novembre 2013
- - Dernière réponse : cs_barbichette
Messages postés
243
Date d'inscription
lundi 30 octobre 2000
Statut
Membre
Dernière intervention
15 juillet 2013
- 13 oct. 2008 à 11:30
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/48145-deformer-une-image-aux-dimensions-d-un-quadrangle-quelconque

cs_barbichette
Messages postés
243
Date d'inscription
lundi 30 octobre 2000
Statut
Membre
Dernière intervention
15 juillet 2013
-
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és
243
Date d'inscription
lundi 30 octobre 2000
Statut
Membre
Dernière intervention
15 juillet 2013
-
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és
4716
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
27 mars 2018
10 -
@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és
3793
Date d'inscription
samedi 22 décembre 2007
Statut
Membre
Dernière intervention
3 juin 2016
6 -
Ah excusez-moi j'avais pas vidé le cache, mes messages n'étaient pas apparents.

Cordialement, Bacterius !
Bacterius
Messages postés
3793
Date d'inscription
samedi 22 décembre 2007
Statut
Membre
Dernière intervention
3 juin 2016
6 -
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és
237
Date d'inscription
mardi 13 novembre 2007
Statut
Membre
Dernière intervention
21 novembre 2013
-
Et plus que quatre points ?
Bacterius
Messages postés
3793
Date d'inscription
samedi 22 décembre 2007
Statut
Membre
Dernière intervention
3 juin 2016
6 -
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és
237
Date d'inscription
mardi 13 novembre 2007
Statut
Membre
Dernière intervention
21 novembre 2013
-
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és
12
Date d'inscription
mercredi 21 août 2002
Statut
Membre
Dernière intervention
9 octobre 2008
-
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 :-)
cirec
Messages postés
3809
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
1 septembre 2019
34 -
ben non ... voici la suite ^^

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
Spatul
Messages postés
12
Date d'inscription
mercredi 21 août 2002
Statut
Membre
Dernière intervention
9 octobre 2008
-
Bonjour,

A quelle ligne de code et dans quelles conditions apparait l'erreur d'étendue ?

Pour un recto/verso ? Retourner l'image ?
cirec
Messages postés
3809
Date d'inscription
vendredi 23 juillet 2004
Statut
Modérateur
Dernière intervention
1 septembre 2019
34 -
Salut,

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és
12
Date d'inscription
mercredi 21 août 2002
Statut
Membre
Dernière intervention
9 octobre 2008
-
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és
1284
Date d'inscription
mardi 28 octobre 2003
Statut
Contributeur
Dernière intervention
3 juillet 2015
11 -
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és
4716
Date d'inscription
dimanche 26 février 2006
Statut
Modérateur
Dernière intervention
27 mars 2018
10 -
Bonjour,

un petit souci sur :

SetLength(TSLFinal, BmpFinal.Height);
et
TSLFinal[y, x].rgbtRed := TabScanLine[v, u].rgbtRed;

->> erreur d'étendue..
blueperfect
Messages postés
237
Date d'inscription
mardi 13 novembre 2007
Statut
Membre
Dernière intervention
21 novembre 2013
-
Au fait, tu ferais comment pour un recto/verso ?
blueperfect
Messages postés
237
Date d'inscription
mardi 13 novembre 2007
Statut
Membre
Dernière intervention
21 novembre 2013
-
Splendeurs....

DH