DELPHI 图片任意角旋转。 我看着书上的C++代码改的,加了点自己的理解。huruihappy

//============================================================================== //图片旋转 //输入参数 // srcImg : TBitmap 源图 // angle : extended 旋转角度 //输出参数 // result : TBitmap ; 旋转后的图 //作者:胡睿 CSDN: huruihappy. 欢迎访问www.googler.cc 更多惊喜 //QQ : 235483710 //Email : [email protected] //代码仅限交流 //============================================================================== function TForm1.ImageRotate(srcImg1: TBitmap; angle: extended): TBitmap; 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 //作者:胡睿 CSDN: huruihappy. 欢迎访问www.googler.cc 更多惊喜 //QQ : 235483710 //Email : [email protected] //代码仅限交流 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 //abcd=(ab+cd) / 2=(A+B+C+D) / 4 //ab= A + (B-A) / 2 //cd=C +(D-C) / 2 //双线性插值 DestBmp.Canvas.Pixels[j,i] := RGB( ( GetRValue( srcImg1.Canvas.Pixels[Iu-1,Iv-1] ) + GetRValue( srcImg1.Canvas.Pixels[Iu+1,Iv-1] ) + GetRValue( srcImg1.Canvas.Pixels[Iu-1,Iv+1] ) + GetRValue( srcImg1.Canvas.Pixels[Iu+1,Iv+1] ) ) div 4 , ( GetGValue( srcImg1.Canvas.Pixels[Iu-1,Iv-1] ) + GetGValue( srcImg1.Canvas.Pixels[Iu+1,Iv-1] ) + GetGValue( srcImg1.Canvas.Pixels[Iu-1,Iv+1] ) + GetGValue( srcImg1.Canvas.Pixels[Iu+1,Iv+1] ) ) div 4 , ( GetBValue( srcImg1.Canvas.Pixels[Iu-1,Iv-1] ) + GetBValue( srcImg1.Canvas.Pixels[Iu+1,Iv-1] ) + GetBValue( srcImg1.Canvas.Pixels[Iu-1,Iv+1] ) + GetBValue( srcImg1.Canvas.Pixels[Iu+1,Iv+1] ) ) div 4 ) ; 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;

 

DELPHI  图片任意角旋转。

 

我看着书上的C++代码改的,加了点自己的理解。

 

如果用SCANLINE的话, 速度会提高很多。要用的朋友自己改下吧。

 

 

  //测试用

   Img_Src.Picture.Assign( ImageRotate(Img_Src.Picture.Bitmap , -3 ) ) ;
   Img_Src.Picture.SaveToFile('c:/1.bmp');

你可能感兴趣的:(DELPHI 图片任意角旋转。 我看着书上的C++代码改的,加了点自己的理解。huruihappy)