圖形放大鏡 |
|
jackkcg
站務副站長 發表:891 回覆:1050 積分:848 註冊:2002-03-23 發送簡訊給我 |
http://netcity1.web.hinet.net/userdata/nep2314/Pages/VCL13.htm 一、實用价值
目前,有許多流行的圖象觀察軟件和圖象處理軟件,為人們在電腦屏幕上瀏覽和加工美麗的圖象提供了方便。然而遺憾的是,這些軟件在圖象放大方面卻不盡如人意。牠們往往只能對整幅圖象進行放大,而不能隨意地放大圖象的侷部,就連微軟公司隨 Windows 提供的畫圖軟件也不例外。 對圖象侷部進行放大,具有極高的實用价值。產品推銷商可以將此項技術應用於新產品的展示和推廣之中,讓用戶能夠對其產品的不同部位,如汽車的表面鍍鉻工藝和新型的擋風玻璃等進行放大觀看。通過電腦網絡上動物解剖課的學生,亦可用其放大小白鼠或是青蛙的不同部位,以便更清晰地觀察血管和各種器官。就象在日常生活中,人們手持放大鏡,在地圖或照片上移動的情景﹗ 本文介紹實現圖象侷部、平滑和無閃爍放大的算法原理,以及在 BCB 、 Delphi 中實現的技術。讀完本文,您一定會為 BCB 、 Delphi 能用如此少的代碼實現如此強大的功能惊歎不已,這是許多其牠開發工具所無法比擬的。 二、算法原理 在BCB中,可利用類別 TCanvas 的 CopyRect 方法實現圖象的放大和縮小。其功能是將源畫佈上的一個指定矩形區域﹙簡稱源矩形﹚內的象素,拷貝到目的畫佈上的一個指定矩形區域﹙簡稱目的矩形﹚中,亦可稱之為象素塊複製。 由 CopyMode 屬性确定拷貝的模式。在直接拷貝模式﹙cmSrcCopy﹚下﹐當源矩形與目的矩形相等時,圖象不變;若源矩形大於目的矩形圖象則縮小;而當源矩形小於目的矩形時,圖象便被放大﹙在目的矩形中擴展﹚。源矩形與目的矩形大小之比,決定圖象的縮放倍數。 CopyRect 方法聲明如下﹕ CopyRect(TRect Dest,TCanvas Canvas,Trect Source);
Dest為目的矩形
Canvas是源畫佈
Source為源矩形 三、實現步驟 (1) 啟動 BCB IDE,新建項目 Magnifier.bpr ,主窗體單元命名為 Main.cpp 。在主窗體上放置一個 TPanel 組件,並在其中加入兩個 TImage 組件。兩個 TImage 組件分別命名為 ForeImage 和 BackImage ,前者重疊於後者之上,並且都裝入 Picture.bmp 位圖。 主窗體和各組件的主要屬性按下表設置﹕ 表1:主窗體和各組件屬性設置
Form1 Name MainForm
Panel1 Name FramePanel
Image1 Name BackImage
Image2 Name ForeImage
上述各組件的許多屬性﹐讀者亦可根據個人的愛好設定。 ( 2 ) 在頭檔中的 private 段聲明函數和變量﹕ void __fastcall ImageCopy(int BoxCenterX,int BoxCenterY,int BoxSide);
int sSide;
int dSide;
bool msHide;
int OldX,OldY,NewX,NewY;
TRect DestRect,SourceRect;
其中,sSide 和 dSide 用以控製「放大鏡」的大小和放大倍數﹔變量 msHide 控製光標﹙鼠標﹚的隱藏和打開;其牠變量用以确定放大部位。 ( 3 ) 建立主窗體 MainForm 的 OnCreate 事件,加入下列語句,以初始化變量及設置複製模式﹕ msHide=True;
Canvas->CopyMode=cmSrcCopy; ( 4 ) 創建主窗體 MainForm 的 OnKeyPress 事件處理程序,輸入語句 Close(); ,當按任意鍵時結束程序運行。 ( 5 ) 定義過程 ImageCopy ,用於處理圖象的放大和恢複,當移動鼠標時調用。這是實現圖象侷部放大最重要的過程﹐源代碼如下: 01: void __fastcall TForm1::ImageCopy(int BoxCenterX,int BoxCenterY,int BoxSide)
02: {
03: SourceRect.Left=BoxCenterX-BoxSide;
04: SourceRect.Top=BoxCenterY-BoxSide;
05: SourceRect.Right=BoxCenterX BoxSide;
06: SourceRect.Bottom=BoxCenterY BoxSide;
07: DestRect.Left=BoxCenterX-dSide;
08: DestRect.Top=BoxCenterY-dSide;
09: DestRect.Right=BoxCenterX dSide;
10: DestRect.Bottom=BoxCenterY dSide;
11: ForeImage->Canvas->CopyRect(DestRect,BackImage->Canvas,SourceRect);
12: } ( 6 ) 創建 ForeImage 的 OnMouseMove 事件處理程序,當鼠標在圖象上移動時,獲取其位置,並作為過程調用的實參。此時,光標隱藏,「放大鏡」出現。隨著「放大鏡」的移動,圖象新的部位被放大,滑過的部位又恢複原狀。 01: void __fastcall TForm1::ForeImageMouseMove(TObject *Sender,TShiftState Shift, int X, int Y)
02: {
03: NewX=X;
04: NewY=Y;
05: if (msHide)
06: {
07: OldX=NewX;
08: OldY=NewY;
09: msHide=False;
10: ShowCursor(False);
11: }
12: else ImageCopy(OldX,OldY,dSide);
13: ImageCopy(NewX,NewY,sSide);
14: OldX=NewX;
15: OldY=NewY;
16: } ( 7 ) 建立主窗體 MainForm 的 OnMouseMove 事件處理程序,當鼠標移開圖象時,「放大鏡」隱藏,光標重新出現。源代碼片段如下﹕ 01: void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,int X, int Y)
02: {
03: if (!msHide)
04: {
05: msHide=true;
06: ShowCursor(true);
07: ImageCopy(OldX,OldY,dSide);
08: }
09: } 四、編譯運行 至此,已不再需要做更多的事情,立即編譯運行吧。啊,美麗的照片出現在屏幕中央!試試放大效果。將鼠標徐徐移入相框,奇蹟出現了,鼠標變成了「放大鏡」,所到之處,圖象的相應部位被放大,十分平滑,毫無閃爍。這不是同您手持放大鏡,觀看地圖和照片的情景一樣嗎。好酷啊﹗還有什麼能比這更激動人心的呢?! 五﹑ 技術剖析 以上介紹了利用了畫佈的 CopyRect 方法,將圖象以象素塊從後台隱藏的 TImage 組件畫佈上向前台 TImage 組件的畫佈上拷貝,以實現圖象的放大與恢複的技術。由於這一技術的採用,在圖象放大前不需要存儲象素,此後直接從後台 TImage 組件畫佈上恢複圖象。不僅節省了內存資源,也确保了對圖象的侷部進行平滑、無閃爍地放大。同時,程序源代碼也簡洁、明了。「放大鏡」的中心便是鼠標的位置,這樣處理的好處是使得圖象在「放大鏡」中均勻展開,並确保圖象邊緣也能同樣放大。要改變「放大鏡」的大小和圖象的放大倍數,只需修改常量 sSide 和 dSide 的值。實際應用中,亦可靈活處置,如將牠們設置成變量,由程序菜單控製。本例「放大鏡」的大小為 90*90 個象素,放大倍數為 1.5。值得一提的是,這裡的「放大鏡」比真正的玻璃放大鏡的效果要好得多。玻璃放大鏡是用凸透鏡製成的,中間與邊緣的放大倍數不一緻,導緻圖象發生形變。而且,當一邊移動一邊觀察時,很容易使人眼花繚亂。本文為您展示的「放大鏡」則沒有這些現象。利用 TCanvas 的 StretchDraw 方法或其牠方法,也可以實現圖象的侷部放大。另外,雖然本文介紹的算法已經相當令人滿意,但還是可以作進一步修改的。例如在「放大鏡」移動時,只放大和恢複必要的部分。有興趣的讀者不妨一試。 *********************************************************
哈哈&兵燹
最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知
K.表Knowlege 知識,就是本站的標語:Open our mind to make knowledge together!
希望能大家敞開心胸,將知識寶庫結合一起
------
********************************************************** 哈哈&兵燹 最會的2大絕招 這個不會與那個也不會 哈哈哈 粉好 Delphi K.Top的K.Top分兩個字解釋Top代表尖端的意思,希望本討論區能提供Delphi的尖端新知 K.表Knowlege 知識,就是本站的標語:Open our mind |
minlee00188
一般會員 發表:9 回覆:14 積分:4 註冊:2002-10-14 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |