首先计算出扭曲的角度,也就是需要知道旋转多少度。
下面是围绕图象中心点进行任意角度的旋转,^_^
设定Image1.AutoSize :=True;
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;
function TMainForm.IntToByte(i:Integer):Byte;
begin
if i>255 then Result:=255
else if i<0 then Result:=0
else Result:=i;
end;
procedure GraphicRotate(var 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
ouble;
xDiff,yDiff,ifx,ify,px,py,ix,iy,x,y,LL :Integer;
nw,ne,sw,se :TFColor;
P1,P2,P3
ByteArray;
begin
Angle :=Angle;
Angle :=-Angle*Pi/180;
sAngle :=Sin(Angle);
cAngle :=Cos(Angle);
xDiff :=(Dst.Width-Src.Width)div 2;
yDiff :=(Dst.Height-Src.Height)div 2;
LL :=Dst.Height;
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;
procedure TForm1.Button1Click(Sender: TObject); //arbitrary degree rotation
var
Angle :Extended;
S: String;
Corners :array of TPoint;
x1,x2,y1,y2 :Integer;
SrcBmp,DstBmp :TBitmap;
Center :TPoint;
function MyRotate(var p :TPoint; ang :Extended):TPoint;
begin
Result.x :=Round((p.x*cos(DegToRad(ang)))-(p.y*sin(DegToRad(ang)))); //绕坐标原点旋转
Result.y :=Round((p.y*cos(DegToRad(ang)))+(p.x*sin(DegToRad(ang))));
end;
begin
S :='45';
Angle :=0.0;
SrcBmp :=TBitmap.Create;
SrcBmp.Assign(Form1.Image1.Picture.Bitmap);
if InputQuery('图象旋转','旋转角度(正值顺时针,负值逆时针):',S) then
Angle :=StrToFloat(S);
SetLength(Corners,4);
Corners[0].x :=-SrcBmp.Width div 2; // 0 1
Corners[0].y :=SrcBmp.Height div 2; // 2 3
Corners[1].x :=-Corners[0].x;
Corners[1].y :=Corners[0].y;
Corners[2].x :=Corners[0].x; //原坐标系角点坐标
Corners[2].y :=-Corners[0].y;
Corners[3].x :=-Corners[0].x;
Corners[3].y :=-Corners[0].y;
//BaseAngle :=BaseAngle+Angle; //BaseAngle 是基于原始位图的旋转
Corners[0] :=MyRotate(Corners[0],Angle{BaseAngle});
Corners[1] :=MyRotate(Corners[1],Angle{BaseAngle}); //新坐标系角点坐标
Corners[2] :=MyRotate(Corners[2],Angle{BaseAngle});
Corners[3] :=MyRotate(Corners[3],Angle{BaseAngle});
x1 :=MinIntValue([Corners[0].x,Corners[1].x,Corners[2].x,Corners[3].x]);
x2 :=MaxIntvalue([Corners[0].x,Corners[1].x,Corners[2].x,Corners[3].x]);
y1 :=MinIntValue([Corners[0].y,Corners[1].y,Corners[2].y,Corners[3].y]);
y2 :=MaxIntvalue([Corners[0].y,Corners[1].y,Corners[2].y,Corners[3].y]);
Corners :=nil;
DstBmp :=TBitmap.Create;
DstBmp.PixelFormat :=pf24bit;
DstBmp.Width :=x2-x1;
DstBmp.Height :=y2-y1;
Center.x :=DstBmp.Width div 2; //新的中心点
Center.y :=DstBmp.Height div 2;
GraphicRotate(SrcBmp,DstBmp,Center.x,Center.y,Angle{BaseAngle});
Form1.Image1.Picture.Bitmap.Assign(DstBmp);
SrcBmp.Free;
DstBmp.Free;
end