首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

图像旋转有关问题

2012-04-09 
图像旋转问题我想做图像旋转,但网上好多代码得不到我想要的结果 scanline Demo 中效果不行~[解决办法]Delp

图像旋转问题
我想做图像旋转,但网上好多代码得不到我想要的结果 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.
你也可以看看这个程序,可是这些程序都有点问题,还期望你能改改,我们互相学习!

热点排行