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
|
Procedure SmoothResize(APNG: TPngImage; ANuWidth, ANuHeight: Integer);
Var
xscale, yscale: Single;
sfrom_y, sfrom_x: Single;
ifrom_y, ifrom_x: Integer;
to_y, to_x: Integer;
weight_x, weight_y: Array [0 .. 1] Of Single;
weight: Single;
new_red, new_green: Integer;
new_blue, new_alpha: Integer;
new_colortype: Integer;
total_red, total_green: Single;
total_blue, total_alpha: Single;
IsAlpha: Boolean;
ix, iy: Integer;
bTmp: TPngImage;
sli, slo: pRGBLine;
ali, alo: pbytearray;
Begin
If (ANuWidth = APNG.Width) And (ANuHeight = APNG.Height) Then
Exit;
If Not(APNG.Header.ColorType In [COLOR_RGBALPHA, COLOR_RGB]) Then
Raise Exception.Create('Only COLOR_RGBALPHA and COLOR_RGB formats' +
' are supported');
IsAlpha := APNG.Header.ColorType In [COLOR_RGBALPHA];
If IsAlpha Then
new_colortype := COLOR_RGBALPHA
Else
new_colortype := COLOR_RGB;
bTmp := TPngImage.CreateBlank(new_colortype, 8, ANuWidth, ANuHeight);
xscale := bTmp.Width / (APNG.Width - 1);
yscale := bTmp.Height / (APNG.Height - 1);
For to_y := 0 To bTmp.Height - 1 Do
Begin
sfrom_y := to_y / yscale;
ifrom_y := Trunc(sfrom_y);
weight_y[1] := sfrom_y - ifrom_y;
weight_y[0] := 1 - weight_y[1];
For to_x := 0 To bTmp.Width - 1 Do
Begin
sfrom_x := to_x / xscale;
ifrom_x := Trunc(sfrom_x);
weight_x[1] := sfrom_x - ifrom_x;
weight_x[0] := 1 - weight_x[1];
total_red := 0.0;
total_green := 0.0;
total_blue := 0.0;
total_alpha := 0.0;
For ix := 0 To 1 Do
Begin
For iy := 0 To 1 Do
Begin
sli := APNG.Scanline[ifrom_y + iy];
new_red := sli[ifrom_x + ix].rgbtRed;
new_green := sli[ifrom_x + ix].rgbtGreen;
new_blue := sli[ifrom_x + ix].rgbtBlue;
weight := weight_x[ix] * weight_y[iy];
total_red := total_red + new_red * weight;
total_green := total_green + new_green * weight;
total_blue := total_blue + new_blue * weight;
If IsAlpha Then
Begin
ali := APNG.AlphaScanline[ifrom_y + iy];
new_alpha := ali[ifrom_x + ix];
total_alpha := total_alpha + new_alpha * weight;
End;
End;
End;
slo := bTmp.Scanline[to_y];
slo[to_x].rgbtRed := Round(total_red);
slo[to_x].rgbtGreen := Round(total_green);
slo[to_x].rgbtBlue := Round(total_blue);
If IsAlpha Then
Begin
alo := bTmp.AlphaScanline[to_y];
alo[to_x] := Round(total_alpha);
End;
End;
End;
APNG.Assign(bTmp);
bTmp.Free;
End; |
Partager