程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> Delphi學習:圖像放大漫游攻略

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 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 為鼠標

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved