2009. augusztus 27., csütörtök
How to rotate a TBitmap smoothly
Problem/Question/Abstract:
I would like to rotate a TBitmap using a smooth algorithm but without clipping the corner of the bitmap. The size of the rotated bitmap change according to the angle.
Answer:
cx, cy represent the center of rotation.
function IntToByte(i: integer): byte;
begin
if (i > 255) then
Result := 255
else if (i < 0) then
Result := 0
else
Result := i;
end;
function TrimInt(i, Min, Max: integer): integer;
begin
if (i > Max) then
Result := Max
else if (i < Min) then
Result := Min
else
Result := i;
end;
procedure SmoothRotate(Src, Dst: TBitmap; cx, cy: integer; Angle: Extended);
type
TFColor = record
b, g, r: Byte
end;
var
Top, Bottom, Left, Right, eww, nsw, fx, fy, wx, wy: Extended;
cAngle, sAngle: Double;
xDiff, yDiff, ifx, ify, px, py, ix, iy, x, y: Integer;
nw, ne, sw, se: TFColor;
P1, P2, P3: PByteArray;
begin
Src.PixelFormat := pf24Bit;
Dst.PixelFormat := pf24Bit;
Angle := -Angle * Pi / 180;
sAngle := Sin(Angle);
cAngle := Cos(Angle);
xDiff := (Dst.Width - Src.Width) div 2;
yDiff := (Dst.Height - Src.Height) div 2;
for y := 0 to Dst.Height - 1 do
begin
P3 := Dst.scanline[y];
py := 2 * (y - cy) + 1;
for x := 0 to Dst.Width - 1 do
begin
px := 2 * (x - cx) + 1;
fx := (((px * cAngle - py * sAngle) - 1) / 2 + cx) - xDiff;
fy := (((px * sAngle + py * cAngle) - 1) / 2 + cy) - yDiff;
ifx := Round(fx);
ify := Round(fy);
if (ifx > -1) and (ifx < Src.Width) and (ify > -1) and (ify < Src.Height) then
begin
eww := fx - ifx;
nsw := fy - ify;
iy := TrimInt(ify + 1, 0, Src.Height - 1);
ix := TrimInt(ifx + 1, 0, Src.Width - 1);
P1 := Src.scanline[ify];
P2 := Src.scanline[iy];
nw.r := P1[ifx * 3];
nw.g := P1[ifx * 3 + 1];
nw.b := P1[ifx * 3 + 2];
ne.r := P1[ix * 3];
ne.g := P1[ix * 3 + 1];
ne.b := P1[ix * 3 + 2];
sw.r := P2[ifx * 3];
sw.g := P2[ifx * 3 + 1];
sw.b := P2[ifx * 3 + 2];
se.r := P2[ix * 3];
se.g := P2[ix * 3 + 1];
se.b := P2[ix * 3 + 2];
Top := nw.b + eww * (ne.b - nw.b);
Bottom := sw.b + eww * (se.b - sw.b);
P3[x * 3 + 2] := IntToByte(Round(Top + nsw * (Bottom - Top)));
Top := nw.g + eww * (ne.g - nw.g);
Bottom := sw.g + eww * (se.g - sw.g);
P3[x * 3 + 1] := IntToByte(Round(Top + nsw * (Bottom - Top)));
Top := nw.r + eww * (ne.r - nw.r);
Bottom := sw.r + eww * (se.r - sw.r);
P3[x * 3] := IntToByte(Round(Top + nsw * (Bottom - Top)));
end;
end;
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése