1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| type
TRGBArray = array[0..0] of TRGBTriple; // élément de bitmap (API windows)
pRGBArray = ^TRGBArray; // type pointeur vers tableau 3 octets 24 bits
var ScanLinesS : array[Word] of pRGBArray; // BmpSource : Tableau de lignes
ScanLinesD : array[Word] of PRGBArray; // BmpDestination
var Sinus: array[0..360] of Double; // Sinus et Cosinus précalculés
Cosin: array[0..360] of Double;
procedure PreCalculSinCos;
var i: integer; a: Double;
begin for i := 0 to 360 do begin
a := i;
Sinus[i] := sin((pi * a) / 180);
Cosin[i] := cos((pi * a) / 180);
end;
end;
function BmpRotation(bmpS : tBitMap; ADeg : integer; AAA : boolean) : tBitMap;
// Rotation de bmpSource vers BmpDestination avec angle de ADeg en degrés
// Formules de la rotation de centre xc, yc et d'angle a :
// x2 = xc + (x1-xc) * cos(a) - (y1-yc) * sin(a)
// y2 = yc + (x1-xc) * sin(a) + (y1-yc) * cos(a)
var dx, dy : single; // pour les calculs en réels
xS, yS : integer; // pixel source
xD, yD : integer; // pixel destination
xc, yc : integer; // Centre de rotation
wyx, wyy : integer;
dxc,dyc : integer; // Décalages entre centre de rotation de Bmp-Result et centre du Bmp-Source
i : integer;
R, G, B : integer; // Pour moyenne Anti-Alias de couleurs de 4 points
begin
while ADeg > 360 do ADeg := ADeg - 360; // ramener angle dans [0..360]
while ADeg < 0 do ADeg := 360 + ADeg;
// Bmp Result :
Result:=tBitMap.Create;
with Result do begin
PixelFormat:=pf24bit;
Width:=Round(sqrt(sqr(bmpS.Width)+sqr(bmpS.Height))); // = diagonale du BmpSource
Height:=Width; // Bmp carré
xc := width shr 1; yc := height shr 1; // centre de la rotation
end;
dxc:=(Result.Width -bmpS.Width) div 2; // décalage entre centre du Bmp Carré et bmSource
dyc:=(Result.Height-bmpS.Height) div 2;
for i := 0 to BmpS.height-1 do ScanLinesS[i]:= BmpS.scanline[i]; // Source
for i := 0 to Result.height-1 do ScanLinesD[i]:= Result.scanline[i]; // Destination
for yD := 0 to Result.height-1 do begin
dy := yD - yc; // distance y au centre
wyx := round(dy*Sinus[ADeg]);
wyy := round(dy*Cosin[ADeg]);
for xD := 0 to Result.width-1 do begin
dx := xD - xc; // distance x au centre
xS := xc + round(dx * Cosin[ADeg]) - wyx - dxc;
yS := yc + round(dx * Sinus[ADeg]) + wyy - dyc;
if (xS>=0) and (yS>=0) and (xS<bmpS.width-1) and (yS<BmpS.height-1) then begin
R := ScanLinesS[yS, xS].rgbtred;
G := ScanLinesS[yS, xS].rgbtgreen;
B := ScanLinesS[yS, xS].rgbtblue;
if AAA and (xS+1 < bmpS.width-1) and (yS+1 < bmpS.height-1) then begin // adoucissement Anti-Alias
R := (R + ScanLinesS[yS, xS+1].Rgbtred
+ ScanLinesS[yS+1,xS ].Rgbtred
+ ScanLinesS[yS+1,xS+1].Rgbtred) div 4;
G := (G + ScanLinesS[yS ,xS+1].Rgbtgreen
+ ScanLinesS[yS+1,xS ].Rgbtgreen
+ ScanLinesS[yS+1,xS+1].rgbtgreen) div 4;
B := (B + ScanLinesS[yS ,xS+1].Rgbtblue
+ ScanLinesS[yS+1,xS ].Rgbtblue
+ ScanLinesS[yS+1,xS+1].rgbtblue) div 4;
end; //if (xS+1 ...
ScanLinesD[yD,xD].Rgbtred := R;
ScanLinesD[yD,xD].Rgbtgreen := G;
ScanLinesD[yD,xD].Rgbtblue := B;
end //if (xS>=0) ...
else begin // Couleur de remplissage pas de correspondance en entrée
ScanLinesD[yD,xD].Rgbtred := 255;
ScanLinesD[yD,xD].Rgbtgreen := 255;
ScanLinesD[yD,xD].Rgbtblue := 255;
end;
end; // for xD
end; // for yD
Result.TransparentColor:=clWhite; // Ligne ajoutée
end; |
Partager