图象旋转的问题,高手和数学好的朋友进!! ( 积分: 100 )

  • 主题发起人 主题发起人 mat
  • 开始时间 开始时间
M

mat

Unregistered / Unconfirmed
GUEST, unregistred user!
在DLEPHI中Canvas可以进行图象的复制,但只能对矩形区域进行复制,如果碰到类似图象旋转一定角度的问题时,该如何处理。类似的情况很多,例如照片拍摄有些歪,需要取一个比较正的头像时需要调整一下相片的角度。请高人指点思路。
 
在DLEPHI中Canvas可以进行图象的复制,但只能对矩形区域进行复制,如果碰到类似图象旋转一定角度的问题时,该如何处理。类似的情况很多,例如照片拍摄有些歪,需要取一个比较正的头像时需要调整一下相片的角度。请高人指点思路。
 
晕,忘记出分了。
 
我曾经用VB实现过一个图象拼接程序,其中就涉及
将一张图倾斜一个角度,并进行凸多变形的转换。
模糊的记得是用一API函数将一个位图读到一个大的一维数组中(逻辑上表示二维的点阵),然后处理这个一维数组,将一个点转一个角度,计算出逻辑二维坐标,写到另一
个大一维数组中,最终将写完的大数组在用API存成图。
但是当时实现效率确实不太好的。

7、8年前写的,不知还能不能找到原程序。
 
去找一个叫做FastLib的代码库,虽然是以前很早的了,不过,里面有些函数应该是你所需要的。下面是我从这个代码库中“依瓢画葫芦”抄来并做了些修改,主要是用于将扫描的大头照调整一下角度。不过,具体的原理不要问我,我也不知道,只会画葫芦,数学从高二开始从来没及格过。 :)

参数说明:bmp, Dest是TBitmap类型,因为我是直接在TImage上显示,因此就直接用了TBitmap,cx, cy是旋转时固定的那个点(圆心),Angle是角度。

unit RotateImage;

interface

uses
{Windows, Messages, SysUtils, Classes,} Graphics{, Controls,
ComCtrls, StdCtrls};

type
TFColor = record
b, g, r: Byte;
end;
PFColor = ^TFColor;

procedure SmoothRotate(Bmp, Dst: TBitmap; cx, cy: Integer; Angle: Extended);

implementation

function TrimInt(Value, min, max: Integer): Integer;
begin
Result := Value;
if Result < min then
Result := min
else if Result > max then
Result := max;
end;

function IntToByte(i: Integer): Byte;
begin
if i > 255 then
Result := 255
else if i < 0 then
Result := 0
else
Result := i;
end;

procedure SmoothRotate(Bmp, Dst: TBitmap; cx, cy: Integer; Angle: Extended);
var
Top, Bottom,
Left, Right,
eww, nsw,
fx, fy,
wx, wy : Extended;
cAngle, sAngle : Double;
xDiff, yDiff,
ifx, ify,
px, py,
ix, iy,
X, Y : Integer;
nw, ne, sw, se,
Tmp : PFColor;
begin
if not Assigned(Bmp) or not Assigned(Dst) then Exit;
Bmp.pixelformat := pf24bit;
Dst.pixelformat := pf24bit;
Angle := -Angle * Pi / 180;
sAngle := Sin(Angle);
cAngle := Cos(Angle);
xDiff := (Dst.Width - Bmp.Width) div 2;
yDiff := (Dst.Height - Bmp.Height) div 2;
for Y := 0 to Dst.Height - 1 do begin
tmp := 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 < Bmp.Width) and (ify > -1) and (ify < Bmp.Height)
then begin
eww := fx - ifx;
nsw := fy - ify;
iy := TrimInt(ify + 1, 0, Bmp.Height - 1);
ix := TrimInt(ifx + 1, 0, Bmp.Width - 1);
nw := Pointer(Integer(Bmp.ScanLine[ify]) + ifx * 3);
ne := Pointer(Integer(Bmp.ScanLine[ify]) + ix * 3);
sw := Pointer(Integer(Bmp.ScanLine[iy]) + ifx * 3);
se := Pointer(Integer(Bmp.ScanLine[iy]) + ix * 3);

Top := nw^.b + eww * (ne^.b - nw^.b);
Bottom := sw^.b + eww * (se^.b - sw.b);
Tmp^.b := IntToByte(Round(Top + nsw * (Bottom - Top)));

Top := nw^.g + eww * (ne^.g - nw^.g);
Bottom := sw^.g + eww * (se^.g - sw^.g);
Tmp^.g := IntToByte(Round(Top + nsw * (Bottom - Top)));

Top := nw^.r + eww * (ne^.r - nw^.r);
Bottom := sw^.r + eww * (se^.r - sw^.r);
Tmp^.r := IntToByte(Round(Top + nsw * (Bottom - Top)));
end;
tmp := Pointer(Integer(tmp) + 3);
end;
end;
end;

end.
 
procedure Tform1.bmp_rotate(Srcbmp, DestBmp: Tbitmap; angle: extended);
var
c1x, c1y, c2x, c2y: integer;
p1x, p1y, p2x, p2y: integer;
radius, n: integer;
alpha: extended;
c0, c1, c2, c3: tcolor;
begin
if SrcBmp.Width > SrcBmp.Height then
begin
DestBmp.width := SrcBmp.Width;
DestBmp.height := SrcBmp.Width;
end
else
DestBmp.Width := SrcBmp.Height;
DestBmp.Height := SrcBmp.Height;
//将角度转换为PI值
angle := (angle / 180) * pi;
// 计算中心点,你可以修改它
c1x := SrcBmp.width div 2;
c1y := SrcBmp.height div 2;
c2x := DestBmp.width div 2;
c2y := DestBmp.height div 2;
// 步骤数值number
if c2x < c2y then
n := c2y
else
n := c2x;
dec(n, 1);
// 开始旋转
for p2x := 0 to n do
begin
for p2y := 0 to n do
begin
if p2x = 0 then
alpha := pi / 2
else
alpha := arctan2(p2y, p2x);
radius := round(sqrt((p2x * p2x) + (p2y * p2y)));
p1x := round(radius * cos(angle + alpha));
p1y := round(radius * sin(angle + alpha));

c0 := SrcBmp.canvas.pixels[c1x + p1x, c1y + p1y];
c1 := SrcBmp.canvas.pixels[c1x - p1x, c1y - p1y];
c2 := SrcBmp.canvas.pixels[c1x + p1y, c1y - p1x];
c3 := SrcBmp.canvas.pixels[c1x - p1y, c1y + p1x];

DestBmp.Canvas.pixels[c2x + p2x, c2y + p2y] := c0;
DestBmp.canvas.pixels[c2x - p2x, c2y - p2y] := c1;
DestBmp.canvas.pixels[c2x + p2y, c2y - p2x] := c2;
DestBmp.canvas.pixels[c2x - p2y, c2y + p2x] := c3;
end;
application.processmessages
end;
end;
 
这有个旋转函数
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;
// result := mf(bitmap);
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;
 
多人接受答案了。
 
后退
顶部