Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

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


Information sur la source

Catégorie :Graphique Classé sous : déformer, quadrangle, image, redimenssioner, distortion Niveau : Initié Date de création : 08/10/2008 Date de mise à jour : 20/10/2008 12:05:42 Vu / téléchargé: 2 698 / 353

Note :
8,33 / 10 - par 3 personnes
8,33 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

Commentaire sur cette source (17)
Ajouter un commentaire et/ou une note

Description

Cliquez pour voir la capture en taille normale
Petite source permettant de déformer une image (TBitmap) aux dimensions d'un quadrangle quelconque (points A, B, C, D).
Reste certainement moyen d'optimiser tout ça...
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Historique

09 octobre 2008 16:38:09 :
Prise en compte des conseils d'optimisation de CIREC. Ajout d'un bouton permettant de charger un bitmap.
09 octobre 2008 16:58:09 :
Mise à jours des optimisations de CIREC (merci ;-) )
20 octobre 2008 12:05:42 :
Implémentation du lissage (anti-aliasing) des bords de l'image.

Commentaires et avis

signaler à un administrateur
Commentaire de blueperfect le 08/10/2008 21:41:14

Splendeurs....

DH

signaler à un administrateur
Commentaire de blueperfect le 08/10/2008 22:47:17

Au fait, tu ferais comment pour un recto/verso ?

signaler à un administrateur
Commentaire de cantador le 09/10/2008 09:46:53

Bonjour,

un petit souci sur :

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

->> erreur d'étendue..

signaler à un administrateur
Commentaire de simonpelloquin le 09/10/2008 09:47:49 9/10

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

signaler à un administrateur
Commentaire de Spatul le 09/10/2008 11:41:28

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 !

signaler à un administrateur
Commentaire de cirec le 09/10/2008 15:47:02 administrateur CS

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 (x<BmpOrigin.Width-2) and (xd>0) then
     TSLFinal[y,x+1] := TabScanLine[v,u];
et
   if (y<BmpOrigin.Height-2) and (yd>0) then
     TSLFinal[y+1,x] := TabScanLine[v,u];

j'en reste là pour l'instant ;)

signaler à un administrateur
Commentaire de Spatul le 09/10/2008 16:15:33

Bonjour,

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

Pour un recto/verso ? Retourner l'image ?

signaler à un administrateur
Commentaire de cirec le 09/10/2008 16:19:17 administrateur CS

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 (x<BmpOrigin.Width-2) then
     TSLFinal[y,x+1] := TabScanLine[v,u];
   if (yd>0) 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

signaler à un administrateur
Commentaire de Spatul le 09/10/2008 17:01:39

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 :-)

signaler à un administrateur
Commentaire de blueperfect le 09/10/2008 17:49:09

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

signaler à un administrateur
Commentaire de Bacterius le 09/10/2008 17:52:49

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 !

signaler à un administrateur
Commentaire de blueperfect le 09/10/2008 18:15:10

Et plus que quatre points ?

signaler à un administrateur
Commentaire de Bacterius le 09/10/2008 19:00:27

Pourquoi tous mes messages sont supprimés ? D'abord sur l'horloge binaire, maintenant ici ?

Est-ce moi qui bug ?

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de Bacterius le 09/10/2008 19:00:51

Ah excusez-moi j'avais pas vidé le cache, mes messages n'étaient pas apparents.

Cordialement, Bacterius !

signaler à un administrateur
Commentaire de cantador le 09/10/2008 20:59:32 8/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

signaler à un administrateur
Commentaire de barbichette le 13/10/2008 11:10:46 8/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

signaler à un administrateur
Commentaire de barbichette le 13/10/2008 11:30:01

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.

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Image de fond dans un TreeView [ par Valérie ] Bonjour, J'utilise une application DELPHI6 CLX et je n'aarive pas à avoir une image de fond dans mon TreeView. L'événement OnPaint n'existe pas. Si image du bureau a intervalle regulier [ par tarik ] salut je voudrais faire des sauvegardes de l'etat du bureau (une sorte d'imprime ecran) a intervalle regulier image ds un richedit [ par sebrs1 ] comment inserer une image ds un richedit? tbitbtn avec image format jpeg [ par vib ] existe il un composant ou une solution pour avoir un bouton du genre bitbtn avec une image au format jpeg ?A+ Image dans une TStatusBar !!! [ par MAsterC ] Comment fait-on pour mettre un Tprogresbar et un petit dessin dans l'item TStatusBar ????POUR PLUS DE DÉTAILS ALLER VOIR DANS INTERNET EXPLORER EN BAS Sacré Mikey, c jamais ou il est! :: Prob localisation souris [ par Gysmo ] Salut a tous!Voila j'ai creer sur mon prog des bontons avec des TImage superposé. Kan on click ca change d'image, une image bouton normal, une image b Texte sur une image [ par Gysmo ] Comment arrivé à écrir du texte sur une image puis la sauvegarder comme tel??!Merci Imprimer une image et un texte sur la même feuille [ par zeusnul ] Bonjour,J'aimerais pouvoir imprimer une image et un texte sur la même feuille, mais je suis dans l'incapacité de trouver ça dans l'aide de delphi. Je ImageList ... Help ! ;-) [ par HEproduct ] Bonjour, je voudrai stocker des images de trés petites tailles dans une image lit et récupérer les noms dans une list box. Après quoi l'utilisateur en Image [ par sebastienbro ] Comment faire pour effacer le contenu d'une image ?


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Téléchargements

Logiciels à télécharger sur le même thème :

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,421 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.