How to rotate a TBitmap smoothly (Views: 27)
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; |