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
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.