Redimensionnement par interpolation bilineaire

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

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.