Vb教程 Vb.net教程 Vfp教程 C/C++教程 Vc/Vc++教程 Delphi教程 Java教程 Powerbuilder
  杀毒频道 | 短信频道 | 网络电视 | 论文中心 | 学上网 | 学软件 | 网页特效 | 电脑基础 | 论坛  
  NCRE | 软考 | CET | 职称英语 | 司法考试 | 报关员 | 公务员 | CATTI | CPA考试  
  Html教程 | Css教程 | Xml教程 | Asp教程 | Asp.net | Php教程 | Jsp教程 | Linux教程 | QQ技巧  
Photoshop Illustrator ImageReady Maya教程 3D Max教程 Lightscape Coredraw教程 Authorware Autocad教程 Freehand教程
Access教程 Mysql教程 Sql server Oracle教程 Word教程 Excel教程 Powerpoint Frontpage Asp.net源码 Php源代码
Flash教程 Fireworks Dreamweaver C#教程 outlook教程 系统安装 vbscript教程 Javascript Jsp源代码 Asp源代码
您的位置:首页 >> delphi教程 >> 正文

Delphi学习:图像放大漫游攻略
文章来源:互联网 作者:amei2000go/CSDN

  我想大家应该都用过 ACDSee 或者 Windows XP,它们都支持图像的放大和漫游,虽然网上也有相关的资料,但是都不是很全面,今天我给大家介绍一种方法,由于篇幅的关系,主要讲如何实现,尽量做到言简意赅,好了,我们现在就开始。

   说明:

   1.本文使用 Object pascal 进行描述,请读者自行转换为相关的代码,作者尽量做到与代码无关
   2.涉及到图像操作,尽量使用 Windows API 和位操作

理论篇:

关键词:


   绘图区-即窗口显示图像的区域,亦可为全屏幕(在全屏幕下绘图的效果比一般窗口下好)
中心点-即要绘图区显示的中心点在原始图像的坐标(声明:这个概念特别重要)

   先说说图像的放大,要放大一张图片,我们一般的做法是直接放大图像,但本文介绍的方法仅放大我们能够看到的部分,放大分两种情况,一种是放大后比绘图区还要小,这种情况没什么好说,当然是显示全部的图像;第二种是放大后的图像比绘图区大,这才是我们今天要讨论的重点话题,这种情况下我们先要确定图像放大后的大小,然后根据“中心点”计算在原始图像的位置和大小,最后把截取的图像放大到绘图区。

   再说说图像的漫游,当显示的图像超过绘图区时,我们需要对图像进行漫游,以便看到全部的图像。原理是:当鼠标在绘图区进行单击时,这时开始漫游,先记录鼠标的单击位置,然后检测鼠标的移动,根据鼠标和上次的位移计算出“中心点”(需要将屏幕坐标转换为原始图像坐标),根据在上面放大的原理到原始图像中取出要显示的部分,放大显示到绘图区。

 算法实现篇:
  
   1.图像放大
  
   变量定义:

  
   PZoom:放大率(整数:100时为100%,根据需要可以将 100 该为 10000 或者更大些,但不推荐使用浮点数)
   a,b:中心点
   w,h:要截取原始图像的宽和高
   x,y:要截取的位置(左上角)
   sw,sh:原始图像的宽和高
   p1,p2:放大比例
   aw,ah:放大后图像的大小
   pw,ph:绘图区大小
   vx,vy:在绘图区显示的位置(左上角)
   vw,vh:在绘图区显示的大小
   ptx,pty:临时变量
  
   已知的变量:PZoom,(a,b),(sw,sh),(p1,p2),(aw,ah),(pw,ph)
   要计算的变量:(x,y),(w,h),(vx,vy),(vw,vh)
   开始计算:
   aw=Round(PZoom*sw/100);
   ah=Round(PZoom*sh/100);
   p1=aw/pw
   p2=ah/ph
   // 注:Round 用于取整,如其他语言的Int(),Fix()等
   if p1>1 then w=Round(sw/p1) else w=sw
   if p2>1 then h=Round(sh/p2) else h=sh
   // 注:shr 为右移运算符,可以使用“>>1”、“div 2”、“\2”或“Round(w/2)”代替
   x=a-w shr 1
   y=b-h shr 1

 // 注:div 为整除运算符
   ptx=(w*PZoom) div 100
   pty=(h*PZoom) div 100
  
   // 以下计算在绘图区显示的图像大小和位置
  
   变量
   Pencent:double; // 缩放比
   wx:double; // 宽缩放比
   hx:double; // 高缩放比
  
   // 获得缩放比
   wx:=pw/ptx
   hx:=ph/pty
   if wx>hx then Pencent:=hx
   else Pencent:=wx;
  
   // 获得图片最后的大小
   vw:=Round(Pencent*ptx);
   vh:=Round(Pencent*pty);
  
   // 计算出图片的位置
   vx:=(pw-vw) div 2;
   vy:=(ph-vh) div 2;
   // ------------------------------------
  
   好了,两个重要的任务完成(x,y),(w,h),(vx,vy),(vw,vh)已经全部计算得出,下面的工作就是显示了,我们选择 Windows API 进行操作
   // 以下显示图像 -----------------------
   变量
   sDC 为原始图片的设备句柄(DC)
   tDC 为临时设备句柄
   dDC 最终设备句柄
  BitBlt(tDC,0,0,w,h,sDC,0,0,SRCCOPY);
   SetStretchBltMode(dDC,STRETCH_DELETESCANS);
   StretchBlt(dDC,0,0,vw,vh,tDC,0,0,w,h,SRCCOPY);
  
   最后绘制到显示的区域即可:
   例如:BitBlt(GetDC(0),vx,vy,vx+vw,xy+vh,dDC,0,0,SRCCOPY);
   // ------------------------------------

   2.图像漫游

  先定义三个全局变量:
   FBeginDragPoint :TPoint; // 记录鼠标开始拖动的位置
   FBeginDragSBPoint :TPoint; // 记录“中心点”位置
   FBeginDrag :boolean; // 是否已经开始“拖动”
   a,b :integer; // “中心点”位置
  
   在鼠标左键点击时,记录鼠标的位置和“中心点”的位置,同时设置 FBeginDrag 为真
   当鼠标右键弹起时,设置 FBeginDrag 为假
   鼠标移动时,判断 FBeginDrag ,如果为假不进行处理,如果为真进行下面处理:
   假设 X,Y 为鼠标当前的位置
   a=FBeginDragPoint.X-((X-FBeginDragPoint.X)*100) div PZoom
   b=FBeginDragPoint.Y-((Y-FBeginDragPoint.Y)*100) div PZoom
  
   最后使用上面介绍的图像放大显示出图像


   技巧篇:

  1.如果图像较大,使用 delphi 的 位图对象会出现内存溢出错误,这时可以进行如下设置:
   bitImage:=TBitmap.Create;
   bitImage.PixelFormat:=pf24bit;
   bitImage.ReleaseHandle;

   2.如果要让图像自动适应窗口的大小,参考以下代码:
   var
   p1,p2 :double;
   begin
   p1:=pw/sw;
   p2:=ph/sw;
   if p1>p2 then PZoom:=Round(p2*100)
   else PZoom:=Round(p1*100);
   if PZoom=0 then PZoom:=100;
   end;

   3.要想让图像的效果好,最好在全屏幕方式下进行
   该方法为“Crazy Marker”所用,如果读者有兴趣可以看看效果
  
   凌丽软件工作室
   2003.12.7

[返回]

编程语言 web开发 数据库 网络技术 操作系统 服务器 网页设计 图形设计 办公软件 常用软件 学电脑

Copyright© www.bianceng.cn Powered by 编程入门网 All Rights Reserved.
关于本站 | 版权声明 | 联系我们 | 友情链接 |
编程入门网 版权所有