图像旋转和镜像问题

Knight94 2003-08-12 09:49:56
我在处理图像旋转和镜像问题的时候,用Pixel的赋值进行操作,发现效率很差,因此改用其它的方法,例如:ScanLine、BitBlt等也不是很好。

不过再用StretchDraw的时候速度挺快,但是不管坐标如何定义,总是有一白边,代码如下:
//MirHorizontal:
var
bit,bitCurrent:TBitmap;
rctDraw:TRect;
begin
bitCurrent.Width:=bit.Width ;
bitCurrent.Height:= bit.Height ;
rctDraw.Top:=0;
rctDraw.Left:=bit.Width;//改成bit.Width-1也不行
rctDraw.Bottom :=bit.Height;//改成bit.Height-1也不行
rctDraw.Right :=0;
bitCurrent.Canvas.StretchDraw(rctDraw,bit);
end;

希望各位图像旋转和镜像问题给于好的建议和方法,上面的代码能指出错误的原因。
...全文
209 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
cnssk 2003-08-13
  • 打赏
  • 举报
回复
根据我使用的情况,scanline是效率最高的,如果你认为不行的话,试试下面两个

//利用块拷贝方法将源图片进行翻转或颠倒
FUNCTION FlipReverseCopyRect(CONST Flip, Reverse: BOOLEAN;
CONST Bitmap: TBitmap): TBitmap;
VAR Bottom: INTEGER;
Left : INTEGER;
Right : INTEGER;
Top : INTEGER;
BEGIN
RESULT := TBitmap.Create;
RESULT.Width := Bitmap.Width;
RESULT.Height := Bitmap.Height;
RESULT.PixelFormat := Bitmap.PixelFormat;
IF Flip THEN BEGIN
Top := Bitmap.Height-1;
Bottom := -1
END
ELSE BEGIN
Top := 0;
Bottom := Bitmap.Height
END;
IF Reverse THEN BEGIN
Left := Bitmap.Width-1;
Right := -1;
END
ELSE BEGIN
Left := 0;
Right := Bitmap.Width;
END;
RESULT.Canvas.CopyRect(Rect(Left,Top, Right,Bottom),
Bitmap.Canvas,
Rect(0,0, Bitmap.Width,Bitmap.Height));
END {FlipReverseCopyRect};


//利用申展方法将源图片进行翻转或颠倒
FUNCTION FlipReverseStretchBlt(CONST Flip, Reverse: BOOLEAN;
CONST Bitmap: TBitmap): TBitmap;
VAR Bottom: INTEGER;
Left : INTEGER;
Right : INTEGER;
Top : INTEGER;
BEGIN
RESULT := TBitmap.Create;
RESULT.Width := Bitmap.Width;
RESULT.Height := Bitmap.Height;
RESULT.PixelFormat := Bitmap.PixelFormat;
IF Flip THEN BEGIN
Top := Bitmap.Height-1;
Bottom := -1
END
ELSE BEGIN
Top := 0;
Bottom := Bitmap.Height
END;
IF Reverse THEN BEGIN
Left := Bitmap.Width-1;
Right := -1;
END
ELSE BEGIN
Left := 0;
Right := Bitmap.Width;
END;
StretchBlt(RESULT.Canvas.Handle, Left, Top, Right-Left, Bottom-Top,
Bitmap.Canvas.Handle,
0,0, Bitmap.Width, Bitmap.Height, cmSrcCopy);
END {FlipReverseStretchBlt};
Knight94 2003-08-12
  • 打赏
  • 举报
回复
旋转180度也已解决,就剩90度和180度。
Knight94 2003-08-12
  • 打赏
  • 举报
回复
To DWGZ() :
你的方法我也试过,效果没有解决,不过,直接调用Api就没出现上面的问题的。
Knight94 2003-08-12
  • 打赏
  • 举报
回复
谢谢各位,
镜像问题我已解决,不过没用Canvas.StretchDraw,用的StretchBlt后一切正常。

余下就是旋转的效率的问题,我的旋转只有90,180,270,可以不用考虑复杂的情况,希望给些建议和好的方法。
cnssk 2003-08-12
  • 打赏
  • 举报
回复
//镜像(水平翻转)
Procedure Mirror(JPg:TJpegImage);
Var
X,Y : Integer;
SrcRect,DstRect : TRect;
Bitmap1,Bitmap2:Tbitmap;
Begin
// Try
Try
Bitmap1:=Tbitmap.create;
Bitmap1.PixelFormat:=pf24bit;
Bitmap1.Width:=Jpg.Width;
Bitmap1.Height:=Jpg.Height;
Bitmap1.Assign(JPg);
X := Bitmap1.Width;
Y := Bitmap1.Height;
SrcRect := Rect(0,0,X,Y);
DstRect := Rect(X,0,0,Y);
Bitmap2 := TBitmap.Create;
Bitmap2.PixelFormat:=pf24bit;
Bitmap2.Width := x;
Bitmap2.Height := y;
Bitmap2.Canvas.CopyRect(DstRect,Bitmap1.Canvas,SrcRect);
Jpg.Assign(Bitmap2);
Finally;
bitmap1.Free;
Bitmap2.Free;
End;
End;
DWGZ 2003-08-12
  • 打赏
  • 举报
回复
rctDraw.Left:=bit.Width + 1;试试
这种例子很多的到处找找一大堆
Knight94 2003-08-12
  • 打赏
  • 举报
回复
up
Knight94 2003-08-12
  • 打赏
  • 举报
回复
不知道为什么,我一用ScanLine,效率更低,还没有直接通过Pixel操作快。

还有一个问题,就是在移动的时候,图片的抖动问题(即闪的特别厉害)。
cnssk 2003-08-12
  • 打赏
  • 举报
回复
FUNCTION RotateScanLine90(CONST Angle: INTEGER;
CONST Bitmap: TBitmap):TBitmap;
FUNCTION SimpleCopy: TBitmap; //0
VAR I : INTEGER;
J : INTEGER;
RowIn : pRGBArray;
RowOut: pRGBArray;
BEGIN
RESULT := TBitmap.Create;
RESULT.Width := Bitmap.Width;
RESULT.Height := Bitmap.Height;
RESULT.PixelFormat := Bitmap.PixelFormat; //
FOR J := 0 TO Bitmap.Height - 1 DO BEGIN
RowIn := Bitmap.ScanLine[J];
RowOut := RESULT.ScanLine[J];
FOR i := 0 TO Bitmap.Width - 1 DO BEGIN
WITH rowOut[i] DO BEGIN
rgbtRed := rowIn[i].rgbtRed;
rgbtGreen := rowIn[i].rgbtGreen;
rgbtBlue := rowIn[i].rgbtBlue;
END;
END;
END;
END {简单拷贝};

FUNCTION Rotate90DegreesCounterClockwise: TBitmap;
VAR I : INTEGER;
J : INTEGER;
RowIn : pRGBArray;
BEGIN
RESULT := TBitmap.Create;
RESULT.Width := Bitmap.Height;
RESULT.Height := Bitmap.Width;
RESULT.PixelFormat := Bitmap.PixelFormat;
FOR J := 0 TO Bitmap.Height - 1 DO BEGIN
RowIn := Bitmap.ScanLine[J];
FOR i := 0 TO Bitmap.Width - 1 DO
pRGBArray(RESULT.ScanLine[Bitmap.Width - i - 1])[j] := rowIn[i]
END
END;
FUNCTION Rotate180DegreesCounterClockwise: TBitmap;
VAR I : INTEGER;
J : INTEGER;
RowIn : pRGBArray;
RowOut: pRGBArray;
BEGIN
RESULT := TBitmap.Create;
RESULT.Width := Bitmap.Width;
RESULT.Height := Bitmap.Height;
RESULT.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now
FOR j := 0 TO Bitmap.Height - 1 DO BEGIN
RowIn := Bitmap.ScanLine[j];
RowOut := RESULT.ScanLine[Bitmap.Height - j - 1];
FOR i := 0 TO Bitmap.Width - 1 DO
RowOut[Bitmap.Width - i - 1] := rowIn[i]
END
END {Rotate180DegreesCounterClockwise};
FUNCTION Rotate270DegreesCounterClockwise: TBitmap;
VAR I : INTEGER;
J : INTEGER;
RowIn: pRGBArray;
BEGIN
RESULT := TBitmap.Create;
RESULT.Width := Bitmap.Height;
RESULT.Height := Bitmap.Width;
RESULT.PixelFormat := Bitmap.PixelFormat; // only pf24bit for now
FOR j := 0 TO Bitmap.Height - 1 DO BEGIN
RowIn := Bitmap.ScanLine[j];
FOR i := 0 TO Bitmap.Width - 1 DO
pRGBARray(RESULT.Scanline[i])[Bitmap.Height - j - 1] := rowIn[i]
END;
END {Rotate270DegreesCounterClockwise};

BEGIN //主函数开始
{ IF Bitmap.PixelFormat <> pf24bit
THEN RAISE EBitmapError.Create('仅支持24位图像');
IF (angle >= 0) AND (angle MOD 90 <> 0)
THEN RAISE EBitmapError.Create('参数错误!');}
Try
CASE (angle DIV 90) MOD 4 OF
0: RESULT := SimpleCopy;
1: RESULT := Rotate90DegreesCounterClockwise; // Anticlockwise for the Brits
2: RESULT := Rotate180DegreesCounterClockwise;
3: RESULT := Rotate270DegreesCounterClockwise
ELSE
RESULT := NIL // avoid compiler warning
END;
Except
On EOutOfResources Do
Messagebox(Application.handle,'系统资源不足!','Error',mb_ok+mb_iconError);
On EOutOfMemory Do
Messagebox(Application.handle,'内存溢出!','Error',mb_ok+mb_iconError);
Else
Messagebox(Application.handle,'出现异常错误!','Error',mb_ok+mb_iconError);
End;

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧