用Windows的PlgBlt(HDC dest,const point *parr, )好像可以 你看一下帮助
http://www.efg2.com/lab/ImageProcessing/RotateScanline.htm 或者参考以下两段代码: image2.Picture :=image15.Picture ; for i:=0 to image1.Height do for j:=0 to image1.Width do image1.Canvas.Pixels[(-i+image2.height),j]:=image2.Canvas.Pixels[j,i];一个控件的源代码!
function RotateBitmap(Bitmap: TBitmap; Angle: Double; Color: TColor): TBitmap;
procedure Register;
implementation
uses Consts, Math;
// Bitmaps must be 24 bit pixel format. // Angle is in degrees. function RotateBitmap(Bitmap: TBitmap; Angle: Double; Color: TColor): TBitmap; const MaxPixelCount = 32768; type PRGBTripleArray = ^TRGBTripleArray; TRGBTripleArray = array[0..MaxPixelCount] of TRGBTriple; var CosTheta: Extended; SinTheta: Extended; xSrc, ySrc: Integer; xDst, yDst: Integer; xODst, yODst: Integer; xOSrc, yOSrc: Integer; xPrime, yPrime: Integer; srcRow, dstRow: PRGBTripleArray; begin Result := TBitmap.Create; SinCos(Angle * Pi / 180, SinTheta, CosTheta); if (SinTheta * CosTheta) < 0 then begin Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta)); Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta)); end else begin Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta)); Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta)); end; with Result.Canvas do begin Brush.Color := Color; Brush.Style := bsSolid; FillRect(ClipRect); end; Result.PixelFormat := pf24bit; Bitmap.PixelFormat := pf24bit; xODst := Result.Width div 2; yODst := Result.Height div 2; xOSrc := Bitmap.Width div 2; yOSrc := Bitmap.Height div 2; for ySrc := Max(Bitmap.Height, Result.Height)-1 downto 0 do begin yPrime := ySrc - yODst; for xSrc := Max(Bitmap.Width, Result.Width)-1 downto 0 do begin xPrime := xSrc - xODst; xDst := Round(xPrime * CosTheta - yPrime * SinTheta) + xOSrc; yDst := Round(xPrime * SinTheta + yPrime * CosTheta) + yOSrc; if (yDst >= 0) and (yDst < Bitmap.Height) and (xDst >= 0) and (xDst < Bitmap.Width) and (ySrc >= 0) and (ySrc < Result.Height) and (xSrc >= 0) and (xSrc < Result.Width) then begin srcRow := Bitmap.ScanLine[yDst]; dstRow := Result.Scanline[ySrc]; dstRow[xSrc] := srcRow[xDst]; end; end; end; end;
procedure TRotateImage.CreateRotatedBitmap; var OrgBitmap: TBitmap; RotBitmap: TBitmap; begin if (Picture.Width > 0) and (Picture.Height > 0) then begin OrgBitmap := TBitmap.Create; OrgBitmap.Width := Picture.Width; OrgBitmap.Height := Picture.Height; with OrgBitmap.Canvas do begin Brush.Color := Color; Brush.Style := bsSolid; FillRect(ClipRect); end; OrgBitmap.Canvas.Draw(0, 0, Picture.Graphic); RotBitmap := RotateBitmap(OrgBitmap, Angle, Color); if UniqueSize then begin with RotatedBitmap.Canvas do begin Brush.Color := Color; Brush.Style := bsSolid; FillRect(ClipRect); end; RotatedBitmap.Width := Round(Sqrt(Sqr(Picture.Width+2) + Sqr(Picture.Height+2))); RotatedBitmap.Height := RotatedBitmap.Width; RotatedBitmap.Transparent := Transparent; if Center and not Stretch then RotatedBitmap.Canvas.Draw((RotatedBitmap.Width - RotBitmap.Width) div 2, (RotatedBitmap.Height - RotBitmap.Height) div 2, RotBitmap) else RotatedBitmap.Canvas.Draw(0, 0, RotBitmap); RotBitmap.Free; end else begin RotatedBitmap.Free; FRotatedBitmap := RotBitmap; end; OrgBitmap.Free; end else begin RotatedBitmap.Width := 0; RotatedBitmap.Height := 0; end; if AutoSize then AdjustSize; end;
destructor TRotateImage.Destroy; begin Picture.Free; RotatedBitmap.Free; inherited Destroy; end;
function TRotateImage.GetPalette: HPALETTE; begin Result := 0; if Picture.Graphic <> nil then Result := Picture.Graphic.Palette; end;
function TRotateImage.DestRect: TRect; begin if Stretch then Result := ClientRect else if Center then Result := Bounds((Width - RotatedBitmap.Width) div 2, (Height - RotatedBitmap.Height) div 2, RotatedBitmap.Width, RotatedBitmap.Height) else Result := Rect(0, 0, RotatedBitmap.Width, RotatedBitmap.Height); end;
procedure TRotateImage.Paint; var Save: Boolean; begin if not RotatedBitmap.Empty then begin Save := FDrawing; FDrawing := True; try with inherited Canvas do StretchDraw(DestRect, RotatedBitmap); finally FDrawing := Save; end; end; if csDesigning in ComponentState then with inherited Canvas do begin Pen.Style := psDash; Brush.Style := bsClear; Rectangle(0, 0, Width, Height); end; end;
procedure TRotateImage.Loaded; begin inherited Loaded; PictureChanged(Self); end;
function TRotateImage.DoPaletteChange: Boolean; var ParentForm: TCustomForm; G: TGraphic; begin Result := False; G := Picture.Graphic; if Visible and (not (csLoading in ComponentState)) and (G <> nil) and (G.PaletteModified) then begin if (G.Palette = 0) then G.PaletteModified := False else begin ParentForm := GetParentForm(Self); if Assigned(ParentForm) and ParentForm.Active and Parentform.HandleAllocated then begin if FDrawing then ParentForm.Perform(WM_QUERYNEWPALETTE, 0, 0) else PostMessage(ParentForm.Handle, WM_QUERYNEWPALETTE, 0, 0); Result := True; G.PaletteModified := False; end; end; end; end;
procedure TRotateImage.Progress(Sender: TObject; Stage: TProgressStage; PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string); begin if IncrementalDisplay and RedrawNow then begin if DoPaletteChange then Update else Paint; end; if Assigned(OnProgress) then OnProgress(Sender, Stage, PercentDone, RedrawNow, R, Msg); end;
function TRotateImage.GetCanvas: TCanvas; var Bitmap: TBitmap; begin if Picture.Graphic = nil then begin Bitmap := TBitmap.Create; try Bitmap.Width := Width; Bitmap.Height := Height; Picture.Graphic := Bitmap; finally Bitmap.Free; end; end; if Picture.Graphic is TBitmap then Result := TBitmap(Picture.Graphic).Canvas else raise EInvalidOperation.Create(SImageCanvasNeedsBitmap); end;
procedure TRotateImage.CMColorChanged(var Msg: TMessage); begin inherited; CreateRotatedBitmap; end;
procedure TRotateImage.SetCenter(Value: Boolean); begin if Value <> Center then begin FCenter := Value; PictureChanged(Self) end; end;
procedure TRotateImage.SetPicture(Value: TPicture); begin Picture.Assign(Value); end;
procedure TRotateImage.SetStretch(Value: Boolean); begin if Value <> Stretch then begin FStretch := Value; PictureChanged(Self); end; end;
procedure TRotateImage.SetTransparent(Value: Boolean); begin if Value <> Transparent then begin FTransparent := Value; PictureChanged(Self); end; end;
procedure TRotateImage.SetAngle(Value: Extended); begin if Value <> Angle then begin FAngle := Value; PictureChanged(Self); end; end;
{$IFNDEF RI_D4orHigher} procedure TRotateImage.SetAutoSize(Value: Boolean); begin if Value <> AutoSizethen begin FAutoSize := Value; if FAutoSize then AdjustSize; end; end; {$ENDIF}
procedure TRotateImage.SetUniqueSize(Value: Boolean); begin if Value <> UniqueSize then begin FUniqueSize := Value; PictureChanged(Self); end; end;
procedure TRotateImage.PictureChanged(Sender: TObject); var G: TGraphic; begin if not (csLoading in ComponentState) then begin G := Picture.Graphic; if G <> nil then begin if not ((G is TMetaFile) or (G is TIcon)) then G.Transparent := FTransparent; if (not G.Transparent) and (Stretch or (RotatedBitmap.Width >= Width) and (RotatedBitmap.Height >= Height)) then ControlStyle := ControlStyle + [csOpaque] else ControlStyle := ControlStyle - [csOpaque]; if DoPaletteChange and FDrawing then Update; end else ControlStyle := ControlStyle - [csOpaque]; CreateRotatedBitmap; if AutoSize and (Picture.Width > 0) and (Picture.Height > 0) then SetBounds(Left, Top, RotatedBitmap.Width, RotatedBitmap.Height); if not FDrawing then Invalidate; end; end;
{$IFDEF RI_D4orHigher} function TRotateImage.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; begin Result := True; if not (csDesigning in ComponentState) or (RotatedBitmap.Width > 0) and (RotatedBitmap.Height > 0) then begin if Align in [alNone, alLeft, alRight] then NewWidth := RotatedBitmap.Width; if Align in [alNone, alTop, alBottom] then NewHeight := RotatedBitmap.Height; end; end; {$ENDIF}
{$IFNDEF RI_D4orHigher} procedure TRotateImage.AdjustSize; begin if not (csDesigning in ComponentState) or (RotatedBitmap.Width > 0) and (RotatedBitmap.Height > 0) then begin if Align in [alNone, alLeft, alRight] then Width := RotatedBitmap.Width; if Align in [alNone, alTop, alBottom] then Height := RotatedBitmap.Height; end; end; {$ENDIF}
procedure Register; begin RegisterComponents('Samples', [TRotateImage]); end;
end.
procedure Rotate(Bmp,Dst:TFastRGB;cx,cy:Integer;Angle:Extended); var cAngle, sAngle: Double; xDiff, yDiff, xpr,ypr, ix,iy, px,py, x,y: Integer; Tmp: PFColor;{what means?} begin Angle:=-Angle*Pi/180; sAngle:=Sin(Angle); cAngle:=Cos(Angle); xDiff:=(Dst.Width-Bmp.Width)div 2; yDiff:=(Dst.Height-Bmp.Height)div 2; Tmp:=Dst.Bits;{what means?} for y:=0 to Dst.Height-1 do begin py:=2*(y-cy)+1; for x:=0 to Dst.Width-1 do begin px:=2*(x-cx)+1; xpr:=Round(px*cAngle-py*sAngle); ypr:=Round(px*sAngle+py*cAngle); ix:=((xpr-1)div 2+cx)-xDiff; iy:=((ypr-1)div 2+cy)-yDiff; if(ix>-1)and(ix<Bmp.Width)and(iy>-1)and(iy<Bmp.Height)then Tmp^:=Bmp.Pixels[iy,ix]; {what means?} Inc(Tmp); end; Tmp:=Pointer(Integer(Tmp)+Dst.Gap); {what means?} end; end;
原理: cos(Alpha), sin(Alpha), 0 只需要用源矩阵乘以 -sin(Alpha),cos(Alpha), 0 0, 0, 1 下载控件,有现成的例子及DEMO! http://www.crosswinds.net/~khojasteh/delphi-components.html TRotateImage v1.21 This component is a visual component similar to TImage with ability to rotate the image in any arbitrary angle. TRotateImage can be used on Delphi 3, 4, and 5.
用Windows的PlgBlt(HDC dest,const point *parr,,,,,hbitmap bmask,0,0), 数组parr共三个点,第一个对应source的左上点,第二个对应source的右上点, 第三个对应source的左下点,bmask 设为0
to : shinesi(阿shine) 能给个例子吗?
Dest, Source: TImage; Pt: array[0..2] of TPoint; begin Pt[0] := Point(Source.Width,0); Pt[1] := Point(Source.Width,Source.Height); Pt[2] := Point(0,Source.Height); PlgBlt(Dest.Canvas.Handle,Pt,Source.Canvas.Handle, 0,0,Source.Width,Source.Height,0,0,0); end;
你看一下帮助
或者参考以下两段代码:
image2.Picture :=image15.Picture ;
for i:=0 to image1.Height do
for j:=0 to image1.Width do
image1.Canvas.Pixels[(-i+image2.height),j]:=image2.Canvas.Pixels[j,i];一个控件的源代码!
unit RotImg;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TRotateImage = class(TGraphicControl)
private
FPicture: TPicture;
FOnProgress: TProgressEvent;
FStretch: Boolean;
FCenter: Boolean;
FIncrementalDisplay: Boolean;
FTransparent: Boolean;
FDrawing: Boolean;
FAngle: Extended;
{$IFNDEF RI_D4orHigher}
FAutoSize: Boolean;
{$ENDIF}
FUniqueSize: Boolean;
FRotatedBitmap: TBitmap;
function GetCanvas: TCanvas;
procedure PictureChanged(Sender: TObject);
procedure SetCenter(Value: Boolean);
procedure SetPicture(Value: TPicture);
procedure SetStretch(Value: Boolean);
procedure SetTransparent(Value: Boolean);
procedure SetAngle(Value: Extended);
{$IFNDEF RI_D4orHigher}
procedure SetAutoSize(Value: Boolean);
{$ENDIF}
procedure SetUniqueSize(Value: Boolean);
procedure CreateRotatedBitmap;
procedure CMColorChanged(var Msg: TMessage); message CM_COLORCHANGED;
protected
{$IFDEF RI_D4orHigher}
function CanAutoSize(var NewWidth, NewHeight: Integer): Boolean; override;
{$ELSE}
procedure AdjustSize;
{$ENDIF}
function DestRect: TRect;
function DoPaletteChange: Boolean;
function GetPalette: HPALETTE; override;
procedure Paint; override;
procedure Loaded; override;
procedure Progress(Sender: TObject; Stage: TProgressStage;
PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string); dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Canvas: TCanvas read GetCanvas;
property RotatedBitmap: TBitmap read FRotatedBitmap;
published
property Align;
{$IFDEF RI_D4orHigher}
property Anchors;
{$ENDIF}
property Angle: Extended read FAngle write SetAngle;
{$IFDEF RI_D4orHigher}
property AutoSize;
{$ELSE}
property AutoSize: Boolean read FAutoSize write SetAutoSize default False;
{$ENDIF}
property Center: Boolean read FCenter write SetCenter default False;
property Color;
{$IFDEF RI_D4orHigher}
property Constraints;
{$ENDIF}
property DragCursor;
{$IFDEF RI_D4orHigher}
property DragKind;
{$ENDIF}
property DragMode;
property Enabled;
property IncrementalDisplay: Boolean read FIncrementalDisplay write FIncrementalDisplay default False;
property ParentColor;
property ParentShowHint;
property Picture: TPicture read FPicture write SetPicture;
property PopupMenu;
property ShowHint;
property Stretch: Boolean read FStretch write SetStretch default False;
property Transparent: Boolean read FTransparent write SetTransparent default False;
property UniqueSize: Boolean read FUniqueSize write SetUniqueSize default True;
property Visible;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
{$IFDEF RI_D4orHigher}
property OnEndDock;
{$ENDIF}
property OnEndDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
{$IFDEF RI_D4orHigher}
property OnStartDock;
{$ENDIF}
property OnStartDrag;
end;
function RotateBitmap(Bitmap: TBitmap; Angle: Double; Color: TColor): TBitmap;
procedure Register;
implementation
uses
Consts, Math;
// Bitmaps must be 24 bit pixel format.
// Angle is in degrees.
function RotateBitmap(Bitmap: TBitmap; Angle: Double; Color: TColor): TBitmap;
const
MaxPixelCount = 32768;
type
PRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..MaxPixelCount] of TRGBTriple;
var
CosTheta: Extended;
SinTheta: Extended;
xSrc, ySrc: Integer;
xDst, yDst: Integer;
xODst, yODst: Integer;
xOSrc, yOSrc: Integer;
xPrime, yPrime: Integer;
srcRow, dstRow: PRGBTripleArray;
begin
Result := TBitmap.Create;
SinCos(Angle * Pi / 180, SinTheta, CosTheta);
if (SinTheta * CosTheta) < 0 then
begin
Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta));
Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta));
end
else
begin
Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta));
Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta));
end;
with Result.Canvas do
begin
Brush.Color := Color;
Brush.Style := bsSolid;
FillRect(ClipRect);
end;
Result.PixelFormat := pf24bit;
Bitmap.PixelFormat := pf24bit;
xODst := Result.Width div 2;
yODst := Result.Height div 2;
xOSrc := Bitmap.Width div 2;
yOSrc := Bitmap.Height div 2;
for ySrc := Max(Bitmap.Height, Result.Height)-1 downto 0 do
begin
yPrime := ySrc - yODst;
for xSrc := Max(Bitmap.Width, Result.Width)-1 downto 0 do
begin
xPrime := xSrc - xODst;
xDst := Round(xPrime * CosTheta - yPrime * SinTheta) + xOSrc;
yDst := Round(xPrime * SinTheta + yPrime * CosTheta) + yOSrc;
if (yDst >= 0) and (yDst < Bitmap.Height) and
(xDst >= 0) and (xDst < Bitmap.Width) and
(ySrc >= 0) and (ySrc < Result.Height) and
(xSrc >= 0) and (xSrc < Result.Width) then
begin
srcRow := Bitmap.ScanLine[yDst];
dstRow := Result.Scanline[ySrc];
dstRow[xSrc] := srcRow[xDst];
end;
end;
end;
end;
procedure TRotateImage.CreateRotatedBitmap;
var
OrgBitmap: TBitmap;
RotBitmap: TBitmap;
begin
if (Picture.Width > 0) and (Picture.Height > 0) then
begin
OrgBitmap := TBitmap.Create;
OrgBitmap.Width := Picture.Width;
OrgBitmap.Height := Picture.Height;
with OrgBitmap.Canvas do
begin
Brush.Color := Color;
Brush.Style := bsSolid;
FillRect(ClipRect);
end;
OrgBitmap.Canvas.Draw(0, 0, Picture.Graphic);
RotBitmap := RotateBitmap(OrgBitmap, Angle, Color);
if UniqueSize then
begin
with RotatedBitmap.Canvas do
begin
Brush.Color := Color;
Brush.Style := bsSolid;
FillRect(ClipRect);
end;
RotatedBitmap.Width := Round(Sqrt(Sqr(Picture.Width+2) + Sqr(Picture.Height+2)));
RotatedBitmap.Height := RotatedBitmap.Width;
RotatedBitmap.Transparent := Transparent;
if Center and not Stretch then
RotatedBitmap.Canvas.Draw((RotatedBitmap.Width - RotBitmap.Width) div 2,
(RotatedBitmap.Height - RotBitmap.Height) div 2, RotBitmap)
else
RotatedBitmap.Canvas.Draw(0, 0, RotBitmap);
RotBitmap.Free;
end
else
begin
RotatedBitmap.Free;
FRotatedBitmap := RotBitmap;
end;
OrgBitmap.Free;
end
else
begin
RotatedBitmap.Width := 0;
RotatedBitmap.Height := 0;
end;
if AutoSize then AdjustSize;
end;
constructor TRotateImage.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle + [csReplicatable];
FPicture := TPicture.Create;
FPicture.OnChange := PictureChanged;
FPicture.OnProgress := Progress;
FUniqueSize := True;
FRotatedBitmap := TBitmap.Create;
Height := 105;
Width := 105;
end;
destructor TRotateImage.Destroy;
begin
Picture.Free;
RotatedBitmap.Free;
inherited Destroy;
end;
function TRotateImage.GetPalette: HPALETTE;
begin
Result := 0;
if Picture.Graphic <> nil then
Result := Picture.Graphic.Palette;
end;
function TRotateImage.DestRect: TRect;
begin
if Stretch then
Result := ClientRect
else if Center then
Result := Bounds((Width - RotatedBitmap.Width) div 2,
(Height - RotatedBitmap.Height) div 2,
RotatedBitmap.Width, RotatedBitmap.Height)
else
Result := Rect(0, 0, RotatedBitmap.Width, RotatedBitmap.Height);
end;
procedure TRotateImage.Paint;
var
Save: Boolean;
begin
if not RotatedBitmap.Empty then
begin
Save := FDrawing;
FDrawing := True;
try
with inherited Canvas do
StretchDraw(DestRect, RotatedBitmap);
finally
FDrawing := Save;
end;
end;
if csDesigning in ComponentState then
with inherited Canvas do
begin
Pen.Style := psDash;
Brush.Style := bsClear;
Rectangle(0, 0, Width, Height);
end;
end;
procedure TRotateImage.Loaded;
begin
inherited Loaded;
PictureChanged(Self);
end;
function TRotateImage.DoPaletteChange: Boolean;
var
ParentForm: TCustomForm;
G: TGraphic;
begin
Result := False;
G := Picture.Graphic;
if Visible and (not (csLoading in ComponentState)) and
(G <> nil) and (G.PaletteModified) then
begin
if (G.Palette = 0) then
G.PaletteModified := False
else
begin
ParentForm := GetParentForm(Self);
if Assigned(ParentForm) and ParentForm.Active and Parentform.HandleAllocated then
begin
if FDrawing then
ParentForm.Perform(WM_QUERYNEWPALETTE, 0, 0)
else
PostMessage(ParentForm.Handle, WM_QUERYNEWPALETTE, 0, 0);
Result := True;
G.PaletteModified := False;
end;
end;
end;
end;
procedure TRotateImage.Progress(Sender: TObject; Stage: TProgressStage;
PercentDone: Byte; RedrawNow: Boolean; const R: TRect; const Msg: string);
begin
if IncrementalDisplay and RedrawNow then
begin
if DoPaletteChange then Update
else Paint;
end;
if Assigned(OnProgress) then OnProgress(Sender, Stage, PercentDone, RedrawNow, R, Msg);
end;
function TRotateImage.GetCanvas: TCanvas;
var
Bitmap: TBitmap;
begin
if Picture.Graphic = nil then
begin
Bitmap := TBitmap.Create;
try
Bitmap.Width := Width;
Bitmap.Height := Height;
Picture.Graphic := Bitmap;
finally
Bitmap.Free;
end;
end;
if Picture.Graphic is TBitmap then
Result := TBitmap(Picture.Graphic).Canvas
else
raise EInvalidOperation.Create(SImageCanvasNeedsBitmap);
end;
procedure TRotateImage.CMColorChanged(var Msg: TMessage);
begin
inherited;
CreateRotatedBitmap;
end;
procedure TRotateImage.SetCenter(Value: Boolean);
begin
if Value <> Center then
begin
FCenter := Value;
PictureChanged(Self)
end;
end;
procedure TRotateImage.SetPicture(Value: TPicture);
begin
Picture.Assign(Value);
end;
procedure TRotateImage.SetStretch(Value: Boolean);
begin
if Value <> Stretch then
begin
FStretch := Value;
PictureChanged(Self);
end;
end;
procedure TRotateImage.SetTransparent(Value: Boolean);
begin
if Value <> Transparent then
begin
FTransparent := Value;
PictureChanged(Self);
end;
end;
procedure TRotateImage.SetAngle(Value: Extended);
begin
if Value <> Angle then
begin
FAngle := Value;
PictureChanged(Self);
end;
end;
{$IFNDEF RI_D4orHigher}
procedure TRotateImage.SetAutoSize(Value: Boolean);
begin
if Value <> AutoSizethen
begin
FAutoSize := Value;
if FAutoSize then AdjustSize;
end;
end;
{$ENDIF}
procedure TRotateImage.SetUniqueSize(Value: Boolean);
begin
if Value <> UniqueSize then
begin
FUniqueSize := Value;
PictureChanged(Self);
end;
end;
procedure TRotateImage.PictureChanged(Sender: TObject);
var
G: TGraphic;
begin
if not (csLoading in ComponentState) then
begin
G := Picture.Graphic;
if G <> nil then
begin
if not ((G is TMetaFile) or (G is TIcon)) then
G.Transparent := FTransparent;
if (not G.Transparent) and (Stretch or (RotatedBitmap.Width >= Width)
and (RotatedBitmap.Height >= Height)) then
ControlStyle := ControlStyle + [csOpaque]
else
ControlStyle := ControlStyle - [csOpaque];
if DoPaletteChange and FDrawing then Update;
end
else
ControlStyle := ControlStyle - [csOpaque];
CreateRotatedBitmap;
if AutoSize and (Picture.Width > 0) and (Picture.Height > 0) then
SetBounds(Left, Top, RotatedBitmap.Width, RotatedBitmap.Height);
if not FDrawing then Invalidate;
end;
end;
{$IFDEF RI_D4orHigher}
function TRotateImage.CanAutoSize(var NewWidth, NewHeight: Integer): Boolean;
begin
Result := True;
if not (csDesigning in ComponentState) or
(RotatedBitmap.Width > 0) and (RotatedBitmap.Height > 0) then
begin
if Align in [alNone, alLeft, alRight] then
NewWidth := RotatedBitmap.Width;
if Align in [alNone, alTop, alBottom] then
NewHeight := RotatedBitmap.Height;
end;
end;
{$ENDIF}
{$IFNDEF RI_D4orHigher}
procedure TRotateImage.AdjustSize;
begin
if not (csDesigning in ComponentState) or
(RotatedBitmap.Width > 0) and (RotatedBitmap.Height > 0) then
begin
if Align in [alNone, alLeft, alRight] then
Width := RotatedBitmap.Width;
if Align in [alNone, alTop, alBottom] then
Height := RotatedBitmap.Height;
end;
end;
{$ENDIF}
procedure Register;
begin
RegisterComponents('Samples', [TRotateImage]);
end;
end.
var
cAngle,
sAngle: Double;
xDiff,
yDiff,
xpr,ypr,
ix,iy,
px,py,
x,y: Integer;
Tmp: PFColor;{what means?}
begin
Angle:=-Angle*Pi/180;
sAngle:=Sin(Angle);
cAngle:=Cos(Angle);
xDiff:=(Dst.Width-Bmp.Width)div 2;
yDiff:=(Dst.Height-Bmp.Height)div 2;
Tmp:=Dst.Bits;{what means?}
for y:=0 to Dst.Height-1 do
begin
py:=2*(y-cy)+1;
for x:=0 to Dst.Width-1 do
begin
px:=2*(x-cx)+1;
xpr:=Round(px*cAngle-py*sAngle);
ypr:=Round(px*sAngle+py*cAngle);
ix:=((xpr-1)div 2+cx)-xDiff;
iy:=((ypr-1)div 2+cy)-yDiff;
if(ix>-1)and(ix<Bmp.Width)and(iy>-1)and(iy<Bmp.Height)then
Tmp^:=Bmp.Pixels[iy,ix]; {what means?}
Inc(Tmp);
end;
Tmp:=Pointer(Integer(Tmp)+Dst.Gap); {what means?}
end;
end;
原理:
cos(Alpha), sin(Alpha), 0
只需要用源矩阵乘以 -sin(Alpha),cos(Alpha), 0
0, 0, 1
下载控件,有现成的例子及DEMO!
http://www.crosswinds.net/~khojasteh/delphi-components.html
TRotateImage v1.21
This component is a visual component similar to TImage with ability to rotate the image in any arbitrary angle. TRotateImage can be used on Delphi 3, 4, and 5.
数组parr共三个点,第一个对应source的左上点,第二个对应source的右上点,
第三个对应source的左下点,bmask 设为0
能给个例子吗?
Pt: array[0..2] of TPoint;
begin
Pt[0] := Point(Source.Width,0);
Pt[1] := Point(Source.Width,Source.Height);
Pt[2] := Point(0,Source.Height);
PlgBlt(Dest.Canvas.Handle,Pt,Source.Canvas.Handle,
0,0,Source.Width,Source.Height,0,0,0);
end;