大家好,我窗体上一张图片!我想点击按钮对其进行放大!点击的时候鼠标还要有放大镜的图标!改如何做呢?

解决方案 »

  1.   

    转贴:
    图像放大镜
     
    海南大学(570228) 叶斗彪
     
    为图像观察器增加一个"放大镜",对图像进行局部放大,是产品推销商和动物解剖学师生们梦寐以求的。本文介绍实现图像局部、平滑和无闪烁放大的算法原理及实现技术。
    一 实用价值
    目前,有许多流行的图像观察软件和图像处理软件,为人们在电脑屏幕上浏览和加工美丽的图像提供了方便。然而遗憾的是,这些软件在图像放大方面却不尽如人意。它们往往只能对整幅图像进行放大,而不能随意地放大图像的局部。
    对图像局部进行放大,具有极高的实用价值。产品推销商可以将此项技术应用于新产品的展示和推广之中,让用户能够对其产品的不同部位,如汽车的表面镀铬工艺和新型的挡风玻璃等进行放大观看。通过电脑网络上动物解剖课的学生,亦可用其放大小白鼠或是青蛙的不同部位,以便更清晰地观察血管和各种器官。就像在日常生活中,人们手持放大镜,在地图或照片上移动的情景!
    本文介绍实现图像局部、平滑和无闪烁放大的算法原理,以及在Delphi中实现的技术。
    二 算法原理
    在Delphi中,可利用类Tcanvas的CopyRect方法实现图像的放大和缩小。其功能是将源画布上的一个指定矩形区域(简称源矩形)内的像素,拷贝到目的画布上的一个指定矩形区域(简称目的矩形)中,亦可称之为像素块复制,如图1所示。图1 像素块复制
    由CopyMode属性确定拷贝的模式。在直接拷贝模式(cmSrcCopy)下,当源矩形与目的矩形相等时,图像不变;若源矩形大于目的矩形,图像则缩小;而当源矩形小于目的矩形时,图像便被放大(在目的矩形中扩展)。源矩形与目的矩形大小之比,决定图像的缩放倍数。CopyRect方法声明如下:
    Procedure CopyRect(const Dest: TRect; Canvas:
    TCanvas; const Source: Trect);
    其中参数,Dest为目的矩形,Canvas是源画布,Source为源矩形。
    三 实现步骤
    1. 新建应用程序主目录C:\Magnifier及其子目录Images,将事先制作好的位图图像Picture.bmp存入Images目录。本例中,Picture.bmp的大小为260×310像素。
    2. 启动Delphi IDE,新建项目Magnifier.dpr,主窗体单元命名为Main.pas,存入C:\Magnifier目录。在主窗体上放置一个TPanel组件,并在其中加入两个TImage组件。两个mage组件分别命名为ForeImage和BackImage,前者重叠于后者之上,并且都装入Picture.bmp位图。
    主窗体和各组件的主要属性按表1设置:
    表1
    上述各组件的许多属性,读者亦可根据个人的爱好设定。
    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;
    注意,别忘了在Main.pas的"type"中声明过程ImageCopy。
    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;
    四 编译运行
    至此,已不再需要做更多的事情,立即编译运行吧。试试放大效果。将鼠标徐徐移入相框,奇迹出现了,鼠标变成了"放大镜",所到之处,图像的相应部位被放大,十分平滑,毫无闪烁。
    要改变"放大镜"的大小和图像的放大倍数,只需修改常量sSide和dSide的值。实际应用中,亦可灵活处置,如将它们设置成变量,由程序菜单控制。本例"放大镜"的大小为90×90个像素,放大倍数为1.5。值得一提的是,这里的"放大镜"比真正的玻璃放大镜的效果要好得多。玻璃放大镜是用凸透镜制成的,中间与边缘的放大倍数不一致,导致图像发生形变。而且,当一边移动一边观察时,很容易使人眼花缭乱。本文为您展示的"放大镜"则没有这些现象。
    利用TCanvas的StretchDraw方法或其他方法,也可以实现图像的局部放大。另外,虽然本文介绍的算法已经相当令人满意,但还是可以作进一步修改的。例如在"放大镜"移动时,只放大和恢复必要的部分。有兴趣的读者不妨一试。
    程序编译、运行环境为Delphi 3.0和中文Windows 98。图2 
      

  2.   

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

  3.   

    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ExtCtrls, StdCtrls;type
      TMainForm = class(TForm)
        FramePanel: TPanel;
        BackImage: TImage;
        ForeImage: TImage;
        procedure FormCreate(Sender: TObject);
        procedure ForeImageMouseMove(Sender: TObject; Shift: TShiftState; X,
          Y: Integer);
      private
        { Private declarations }
      public
      procedure ImageCopy(CenterX, CenterY, Side: Integer);
        { Public declarations }
      end;var
      MainForm: TMainForm;
    implementation
    const
    sSide=30;
    dSide=45;
    var
    msHide: Boolean;
    OldX, OldY, NewX, NewY: Integer;
    Dest, Source : TRect;
    {$R *.DFM}procedure TMainForm.FormCreate(Sender: TObject);
    begin
      msHide:=True;
      Canvas.CopyMode:=cmSrcCopy
    end;
    procedure TMainForm.ImageCopy(CenterX, CenterY, Side: Integer);
    begin
    with Source do
    begin
    Left:=CenterX-Side;
    Top:=CenterY-Side;
    Right:=CenterX+Side;
    Bottom:=CenterY+Side;
    end;
    with Dest do
      begin
        Left:=CenterX-dSide;
        Top:=CenterY-dSide;
        Right:=CenterX+dSide;
        Bottom:=CenterY+dSide;
      end;
    ForeImage.Canvas.CopyRect(Dest, BackImage.Canvas, Source);
    end;procedure TMainForm.ForeImageMouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    begin
    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;
    end;end.