Delphi学习:图像放大漫游攻略

2016-01-29 14:11 60 1 收藏

Delphi学习:图像放大漫游攻略,Delphi学习:图像放大漫游攻略

【 tulaoshi.com - Delphi 】

 

我想大家应该都用过 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 p11 then w=Round(sw/p1) else w=sw
  if p21 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 wxhx 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 为鼠标

来源:https://www.tulaoshi.com/n/20160129/1492724.html

延伸阅读
标签: Delphi
  Delphi中的TImage控件直接支持Bitmap格式(.bmp)、 Icon格式(.ico)和Metafile格式(.emf or .wmf)的图像文件。在Delphi的设计窗口中可以把这三种格式的文件赋给TImage控件的Picture属性。TImage控件还能显示其他格式的图像,如JPEG格式的图像。但不能直接把文件名赋值给Picture属性,而需要把图像对象赋值给属性Picture的Graphic属性...
标签: Delphi
  基本上句柄是标志窗口,我可以根据句柄又可引申其中更多如类名,windowtitle等属性所以基于这点,一般开发工具会提供查句柄,查类名等工具,vs提供的spy++就是一个很好例子。现在教你们一查句柄知多少。其实也简单,下面贴出源代码。 procedure Tform1.TimerTimer(Sender: TObject); var Pos: TPoint; Handle: H...
android中图像在画布上放大缩小时,图像的边框大小没有改变! 原图如下: 放大后:原来图片的边框没有改变,位置依旧! 所以如果要放置图片的位置的话,就需要做相应的位置移动才可以! 采用如下代码(全屏放置图片): 代码如下: Matrix matrix = new Matrix(); matrix.postScale(canvas.getWidth()*1.01f/bmpBg.getW...
标签: Delphi
首先是初始化。初始化时,有几项工作需要进行:①创建设备描述表(Device Context)。(注:关于DC,各种资料译文不尽相同如设备环境、设备描述表、设备上下文等,但好象都不太贴切。要是能有李善兰这样的翻译就好了。下文中的RC情形相同)②设置相应的象素格式(PIXELFORMAT DESCRIPTOR)。③创建着色描述表(Rendering Context)。 Del...
标签: Delphi
  1. 建立一个窗体 2. 放一个ComboBox和Listbox 3. 改变Component的Style为csOwnerDrawVariable和ListBox的Style为lbOwnerDrawVariable。 4. 声明5个TBitmap的全局变量 5. 覆盖Form的OnCreate. 6. 覆盖ComboBox的OnDraw. 7. 覆盖ComboBox的OnMeasureItem. 8. 释放资源在Form的OnClose. unit Owne...

经验教程

875

收藏

97
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部