Delphi 之Copyrect的使用

http://cqujsjcyj.iteye.com/blog/380970

Copyrect的使用(图片复制、放大、以及做图片放大镜等)

一、从一个选取一个区域中的图象到另一个图象组件中的固定区域

procedure TForm1.Button1Click(Sender: TObject);

var

rtDest, rtSource: TRect;

rtIndex: Integer;

begin

rtDest := Rect(0, 0, 200, 200); //在图象二中选取的区域,定义的坐标是相对于Image2的

rtSource := Rect(0, 0, 50 , 41);//在图象一中选取的区域,定义的坐标是相对于Image1的

Image2.Canvas.CopyRect(rtDest,.Canvas,rtSource);

end;

注意:

1、 区域(Rect)坐标的定义,是相对于它的父控件。

2、 可以起到图象放大作用。如果图象一的选取区域小于图象二中的选取区域,那么图一选取区域中的图象,拉伸填充到图象二中的选取区域。(图象区域相同的复制不会造成图象失真,如果变大或者变小,就容易造成失真)

3、 相片的拷贝只限于BMP图片

二、如果要拷贝非bmp图片可以用以下方法

procedure TForm1.Button3Click(Sender: TObject);

var

Bitmap: TBitmap;

MyRect, MyOther: TRect;

begin

MyRect := Rect(0,0,900,900);

MyOther := Rect(0,0,300,300);

Bitmap := TBitmap.Create;

bitmap.Assign(Image1.picture.Graphic);//转换文件格式成bmp后保存到bitmap中,这样就能用CopyRect了

Image2.Canvas.BrushCopy(MyOther, bitmap, MyRect, clBlack); //这行与下行的意思基本相同,选择其一即可

Image2.Canvas.CopyRect(MyOther,bitmap.Canvas,MyRect);

Bitmap.Free;

end;

end.

三、如何将外部图形保存在bitmap里面呢?

例子程序

var

b: bmp;

begin

b.b := TBitmap.Create;

b.b.Assign(Image1.picture.Bitmap);

end;

【图象列表】:

var

ImageList: TList;

begin

ImageList := TList.Create;

ImageList.Add(Image1.Picture.Bitmap);

Image2.Picture.Bitmap := TBitMap(ImageList.Items[0]);

end;

四、实现图象局部放大的原理和方法

研究了好几个小时,试过了各种函数,想做图片分辨率的调整,不是效果与期望不符就是运行出错,差一点准备发飚,自己写一个抽样缩小和插值放大的函数,却鬼使神差地看了下被我忽略这篇文章……我的妈呀,快搞疯了,不过就是这么一句话而已!

·算法原理

在Delphi中,可利用类Tcanvas的CopyRect方法实现图象的放大和缩小。其功能是将源画布上的一个指定矩形区域(简称源矩形)内的象素,拷贝到目的画布上的一个指定矩形区域(简称目的矩形)中。亦可称之为象素块复制,如图1所示。

由CopyMode属性确定拷贝的模式。在直接拷贝模式(cmSrcCopy)下,当源矩形与目的矩形相等时,图象不变;若源矩形大于目的矩形,图象则缩小;而当源矩形小于目的矩形时,图象便被放大(在目的矩形中扩展)。源矩形与目的矩形大小之比,决定图象的缩放倍数。CopyRect方法声明如下:

Procedure CopyRect(const Dest: TRect; Canvas: TCanvas; const Source: Trect);

其中参数,Dest为目的矩形,Canvas是源画布,Source为源矩形。

·实现步骤

·新建应用程序主目录C:\Magnifier及其子目录Images,将事先制作好的位图图象Picture.bmp存入Images目录?纠校琍icture.bmp的大小为260*310象素。

·启动Delphi IDE,新建项目Magnifier.dpr,主窗体单元命名为Main.pas,存入C:\Magnifier目录。在主窗体上放置一个TPanel组件,并在其中加入两个TImage组件。两个TImage组件分别命名为ForeImage和BackImage,前者重叠于后者之上,并且都装入Picture.bmp位图。

·在主单元Main.pas的implementation段声明常量和变量:

const

sSide=30;

dSide=45;

var

msHide: Boolean;

OldX, OldY, NewX, NewY: Integer;

DestRect, SourceRect : TRect;

其中,常量sSide和dSide用以控制"放大镜"的大小和放大倍数;变量msHide控制光标(鼠标)的隐藏和打开;其它变量用以确定放大部位。

·建立主窗体MainForm的OnCreate事件,加入下列语句,以初始化变量及设置复制模式:

msHide:=True;

Canvas.CopyMode:=cmSrcCopy;

·创建主窗体MainForm的OnKeyPress事件处理程序,在其begin与end之间输入语句"Close;",当按任意键时结束程序运行。

·定义过程ImageCopy,用于处理图象的放大和恢复,当移动鼠标时调用。这是实现图象局部放大最重要的过程,源代码如下。

procedure TMainForm.ImageCopy(BoxCenterX, BoxCenterY, BoxSide: Integer);

begin

with SourceRect do

begin

Left:=BoxCenterX-BoxSide;

Top:=BoxCenterY-BoxSide;

Right:=BoxCenterX+BoxSide;

Bottom:=BoxCenterY+BoxSide;

end;

with DestRect do

begin

Left:=BoxCenterX-dSide;

Top:=BoxCenterY-dSide;

Right:=BoxCenterX+dSide;

Bottom:=BoxCenterY+dSide;

end;

ForeImage.Canvas.CopyRect(DestRect, BackImage.Canvas, SourceRect);

end;

注意,别忘了在Main.pas的"type"中声明过程ImageCopy。

·创建ForeImage的OnMouseMove事件处理程序,当鼠标在图象上移动时,获取其位置,并作为过程调用的实参。此时,光标隐藏,"放大镜"出现。随着"放大镜"的移动,图象新的部位被放大,滑过的部位又恢复原状。以下为begin与end之间的代码:

NewX:=X;

NewY:=Y;

if msHide then

begin

OldX:=NewX;

OldY:=NewY;

msHide:=False;

ShowCursor(False);

end else

begin

ImageCopy(OldX, OldY, dSide);

end;

ImageCopy(NewX, NewY, sSide);

OldX:=NewX;

OldY:=NewY;

·建立主窗体MainForm的OnMouseMove事件处理程序,当鼠标移开图象时,"放大镜"隐藏,光标重新出现。源代码片段如下:

if not msHide then

begin

msHide:=True;

ShowCursor(True);

ImageCopy(OldX, OldY, dSide);

end;

·技术剖析

以上介绍了利用了画布的CopyRect方法,将图象以象素块从后台隐藏的TImage组件画布上向前台TImage组件的画布上拷贝,以实现图象的放大与恢复的技术。由于这一技术的采用,在图象放大前不需要存储象素,此后直接从后台TImage组件画布上恢复图象。不仅节省了内存资源,也确保了对图象的局部进行平滑、无闪烁地放大。同时,程序源代码也简洁、明了。

五、一个放大镜的原程序

procedure TMainForm.ImageCopy(BoxCenterX, BoxCenterY, BoxSide: Integer);

begin

with SourceRect do

begin

Left:=BoxCenterX-BoxSide;

Top:=BoxCenterY-BoxSide;

Right:=BoxCenterX+BoxSide;

Bottom:=BoxCenterY+BoxSide;

end;

with DestRect do

begin

Left:=BoxCenterX-dSide;

Top:=BoxCenterY-dSide;

Right:=BoxCenterX+dSide;

Bottom:=BoxCenterY+dSide;

end;

ForeImage.Canvas.CopyRect(DestRect, BackImage.Canvas, SourceRect);

end;