Redimensionnement par interpolation bilineaire

0/5 (2 avis)

Vue 12 145 fois - Téléchargée 496 fois

Description

unité contenant une procedure permettant de redimensionner un bitmap par interpolation bilineaire (methode plus fiable que le redimensionnement brute (par stretchdraw par ex) car l'indesirable effet d'aliasing est attenué, donc le rendu est plus doux).
PROCEDURE REDIMENSIONNEMENT_PAR_INTERPOLATION_BILINEAIRE(VAR BMP : TBitmap; CONST Largeur, Hauteur : integer);

Source / Exemple :


//Module permettant d'effectuer un Redimensionnement par Interpolation BiLinéaire
//l'Image résultante est bien meilleur qu'avec un redimensionnement brute (problème d'Aliasing)
//Créé par MORLET Alexandre en Mai 2002
//Basé sur le Code Source en C de Christophe Boyanique et Emmanuel Pinard
//L'Interpolation BiLinéaire consiste à utiliser les 4 points les
//plus proches des cordonnées calculées dans l'image source en les pondérant par des
//cooefficients inversement proportionnels à la distance et dont la somme vaut 1

UNIT U_Interpolation_BiLineaire;

INTERFACE

USES Windows, Graphics,Math;

PROCEDURE REDIMENSIONNEMENT_PAR_INTERPOLATION_BILINEAIRE (VAR BMP : TBitmap; CONST Largeur, Hauteur : integer);

IMPLEMENTATION

PROCEDURE REDIMENSIONNEMENT_PAR_INTERPOLATION_BILINEAIRE (VAR BMP : TBitmap; CONST Largeur, Hauteur : integer);
TYPE
TRGBArray = ARRAY[0..0] OF TRGBTriple;
PRGBArray = ^TRGBArray;
VAR
X, Y : integer; //coordonnées image source
I, J : integer; //coordonnées image destination
Diff : ARRAY[0..3] OF double; //distance pour l'interpolation bilinéaire
DX, DY : ARRAY[0..3] OF double;  // Coordonnees image source (points voisins, reelles)
IX, IY : ARRAY[0..3] OF integer;   // Coordonnees image source (points voisins, entieres)
XR, YR : double; // Coordonnees image source (reelles)
R, G, B : ARRAY[0..3] OF integer;
TabScanlineBMP, TabScanlineBMPF : ARRAY OF PRGBArray;
V : double;
BMPF : TBitmap;
BEGIN

BMP.pixelFormat := pf24bit;

BMPF := TBitmap.Create;

TRY
   WITH BMPF DO
        BEGIN
        Width := Largeur;
        Height := Hauteur;
        pixelFormat := pf24bit;
        END;

   setLength(TabScanlineBMP, BMP.Height);
   setLength(TabScanlineBMPF, BMPF.Height);

   FOR X := 0 TO BMP.Height - 1 DO
       TabScanlineBMP[X] := BMP.Scanline[X];

   FOR X := 0 TO BMPF.Height - 1 DO
       TabScanlineBMPF[X] := BMPF.Scanline[X];

   FOR J := 0 TO BMPF.Height - 1 DO
       BEGIN
       FOR I := 0 TO BMPF.Width - 1 DO
	   BEGIN
	   X := Trunc( -0.5 + I * BMP.Width / BMPF.Width );
	   Y := Trunc( -0.5 + J * BMP.Height / BMPF.Height );

	   X := Min(X, BMP.Width - 1);
	   Y := Min(Y, BMP.Height - 1);
	   X := Max(X, 0);
	   Y := Max(Y, 0);

	   XR := -0.5 + I * BMP.Width / BMPF.Width;
	   YR := -0.5 + J * BMP.Height / BMPF.Height;

	   XR := Min(XR, BMP.Width - 1);
	   YR := Min(YR, BMP.Height - 1);
	   XR := Max(XR, 0);
	   YR := Max(YR, 0);

	   IF (X = XR) AND (Y = YR) THEN
              BEGIN
              TabScanlineBMPF[J,I].RGBTRed := TabScanlineBMP[Y,X].RGBTRed;
              TabScanlineBMPF[J,I].RGBTGreen := TabScanlineBMP[Y,X].RGBTGreen;
              TabScanlineBMPF[J,I].RGBTBlue := TabScanlineBMP[Y,X].RGBTBlue;
              END
           ELSE
	      BEGIN
	      DX[0] := XR - Floor(XR);
	      DY[0] := YR - Floor(YR);
              IX[0] := Trunc(Floor(XR));
              IY[0] := Trunc(Floor(YR));

	      DX[1] := 1.0 - DX[0];
	      DY[1] := DY[0];
              IX[1] := IX[0] + 1;
              IY[1] := IY[0];

	      DX[2] := DX[0];
	      DY[2] := 1.0 - DY[0];
              IX[2] := IX[0];
              IY[2] := IY[0] + 1;

	      DX[3] := DX[1];
	      DY[3] := DY[2];
              IX[3] := IX[1];
              IY[3] := IY[2];

	      IF (DX[0] = 0) THEN
		 BEGIN
		 Diff[0] := 1.0 / Sqrt( DX[0]*DX[0] + DY[0]*DY[0] );
		 Diff[2] := 1.0 / Sqrt( DX[2]*DX[2] + DY[2]*DY[2] );
		 V := Diff[0] + Diff[2];

		 R[0] := TabScanlineBMP[IY[0],IX[0]].RGBTRed;
		 G[0] := TabScanlineBMP[IY[0],IX[0]].RGBTGreen;
		 B[0] := TabScanlineBMP[IY[0],IX[0]].RGBTBlue;

		 R[2] := TabScanlineBMP[IY[2],IX[2]].RGBTRed;
		 G[2] := TabScanlineBMP[IY[2],IX[2]].RGBTGreen;
		 B[2] := TabScanlineBMP[IY[2],IX[2]].RGBTBlue;

		 TabScanlineBMPF[J,I].RGBTRed := Trunc((R[0] * Diff[0] + R[2] * Diff[2]) / V);
		 TabScanlineBMPF[J,I].RGBTGreen := Trunc((G[0] * Diff[0] + G[2] * Diff[2]) / V);
		 TabScanlineBMPF[J,I].RGBTBlue := Trunc((B[0] * Diff[0] + B[2] * Diff[2]) / V);
		 END
              ELSE IF (DY[0] = 0) THEN
                      BEGIN
		      Diff[0] := 1.0 / Sqrt (DX[0]*DX[0] + DY[0]*DY[0]);
		      Diff[1] := 1.0 / Sqrt (DX[1]*DX[1] + DY[1]*DY[1]);
		      V := Diff[0] + Diff[1];

		      R[0] := TabScanlineBMP[IY[0], IX[0]].RGBTRed;
		      G[0] := TabScanlineBMP[IY[0], IX[0]].RGBTGreen;
		      B[0] := TabScanlineBMP[IY[0], IX[0]].RGBTBlue;

                      R[1] := TabScanlineBMP[IY[1], IX[1]].RGBTRed;
		      G[1] := TabScanlineBMP[IY[1], IX[1]].RGBTGreen;
		      B[1] := TabScanlineBMP[IY[1], IX[1]].RGBTBlue;

		      TabScanlineBMPF[J,I].RGBTRed := Trunc((R[0] * Diff[0] + R[1] * Diff[1]) / V);
		      TabScanlineBMPF[J,I].RGBTGreen := Trunc((G[0] * Diff[0] + G[1] * Diff[1]) / V);
		      TabScanlineBMPF[J,I].RGBTBlue := Trunc((B[0] * Diff[0] + B[1] * Diff[1]) / V);
                      END
              ELSE
		      BEGIN
		      Diff[0] := 1.0 / Sqrt( DX[0]*DX[0] + DY[0]*DY[0]);
		      Diff[1] := 1.0 / Sqrt( DX[1]*DX[1] + DY[1]*DY[1]);
		      Diff[2] := 1.0 / Sqrt( DX[2]*DX[2] + DY[2]*DY[2]);
		      Diff[3] := 1.0 / Sqrt( DX[3]*DX[3] + DY[3]*DY[3]);
		      V := Diff[0] + Diff[1] + Diff[2] + Diff[3];

		      R[0] := TabScanlineBMP[IY[0], IX[0]].RGBTRed;
		      G[0] := TabScanlineBMP[IY[0], IX[0]].RGBTGreen;
		      B[0] := TabScanlineBMP[IY[0], IX[0]].RGBTBlue;

		      R[1] := TabScanlineBMP[IY[1], IX[1]].RGBTRed;
		      G[1] := TabScanlineBMP[IY[1], IX[1]].RGBTGreen;
		      B[1] := TabScanlineBMP[IY[1], IX[1]].RGBTBlue;

		      R[2] := TabScanlineBMP[IY[2], IX[2]].RGBTRed;
		      G[2] := TabScanlineBMP[IY[2], IX[2]].RGBTGreen;
		      B[2] := TabScanlineBMP[IY[2], IX[2]].RGBTBlue;

		      R[3] := TabScanlineBMP[IY[3], IX[3]].RGBTRed;
		      G[3] := TabScanlineBMP[IY[3], IX[3]].RGBTGreen;
		      B[3] := TabScanlineBMP[IY[3], IX[3]].RGBTBlue;

		      TabScanlineBMPF[J,I].RGBTRed :=
		      Trunc((R[0] * Diff[0] + R[1] * Diff[1] + R[2] * Diff[2] + R[3] * Diff[3]) / V);

		      TabScanlineBMPF[J,I].RGBTGreen :=
		      Trunc((G[0] * Diff[0] + G[1] * Diff[1] + G[2] * Diff[2] + G[3] * Diff[3]) / V);

		      TabScanlineBMPF[J,I].RGBTBlue :=
		      Trunc((B[0] * Diff[0] + B[1] * Diff[1] + B[2] * Diff[2] + B[3] * Diff[3]) / V);
		      END;
              END;
           END;
       END;
BMP.Assign(BMPF);

FINALLY BMPF.Free; TabScanlineBMP := nil ; TabScanlineBMPF := nil; END;

END;

END.

Conclusion :


sur http://ps2superpage.ifrance.com/ps2superpage/resize.zip, vous trouverez un programme utilitaire que j'ai codé (pour DCMP3 v1.3, un soft Dreamcast qui permet entre autres de visualiser des images JPEG sur sa TV pour ceux qui connaissent) exploitant mon unité de redimensionnement.
Reste à coder l'unité de redimensionnement par la méthode bicubique :P

Codes Sources

A voir également

Ajouter un commentaire Commentaires
cs_code1 Messages postés 22 Date d'inscription vendredi 30 juillet 2004 Statut Membre Dernière intervention 21 octobre 2004
31 juil. 2004 à 00:09
bien
mai tu pourai etuliser le code de delphi prog
il est plus cour
SnakeBurn Messages postés 11 Date d'inscription mercredi 22 mai 2002 Statut Membre Dernière intervention 12 juin 2002
27 mai 2002 à 16:56
T'aurais pu mettre un zip

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.