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

我是一只黄豆

我是一只黄豆

2016-01-29 14:11

Delphi学习:图像放大漫游攻略,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 为鼠标

展开更多 50%)
分享

猜你喜欢

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

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

基于Delphi的图像漫游

编程语言 网络编程
基于Delphi的图像漫游

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Photoshop插值放大图像浅析

PS PS教程
Photoshop插值放大图像浅析

Delphi图形图像编程

编程语言 网络编程
Delphi图形图像编程

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

Delphi图形图像编程(二)

Delphi
Delphi图形图像编程(二)

用PS放大图像怎样保证不失真

电脑 PS
用PS放大图像怎样保证不失真

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

用简单的Tracer类来为应用写入跟踪

用简单的Tracer类来为应用写入跟踪

开发基于DCOM的局域网聊天室(一)

开发基于DCOM的局域网聊天室(一)
下拉加载更多内容 ↓