图像旋转问题
我想做图像旋转,但网上好多代码得不到我想要的结果 scanline Demo 中效果不行~
[解决办法]
- Delphi(Pascal) code
procedure TForm1.RotalBmp(FAngle, FAlpha, FZoom: Integer); var Bmp : TGpBitmap; Bd : TBitmapData; Img : PByte; hd : PChar; r,g,b,a ,OldAlpah: Byte; i,j : Integer; gp : TGpGraphics; M : TGpMatrix;begin Gr.Width := OldGr.Width + (OldGr.Width * FZoom / 30); Gr.Height := OldGr.Height + (OldGr.Height * FZoom / 30); pb1.Width := Round(Sqrt(Gr.Width * Gr.Width + Gr.Height * Gr.Height)); pb1.Height := Round(Sqrt(Gr.Width * Gr.Width + Gr.Height * Gr.Height)); Gr.X := Round(pb1.Width - Gr.Width ) div 2; Gr.Y := Round(pb1.Height - Gr.Height ) div 2; Bmp := TGpBitmap.Create('a.JPG'); Bd := Bmp.LockBits(GpRect(0,0,Bmp.Width, Bmp.Height), [imRead, imWrite], pf32bppARGB); Img := PByte(Bd.Scan0); for i := 0 to Bd.Height - 1 do begin hd := PChar(img) + i*bd.Stride; for j:= 0 to Bd.Width - 1 do begin OldAlpah := Byte(hd[j * 4 + 3]); hd[j * 4 + 3] := Char( Round(OldAlpah / 255 * FAlpha )); end; end; Bmp.UnlockBits(bd); try gp := TGpGraphics.Create(pb1.Canvas.Handle); M := TGpMatrix.Create; Center.X := pb1.Width div 2; Center.Y := pb1.Height div 2; M.RotateAt(FAngle,Center); gp.SetTransform(M); gp.DrawImage(Bmp,Gr); finally gp.Free; Bmp.Free; m.Free; end;end;
[解决办法]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,math;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
function ImageRotate(srcImg1: TBitmap; angle: extended): TBitmap;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
BitMap:TBitMap;
implementation
{$R *.dfm}
function TForm1.ImageRotate(srcImg1: TBitmap; angle: extended): TBitmap;//angle为角度
var
radius, n: integer;
alpha: extended;
DestBmp : TBitmap ;
fRotateAngle : extended ; //旋转的弧度 ****************
fsrcX1,fsrcX2,fsrcX3,fsrcX4, fsrcY1,fsrcY2,fsrcY3,fsrcY4 : Extended ; //原图4个定点坐标 *************
fDestX1,fDestX2,fDestX3,fDestX4, fDestY1,fDestY2,fDestY3,fDestY4 : Extended ; //目标图4个顶点坐标 ***************
fSina,fCosa : Extended ; //旋转角的正弦和余弦值 **********
f1,f2 : Extended ; //常数
coX,coY : Extended ; //输出图像在输入图像中待插值的坐标,必须为浮点
Iu,Iv,i,j,k,t1,t2 : Integer ;
begin
DestBmp := TBitmap.Create ;
//将角度转化为弧度
fRotateAngle := Pi * angle / 180 ;
//计算旋转角的正弦
fSina := Sin(fRotateAngle) ;
//计算旋转角的余弦
fCosa := Cos(fRotateAngle) ;
//计算原图4点坐标,以图像中心为坐标原点
fSrcX1 := -( srcImg1.Width - 1 ) / 2 ;
fSrcY1 := (srcImg1.Height - 1) / 2 ;
fSrcX2 := ( srcImg1.Width - 1 ) / 2 ;
fSrcY2 := (srcImg1.Height - 1) / 2 ;
fSrcX3 := -( srcImg1.Width - 1 ) / 2 ;
fSrcY3 := -(srcImg1.Height - 1) / 2 ;
fSrcX4 := ( srcImg1.Width - 1 ) / 2 ;
fSrcY4 := -(srcImg1.Height - 1) / 2 ;
//计算新图4个角坐标,以图像中心为坐标原点
fDestX1 := fCosa * fSrcX1 + fSina * fSrcY1 ;
fDestY1 := -fSina * fSrcX1 + fCosa * fSrcY1 ;
fDestX2 := fCosa * fSrcX2 + fSina * fSrcY2 ;
fDestY2 := -fSina * fSrcX2 + fCosa * fSrcY2 ;
fDestX3 := fCosa * fSrcX3 + fSina * fSrcY3 ;
fDestY3 := -fSina * fSrcX3 + fCosa * fSrcY3 ;
fDestX4 := fCosa * fSrcX4 + fSina * fSrcY4 ;
fDestY4 := -fSina * fSrcX4 + fCosa * fSrcY4 ;
//输出后图像宽度和高度
DestBmp.Width := Round( Max( Abs(fDestX4 - fDestX1) , Abs(fDestX3 - fDestX2) ) + 0.5 ) ;
DestBmp.Height := Round( Max( Abs(fDestY4 - fDestY1) , Abs(fDestY3 - fDestY2) ) + 0.5 ) ;
//计算常数
f1 := -0.5 * (DestBmp.Width - 1) * fCosa + 0.5 * (DestBmp.Height - 1) * fSina + 0.5 * (DestBmp.Width - 1) ;
f2 := -0.5 * (DestBmp.Width - 1) * fSina - 0.5 * (DestBmp.Height - 1) * fCosa + 0.5 * (DestBmp.Height - 1) ;
//----------------------------------------
//开始旋转
//双线性插值抗锯齿,更好效果可以使用立体卷积(速度奇慢)
for i := 0 to DestBmp.Height - 1 do
for j := 0 to DestBmp.Width - 1 do
begin
//输出J,I 映射到原图像坐标
coX := j * fCosa - i * fSina + f1 ;
coY := j * fSina + i * fCosa + f2 ;
//坐标取整
Iu := Round(coX) ;
Iv := Round(coY) ;
//判断是否在原图范围内
if ( coX >= 0 ) and ( coX < srcImg1.Width - 1 ) and
( coY >= 0 ) and ( coY < srcImg1.Height - 1 ) then
begin
if ( Iv >= 1 ) and ( Iv <= srcImg1.Height - 1 ) and
( Iu >= 1 ) and ( Iu <= srcImg1.Width - 1 ) then
begin
//竖直方向插值
DestBmp.Canvas.Pixels[j,i] := RGB(
( GetRValue(srcImg1.Canvas.Pixels[Iu,Iv-1]) + GetRValue(srcImg1.Canvas.Pixels[Iu,Iv+1]) ) div 2 ,
( GetGValue(srcImg1.Canvas.Pixels[Iu,Iv-1]) + GetGValue(srcImg1.Canvas.Pixels[Iu,Iv+1]) ) div 2 ,
( GetBValue(srcImg1.Canvas.Pixels[Iu,Iv-1]) + GetBValue(srcImg1.Canvas.Pixels[Iu,Iv+1]) ) div 2
) ;
//水平方向插值
DestBmp.Canvas.Pixels[j,i] := RGB(
( GetRValue( srcImg1.Canvas.Pixels[Iu-1,Iv] ) + GetRValue( srcImg1.Canvas.Pixels[Iu,Iv+1] ) ) div 2 ,
( GetGValue( srcImg1.Canvas.Pixels[Iu-1,Iv] ) + GetGValue( srcImg1.Canvas.Pixels[Iu,Iv+1] ) ) div 2 ,
( GetBValue( srcImg1.Canvas.Pixels[Iu-1,Iv] ) + GetBValue( srcImg1.Canvas.Pixels[Iu,Iv+1] ) ) div 2
) ;
end
else
begin
//错误点也设置为白色
DestBmp.Canvas.Pixels[j,i] := RGB(255,255,255);
end ;
end
else
begin
//不在原图范围内,则设置为白点
DestBmp.Canvas.Pixels[j,i] := RGB(255,255,255);
end ;
application.processmessages ;
end ;
Result := DestBmp ;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.Canvas.Draw(0,0,BitMap);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
BitMap:=TBitMap.Create;
BitMap.LoadFromFile('Car1.bmp');
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Form1.Canvas.Draw(0,0,BitMap);
Form1.Canvas.Draw(0,0,ImageRotate(BitMap,45));
end;
end.
按照这个旋转应该效果很好,可是好像有点问题。你自己复制代码看看就知道了
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
// procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
b,c:TBitMap;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); //产生图片
begin
b:=TBitMap.Create;
b.LoadFromFile('Car1.bmp');
Form1.Canvas.Draw(0,0,b);
//b.Free; //不能释放掉
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i,j:integer;
begin
Repaint;
for i:=0 to b.Width-1 do
begin
for j:=0 to b.Height-1 do
begin
Form1.Canvas.Pixels[i,b.Width-j]:=b.Canvas.Pixels[j,i];
end;
// c.Free;
end;
end;
end.
你也可以看看这个程序,可是这些程序都有点问题,还期望你能改改,我们互相学习!