怎样局部放大图片。(50分)

  • 主题发起人 主题发起人 一阵风
  • 开始时间 开始时间

一阵风

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一张很大的图片, 在一个屏幕显示不下,
我想做一个像放大镜,点击这张图的某一位置就可以局部放大。

就像PHotoshop的放大一样。 请问有这样的控件吗? 谢谢
 
SetStretchBltMode();
StretchBlt();
 
可否详细
 
好可怜, 没人回答我,
 
一、 实用价值
---- 目前,有许多流行的图象观察软件和图象处理软件,为人们在电脑屏幕上浏览和加工美丽的图象提供了方便。然而遗憾的是,这些软件在图象放大方面却不尽如人意。它们往往只能对整幅图象进行放大,而不能随意地放大图象的局部,就连微软公司随Windows提供的画图软件也不例外。

---- 对图象局部进行放大,具有极高的实用价值。产品推销商可以将此项技术应用于新产品的展示和推广之中,让用户能够对其产品的不同部位,如汽车的表面镀铬工艺和新型的挡风玻璃等进行放大观看。通过电脑网络上动物解剖课的学生,亦可用其放大小白鼠或是青蛙的不同部位,以便更清晰地观察血管和各种器官。就象在日常生活中,人们手持放大镜,在地图或照片上移动的情景!

---- 本文介绍实现图象局部、平滑和无闪烁放大的算法原理,以及在Delphi中实现的技术。读完本文,您一定会为Delphi能用如此少的代码实现如此强大的功能惊叹不已,这是许多其它开发工具所无法比拟的。

二、 算法原理
---- 在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目录。本例中,Picture.bmp的大小为260*310象素。

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


表1 主窗体和各组件属性设置

组 件 属 性 设 置
Form1 Name MainForm
Panel1 Name FramePanel
Image1 Name BackImage
Image2 Name ForeImage

---- 上述各组件的许多属性,读者亦可根据个人的爱好设定。

---- 3.在主单元Main.pas的implementation段声明常量和变量:
const
sSide=30;
dSide=45;

var
msHide: Boolean;
OldX, OldY, NewX, NewY: Integer;
DestRect, SourceRect : TRect;

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

-- 4.建立主窗体MainForm的OnCreate事件,加入下列语句,以初始化变量及设置复制模式:
msHide:=True;
Canvas.CopyMode:=cmSrcCopy;

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

6.定义过程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;

7.创建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;

--- 8.建立主窗体MainForm的OnMouseMove事件处理程序,当鼠标移开图象时,“放大镜”隐藏,光标重新出现。源代码片段如下:
if not msHide then
begin
msHide:=True;
ShowCursor(True);
ImageCopy(OldX, OldY, dSide);
end;

四、 编译运行
--- 至此,已不再需要做更多的事情,立即编译运行吧。啊,美丽的照片出现在屏幕中央!试试放大效果。将鼠标徐徐移入相框,奇迹出现了,鼠标变成了“放大镜”,所到之处,图象的相应部位被放大,十分平滑,毫无闪烁。这不是同您手持放大镜,观看地图和照片的情景一样吗。好酷啊!还有什么能比这更激动人心的呢?!

五、 技术剖析
---- 以上介绍了利用了画布的CopyRect方法,将图象以象素块从后台隐藏的TImage组件画布上向前台TImage组件的画布上拷贝,以实现图象的放大与恢复的技术。由于这一技术的采用,在图象放大前不需要存储象素,此后直接从后台TImage组件画布上恢复图象。不仅节省了内存资源,也确保了对图象的局部进行平滑、无闪烁地放大。同时,程序源代码也简洁、明了。“放大镜”的中心便是鼠标的位置,这样处理的好处是使得图象在“放大镜”中均匀展开,并确保图象边缘也能同样放大。要改变“放大镜”的大小和图象的放大倍数,只需修改常量sSide和dSide的值。实际应用中,亦可灵活处置,如将它们设置成变量,由程序菜单控制。本例“放大镜”的大小为90*90个象素,放大倍数为1.5。值得一提的是,这里的“放大镜”比真正的玻璃放大镜的效果要好得多。玻璃放大镜是用凸透镜制成的,中间与边缘的放大倍数不一致,导致图象发生形变。而且,当一边移动一边观察时,很容易使人眼花缭乱。本文为您展示的“放大镜”则没有这些现象。利用TCanvas的StretchDraw方法或其它方法,也可以实现图象的局部放大。另外,虽然本文介绍的算法已经相当令人满意,但还是可以作进一步修改的。例如在“放大镜”移动时,只放大和恢复必要的部分。有兴趣的读者不妨一试。

---- 程序编译、运行环境为Delphi 3.0和中文Windows 98。
 
to yangxiangjun,
这篇文件我看过,也着着上面做过,不过效果好像没有他说的好吧。。在放大的过程中,依然会闪烁,跳动。
求好解!
 
我有几个控件,是卷起千堆雪tyn 发给我的。关于缩略图、局部放大
如果要的话,留下email.
 
to vine:能否发过一份,学习一下? youyan@263.net
谢谢
 
已经发过去了
 
to vine,可以发我一份吗? 谢谢

xiaofei_linxia@163.com
 
卷板主给你提个意见好不好?
这两天看到你发的内容为:
SetStretchBltMode();
StretchBlt();
的贴子不下十个了不能让别人自已搜搜吗?
 
to 一阵风
已经发过去了!
 
用以上提到的函数好像效果都不太好,
我试过
SetStretchBltMode();
StretchBlt();
还有Canvas.CopyRect
Canvas.Stretch
效果都不好,不知道哪位有好一点的控件?
 
实现图象局部放大的原理和方法


一、 实用价值

---- 目前,有许多流行的图象观察软件和图象处理软件,为人们在电脑屏幕上浏览和加工美丽的图象提供了方便。然而遗憾的是,这些软件在图象放大方面却不尽如人意。它们往往只能对整幅图象进行放大,而不能随意地放大图象的局部,就连微软公司随Windows提供的画图软件也不例外。


---- 对图象局部进行放大,具有极高的实用价值。产品推销商可以将此项技术应用于新产品的展示和推广之中,让用户能够对其产品的不同部位,如汽车的表面镀铬工艺和新型的挡风玻璃等进行放大观看。通过电脑网络上动物解剖课的学生,亦可用其放大小白鼠或是青蛙的不同部位,以便更清晰地观察血管和各种器官。就象在日常生活中,人们手持放大镜,在地图或照片上移动的情景!


---- 本文介绍实现图象局部、平滑和无闪烁放大的算法原理,以及在Delphi中实现的技术。读完本文,您一定会为Delphi能用如此少的代码实现如此强大的功能惊叹不已,这是许多其它开发工具所无法比拟的。


二、 算法原理

---- 在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目录。本例中,Picture.bmp的大小为260*310象素。


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

---- 主窗体和各组件的主要属性按表1设置:



表1 主窗体和各组件属性设置


组 件 属 性 设 置

Form1 Name MainForm

Panel1 Name FramePanel

Image1 Name BackImage

Image2 Name ForeImage


---- 上述各组件的许多属性,读者亦可根据个人的爱好设定。


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

const

sSide=30;

dSide=45;


var

msHide: Boolean;

OldX

OldY

NewX

NewY: Integer;

DestRect

SourceRect : TRect;


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


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

msHide:=True;

Canvas.CopyMode:=cmSrcCopy;


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


6.定义过程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;


7.创建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;


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

if not msHide then

begin

msHide:=True;

ShowCursor(True);

ImageCopy(OldX

OldY

dSide);

end;


四、 编译运行

--- 至此,已不再需要做更多的事情,立即编译运行吧。啊,美丽的照片出现在屏幕中央!试试放大效果。将鼠标徐徐移入相框,奇迹出现了,鼠标变成了“放大镜”,所到之处,图象的相应部位被放大,十分平滑,毫无闪烁。这不是同您手持放大镜,观看地图和照片的情景一样吗。好酷啊!还有什么能比这更激动人心的呢?!


五、 技术剖析

---- 以上介绍了利用了画布的CopyRect方法,将图象以象素块从后台隐藏的TImage组件画布上向前台TImage组件的画布上拷贝,以实现图象的放大与恢复的技术。由于这一技术的采用,在图象放大前不需要存储象素,此后直接从后台TImage组件画布上恢复图象。不仅节省了内存资源,也确保了对图象的局部进行平滑、无闪烁地放大。同时,程序源代码也简洁、明了。“放大镜”的中心便是鼠标的位置,这样处理的好处是使得图象在“放大镜”中均匀展开,并确保图象边缘也能同样放大。要改变“放大镜”的大小和图象的放大倍数,只需修改常量sSide和dSide的值。实际应用中,亦可灵活处置,如将它们设置成变量,由程序菜单控制。本例“放大镜”的大小为90*90个象素,放大倍数为1.5。值得一提的是,这里的“放大镜”比真正的玻璃放大镜的效果要好得多。玻璃放大镜是用凸透镜制成的,中间与边缘的放大倍数不一致,导致图象发生形变。而且,当一边移动一边观察时,很容易使人眼花缭乱。本文为您展示的“放大镜”则没有这些现象。利用TCanvas的StretchDraw方法或其它方法,也可以实现图象的局部放大。另外,虽然本文介绍的算法已经相当令人满意,但还是可以作进一步修改的。例如在“放大镜”移动时,只放大和恢复必要的部分。有兴趣的读者不妨一试。


---- 程序编译、运行环境为Delphi 3.0和中文Windows 98。
 
vine:
能否给我来一份?(jiangdonghui@163.net),我现在做一个课题,急需!谢谢!
 
vine:大好人,我也想要。
ranxin@263.net
 
me
gaohuaigang@163.com
 
可以发我一份吗? 谢谢

ably@371.net
 
我是这样做的:
1,两个image,1个显示大图,另一个准备显示放大的
2,根据光标位置,移动第二个image
3,用bitble将image1的当前光标位置取部分,放大显示到image2去。
 
后退
顶部