国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

圖像放大漫游攻略

2019-11-18 18:27:48
字體:
來源:轉載
供稿:網友
 

圖像放大漫游攻略

  我想大家應該都用過 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”所用,如果讀者有興趣可以看看效果

凌麗軟件工作室
http://wosens.com
2003.12.7


上一篇:字符畫軟件的四個關鍵技術

下一篇:一個新算法的表達式求值的函數

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 康马县| 临泽县| 平南县| 鹤岗市| 新乡县| 澄城县| 祁阳县| 淮滨县| 长武县| 景东| 收藏| 宣武区| 澄江县| 从化市| 小金县| 云和县| 理塘县| 金华市| 襄樊市| 荆州市| 沙坪坝区| 西林县| 曲靖市| 桐城市| 通州区| 双城市| 柳河县| 栖霞市| 漳浦县| 扎赉特旗| 华安县| 准格尔旗| 浪卡子县| 大埔区| 陇西县| 鹿邑县| 景宁| 于都县| 沙洋县| 松潘县| 砚山县|