圖像縮放合成處理畢業(yè)論文_第1頁
已閱讀1頁,還剩31頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、<p>  摘要 圖片的合成和縮放我們實現(xiàn)了其基本的算法,本文通過bmp位圖數據源,通過采用雙線形插值,后處理操作和合成算法實現(xiàn)了對圖片的基本操作,并以此為基礎實現(xiàn)了對bmp位圖的讀寫。試驗結果表明,我們所實現(xiàn)的算法適用于對BMP位圖文件的基本操作。</p><p>  在實現(xiàn)數字圖象處理的過程中,主要是通過對圖像中的每一個像素點運用各種圖像處理算法來達到預期的效果,所以進行圖像處理的第一步,也是我們

2、最關心的問題,是如何得到圖像中每一個像素點的亮度值;為了觀察和驗證處理的圖像效果,另一個需要解決的問題是如何將處理前后的圖像正確的顯示出來。我們就是解決這些問題。</p><p>  關鍵詞:圖片的合成和縮放;雙線形插值;bmp位圖;數字圖象處理 </p><p>  vc++ picture processing implementation</p><

3、p>  Abstract The picture synthesis we have realized its basic algorithm, this article through the bmp position chart data pool, through used the double linear interpolation, the post-processing operation and the sy

4、nthesis algorithm has realized to the picture elementary operation, and has realized read-write to the bmp position chart take this as the foundation. The test result indicated, we realize the algorithm is suitable for t

5、o the BMP position chart document elementary operation.</p><p>  In the realization digital image processing process, mainly is through utilizes each kind of picture processing algorithm to in the picture ea

6、ch picture to achieve the anticipated effect, therefore carries on picture processing the first step, also is our most issue of concern, is how obtains in the picture each picture brightness value; In order to observe wi

7、th the confirmation processing picture effect, around another needs to solve how will the question is process the picture correct demonstr</p><p>  Key words: Picture synthesis; Double linear interpolation;

8、 Bmp position chart; Digital image processing</p><p><b>  目 錄</b></p><p>  1圖像縮放合成處理的意義國內外的情況綜述…………………………… ……1</p><p>  2設備無關位圖文件的讀寫存和縮放………………………………………………2</p>

9、<p>  2.1 BMP文件的格式……………………………………………………………………2</p><p>  2.1.1 BMP文件組成……………………………………………………………………2</p><p>  2.1.2 BMP文件頭………………………………………………………………………2</p><p>  2.1.3 位圖信息頭…………………

10、…………………………………………………3</p><p>  2.1.4 顏色表…………………………………………………………………………3</p><p>  2.1.5 位圖數據………………………………………………………………………4</p><p>  2.2 BMP文件的讀寫……… ……………………………………………………………4</p>

11、<p>  2.3 BMP文件的保存……… …………………………………………………………10</p><p>  2.4 BMP文件的縮放…… ……………………………………………………………15</p><p>  3圖像合成的具體方法… ……………………………………………………………21</p><p>  3.1 圖片合成算法詳解………………

12、…………………………………………………21</p><p>  3.2 圖片合成算法集的實現(xiàn) …… ……………………………………………………22</p><p>  3.3 圖片合成檢查步驟…………………………………………………………………24</p><p>  4試驗數據與展望 …… ………………………………………………………………25</p>

13、<p>  4.1試驗數據…………………… ………………………………………………………25</p><p>  4.2展望…………………………… ……………………………………………………26</p><p>  參考文獻……………………………………………………………………………………28</p><p>  致謝………… …………………………………………

14、……………………………………30</p><p><b>  引 言</b></p><p>  數字圖像處理技術與理論是計算機應用的一個重要領域,許多工程應用都涉及到圖像處理,一直有一個強烈的愿望,想系統(tǒng)的寫一個關于數字圖像處理的講座,由于工作學習很忙,時至今日才得以實現(xiàn)。</p><p>  1 圖片縮放合成的意義,國內外的情況綜述

15、</p><p>  “圖”是物體透射光或反射光的分布,“像”是人的視覺系統(tǒng)對圖的接收在大腦中形成的印象或認識。圖像是兩者的結合。人類獲取外界信息是靠聽覺、視覺、觸覺、嗅覺、味覺等,但絕大部分(約80%左右)來自視覺所接收的圖像信息。圖像處理就是對圖像信息進行加工處理,以滿足人的視覺心理和實際應用的需要。簡單的說,依靠計算機對圖像進行各種目的的處理我們就稱之為數字圖像處理。早期的數字圖像處理的目的是以人為對象,為

16、了滿足人的視覺效果而改善圖像的質量,處理過程中輸入的是質量差的圖像,輸出的是質量好的圖像,常用的圖像處理方法有圖像增強、復原等。隨著計算機技術的發(fā)展,有一類圖像處理是以機器為對象,處理的目的是使機器能夠自動識別目標,這稱之為圖像的識別,因為這其中要牽涉到一些復雜的模式識別的理論,討論其中最基本的內容。由于在許多實際應用的編程中往往都要涉及到數字圖像處理,涉及到圖像合成算法,討論如何利用微軟的Visual C++開發(fā)工具來實現(xiàn)一些常用的數

17、字圖像處理算法,論述了圖像處理的理論,同時給出了VC實現(xiàn)的源代碼。</p><p>  傳統(tǒng)的電腦只能處理文字、數字,最多是簡單的圖形。近年來,隨著電腦硬件技術的飛速發(fā)展和更新,使得計算機處理圖形圖像的能力大大增強。以前要用大型圖形工作站來運行的圖形應用軟件,或是特殊文件格式的生成及對圖形所作的各種復雜的處理和轉換;如今,很普遍的家用電腦就完全可以勝任,我們可以輕易的使用PhotoShop、CorelDraw、3

18、D MAX或是別的什么軟件做出精美的圖片或是逼真的三維物體,你甚至可以自己去做一個有趣的動畫。    在當今信息社會,以多媒體為代表的信息技術和信息產業(yè)的發(fā)展和應用對人類社會產生的影響和作用愈來愈明顯,愈來愈重要。多媒體的發(fā)展和應用,極大地推動了諸多工業(yè)的相互滲透和飛速發(fā)展,逐步改變了整個人類社會的工作結構和生活方式。可以毫不夸張地說,多媒體產業(yè)的形成和發(fā)展,將不僅引起計算機工業(yè)的一次革命,也將影響人類社

19、會發(fā)生一場巨大的變革。我們知道,所謂多媒體,即多種信息媒介,通常包括以下幾種:文本、圖形、影像、聲音、視頻、動畫??梢钥闯?,多媒體的應用在很大程度當依賴于豐富多彩的圖形和圖像。也就是說,圖形圖像技術的飛速發(fā)展也將是必然趨勢,掌握圖形圖像處理技術對一個計算機操作人</p><p>  圖形文件有以下特點:(1)數據量大。由于現(xiàn)在數據獲取手段日趨先進,可以得到的數據越來越復雜,數據量也增大。(2)結構性強。數據在本質

20、上分為數字化的和模擬的兩種。模擬信息可以轉換為數字信息。數字系統(tǒng)中的最基本單位為位(bit),其他結構單位都以位為礎。在較低層次上可以是“構造塊”(如浮點數、整數和字符);在較高層次上可以是記錄(如Pascal中)或結構(如C語言中),而圖形文件就是由特定的結構或記錄組成的。每種圖形文件都按自己的方式組織圖形信息,由于圖形文件包含的數據量大,所以很多圖形文件都使用一定的壓縮算法來壓縮圖形數據。</p><p> 

21、 設備無關位圖文件的讀寫存和縮放</p><p><b>  BMP文件的格式</b></p><p>  2.1.1 BMP文件組成 </p><p>  BMP文件由文件頭、位圖信息頭、顏色信息和圖形數據四部分組成。文件頭主要包含文件的大小、文件類型、圖像數據偏離文件頭的長度等信息;位圖信息頭包含圖象的尺寸信息、圖像用幾個比特數值來表示一個

22、像素、圖像是否壓縮、圖像所用的顏色數等信息。顏色信息包含圖像所用到的顏色表,顯示圖像時需用到這個顏色表來生成調色板,但如果圖像為真彩色,既圖像的每個像素用24個比特來表示,文件中就沒有這一塊信息,也就不需要操作調色板。文件中的數據塊表示圖像的相應的像素值,需要注意的是:圖像的像素值在文件中的存放順序為從左到右,從下到上,也就是說,在BMP文件中首先存放的是圖像的最后一行像素,最后才存儲圖像的第一行像素,但對與同一行的像素,則是按照先左邊

23、后右邊的的順序存儲的;另外一個需要讀者朋友關注的細節(jié)是:文件存儲圖像的每一行像素值時,如果存儲該行像素值所占的字節(jié)數為4的倍數,則正常存儲,否則,需要在后端補0,湊足4的倍數。 </p><p>  2.1.2 BMP文件頭 </p><p>  BMP文件頭數據結構含有BMP文件的類型、文件大小和位圖起始位置等信息。其結構定義如下: </p><p>  type

24、def struct tagBITMAPFILEHEADER </p><p><b>  { </b></p><p>  WORD bfType; // 位圖文件的類型,必須為"BM" </p><p>  DWORD bfSize; // 位圖文件的大小,以字節(jié)為單位 </p><p>  WO

25、RD bfReserved1; // 位圖文件保留字,必須為0 </p><p>  WORD bfReserved2; // 位圖文件保留字,必須為0 </p><p>  DWORD bfOffBits; // 位圖數據的起始位置,以相對于位圖文件頭的偏移量表示,以字節(jié)為單位 </p><p>  } BITMAPFILEHEADER;該結構占據14個字節(jié)。 &

26、lt;/p><p>  2.1.3 位圖信息頭 </p><p>  BMP位圖信息頭數據用于說明位圖的尺寸等信息。其結構如下: </p><p>  typedef struct tagBITMAPINFOHEADER{ </p><p>  DWORD biSize; // 本結構所占用字節(jié)數 </p><p>  L

27、ONG biWidth; // 位圖的寬度,以像素為單位 </p><p>  LONG biHeight; // 位圖的高度,以像素為單位 </p><p>  WORD biPlanes; // 目標設備的平面數不清,必須為1 </p><p>  WORD biBitCount// 每個像素所需的位數,必須是1(雙色), 4(16色),8(256色)或24(真

28、彩色)之一 </p><p>  DWORD biCompression; // 位圖壓縮類型,必須是 0(不壓縮),1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一 </p><p>  DWORD biSizeImage; // 位圖的大小,以字節(jié)為單位 </p><p>  LONG biXPelsPerMeter; // 位圖水平分辨率,每米像

29、素數 </p><p>  LONG biYPelsPerMeter; // 位圖垂直分辨率,每米像素數 </p><p>  DWORD biClrUsed;// 位圖實際使用的顏色表中的顏色數 </p><p>  DWORD biClrImportant;// 位圖顯示過程中重要的顏色數 </p><p>  } BITMAPINFOH

30、EADER;該結構占據40個字節(jié)。 </p><p>  注意:對于BMP文件格式,在處理單色圖像和真彩色圖像的時候,無論圖象數據多么龐大,都不對圖象數據進行任何壓縮處理,一般情況下,如果位圖采用壓縮格式,那么16色圖像采用RLE4壓縮算法,256色圖像采用RLE8壓縮算法。 </p><p>  2.1.4 顏色表 </p><p>  顏色表用于說明位圖中的顏色

31、,它有若干個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顏色。RGBQUAD結構的定義如下: </p><p>  typedef struct tagRGBQUAD { </p><p>  BYTErgbBlue;// 藍色的亮度(值范圍為0-255) </p><p>  BYTErgbGreen; // 綠色的亮度(值范圍為0-255) <

32、/p><p>  BYTErgbRed; // 紅色的亮度(值范圍為0-255) </p><p>  BYTErgbReserved;// 保留,必須為0 </p><p>  } RGBQUAD; </p><p>  顏色表中RGBQUAD結構數據的個數由BITMAPINFOHEADER 中的biBitCount項來確定,當biBitCou

33、nt=1,4,8時,分別有2,16,256個顏色表項,當biBitCount=24時,圖像為真彩色,圖像中每個像素的顏色用三個字節(jié)表示,分別對應R、G、B值,圖像文件沒有顏色表項。位圖信息頭和顏色表組成位圖信息,BITMAPINFO結構定義如下: </p><p>  typedef struct tagBITMAPINFO { </p><p>  BITMAPINFOHEADER bm

34、iHeader; // 位圖信息頭 </p><p>  RGBQUAD bmiColors[1]; // 顏色表 </p><p>  } BITMAPINFO; </p><p>  注意:RGBQUAD數據結構中,增加了一個保留字段rgbReserved,它不代表任何顏色,必須取固定的值為"0",同時, RGBQUAD結構中定義的顏色值中,

35、紅色、綠色和藍色的排列順序與一般真彩色圖像文件的顏色數據排列順序恰好相反,既:若某個位圖中的一個像素點的顏色的描述為"00,00,ff,00",則表示該點為紅色,而不是藍色。 </p><p>  2.1.5 位圖數據 </p><p>  位圖數據記錄了位圖的每一個像素值或該對應像素的顏色表的索引值,圖像記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。這種格式我

36、們又稱為Bottom_Up位圖,當然與之相對的還有Up_Down形式的位圖,它的記錄順序是從上到下的,對于這種形式的位圖,也不存在壓縮形式。位圖的一個像素值所占的字節(jié)數:當biBitCount=1時,8個像素占1個字節(jié);當biBitCount=4時,2個像素占1個字節(jié);當 biBitCount=8時,1個像素占1個字節(jié);當biBitCount=24時,1個像素占3個字節(jié),此時圖像為真彩色圖像。當圖像不是為真彩色時,圖像文件中包含顏色表,

37、位圖的數據表示對應像素點在顏色表中相應的索引值,當為真彩色時,每一個像素用三個字節(jié)表示圖像相應像素點彩色值,每個字節(jié)分別對應R、G、B分量的值,這時候圖像文件中沒有顏色表。上面我已經講過了,Windows規(guī)定圖像文件中一個掃描行所占的字節(jié)數必須是4的倍數(即以字為單位),不足的以0填充,圖像文件中一個掃描行所占的字節(jié)數計算方法: </p><p>  DataSizePerLine= (biWidth* biBi

38、tCount+31)/8;// 一個掃描行所占的字節(jié)</p><p>  位圖數據的大小按下式計算(不壓縮情況下): </p><p>  DataSize= DataSizePerLine* biHeight。</p><p><b>  BMP文件的讀寫</b></p><p>  如今Windows(3.x以及95

39、,98,NT)系列已經成為絕大多數用戶使用的操作系統(tǒng),它比DOS成功的一個重要因素是它可視化的漂亮界面。那么Windows是如何顯示圖象的呢?這就要談到位圖(bitmap)。</p><p>  我們知道,普通的顯示器屏幕是由許許多多點構成的,我們稱之為象素。顯示時采用掃描的方法:電子槍每次從左到右掃描一行,為每個象素著色,然后從上到下這樣掃描若干行,就掃過了一屏。為了防止閃爍,每秒要重復上述過程幾十次。例如我們

40、常說的屏幕分辨率為640×480,刷新頻率為70Hz,意思是說每行要掃描640個象素,一共有480行,每秒重復掃描屏幕70次。我們稱這種顯示器為位映象設備。所謂位映象,就是指一個二維的象素矩陣,而位圖就是采用位映象方法顯示和存儲的圖象。舉個例子,圖1.1是一幅普通的黑白位圖,圖1.2是被放大后的圖,圖中每個方格代表了一個象素。我們可以看到:整個骷髏就是由這樣一些黑點和白點組成的。</p><p>  先

41、來說說三元色RGB概念。我們知道,自然界中的所有顏色都可以由紅、綠、藍(R,G,B)組合而成。有的顏色含有紅色成分多一些,如深紅;有的含有紅色成分少一些,如淺紅。針對含有紅色成分的多少,可以分成0到255共256個等級,0級表示不含紅色成分;255級表示含有100%的紅色成分。同樣,綠色和藍色也被分成256級。這種分級概念稱為量化。</p><p>  這樣,根據紅、綠、藍各種不同的組合我們就能表示出256

42、15;256×256,約1600萬種顏色。這么多顏色對于我們人眼來說已經足夠豐富了。</p><p>  表1.1     常見顏色的RGB組合值</p><p>  在實現(xiàn)數字圖象處理的過程中,主要是通過對圖像中的每一個像素點運用各種圖像處理算法來達到預期的效果,所以進行圖像處理的第一步,也是我們最關心的問題,是如何得到圖像中每一個像素點

43、的亮度值;為了觀察和驗證處理的圖像效果,另一個需要解決的問題是如何將處理前后的圖像正確的顯示出來。我們這章內容就是解決這些問題。 </p><p>  隨著科技的發(fā)展,圖像處理技術已經滲透到人類生活的各個領域并得到越來越多的應用,但是突出的一個矛盾是圖像的格式也是越來越多,目前圖像處理所涉及的主要的圖像格式就有很多種,如TIF、JEMP、BMP等等,一般情況下,為了處理簡單方便,進行數字圖像處理所采用的都是BMP

44、格式的圖像文件(有時也稱為DIB格式的圖像文件),并且這種格式的文件是沒有壓縮的。我們通過操作這種格式的文件,可以獲取正確顯示圖像所需的調色板信息,圖像的尺寸信息,圖像中各個像素點的亮度信息等等,有了這些數據,開發(fā)人員就可以對圖像施加各種處理算法,進行相應的處理。如果特殊情況下需要處理其它某種格式的圖像,如GIF、JEMP等格式的圖象文件,可以首先將該格式轉換為BMP格式,然后再進行相應的處理。這一點需要讀者清楚。 </p>

45、<p>  BMP格式的圖像文件又可以分為許多種類,如真彩色位圖、256色位圖,采用RLE(游程編碼)壓縮格式的BMP位圖等等。由于在實際的工程應用和圖像算法效果驗證中經常要處理的是256級并且是沒有壓縮的BMP灰度圖像,例如通過黑白采集卡采集得到的圖像就是這種格式,所以我們在整個講座中范例所處理的文件格式都是BMP灰度圖像。如果讀者對這種格式的位圖能夠作到熟練的操作,那么對于其余形式的BMP位圖的操作也不會很困難。 &l

46、t;/p><p>  BMP灰度圖像作為Windows環(huán)境下主要的圖像格式之一,以其格式簡單,適應性強而倍受歡迎。正如我們在上一講中介紹過的那樣,這種文件格式就是每一個像素用8bit表示,顯示出來的圖像是黑白效果,最黑的像素的灰度(也叫作亮度)值為"0",最白的像素的灰度值為"255",整個圖像各個像素的灰度值隨機的分布在"0"到"255"

47、;的區(qū)間中,越黑的像素,其灰度值越接近于"0",越白(既越亮)的像素,其灰度值越接近于"255";與此對應的是在該文件類型中的顏色表項的各個RGB分量值是相等的,并且顏色表項的數目是256個。 </p><p>  在進行圖像處理時,操作圖像中的像素值就要得到圖像陣列;經過處理后的圖像的像素值需要存儲起來;顯示圖像時要正確實現(xiàn)調色板、得到位圖的尺寸信息等。</p>

48、;<p>  可以根據BMP位圖文件的結構,操作BMP位圖文件并讀入圖像數據,為此我們充分利用了VC的對話框結構,自己新建ReadDIBFile()函數,這樣用戶就可以在自動生成程序的打開文件對話框中選擇所要打開的位圖文件,然后程序將自動調用該函數執(zhí)行讀取數據的操作。該函數的實現(xiàn)代碼如下所示</p><p>  HDIB WINAPI ReadDIBFile(CFile& file)<

49、/p><p><b>  {</b></p><p>  BITMAPFILEHEADER bmfHeader;</p><p>  DWORD dwBitsSize;</p><p>  HDIB hDIB;</p><p>  LPSTR pDIB;</p><p>  /

50、/ 獲取DIB(文件)長度(字節(jié))</p><p>  dwBitsSize = file.GetLength();</p><p>  // 嘗試讀取DIB文件頭</p><p>  if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))</p>&l

51、t;p><b>  {</b></p><p>  // 大小不對,返回NULL。</p><p>  return NULL;</p><p><b>  }</b></p><p>  // 判斷是否是DIB對象,檢查頭兩個字節(jié)是否是"BM"</p>&l

52、t;p>  if (bmfHeader.bfType != DIB_HEADER_MARKER)</p><p><b>  {</b></p><p>  // 非DIB對象,返回NULL。</p><p>  return NULL;</p><p><b>  }</b></p&g

53、t;<p>  // 為DIB分配內存</p><p>  hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);</p><p>  if (hDIB == 0)</p><p><b>  {</b></p><p>

54、;  // 內存分配失敗,返回NULL。</p><p>  return NULL;</p><p><b>  }</b></p><p><b>  // 鎖定</b></p><p>  pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);</p&g

55、t;<p><b>  // 讀象素</b></p><p>  if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=</p><p>  dwBitsSize - sizeof(BITMAPFILEHEADER) )</p><p><b>

56、  {</b></p><p><b>  // 大小不對。</b></p><p><b>  // 解除鎖定</b></p><p>  ::GlobalUnlock((HGLOBAL) hDIB);</p><p><b>  // 釋放內存</b></

57、p><p>  ::GlobalFree((HGLOBAL) hDIB);</p><p>  // 返回NULL。</p><p>  return NULL;</p><p><b>  }</b></p><p><b>  // 解除鎖定</b></p>&

58、lt;p>  ::GlobalUnlock((HGLOBAL) hDIB);</p><p>  // 返回DIB句柄</p><p>  return hDIB;</p><p><b>  }</b></p><p>  呼叫兩個函數之一來顯示DIB時,您需要幾個關于圖像的信息。如果除了文件表頭外,整個文件被儲

59、存在內存的連續(xù)區(qū)塊中,指向該內存塊開始處(也就是信息表頭的開頭)的指標被稱為指向packed DIB的指標。因為整個DIB由單個指標(如pPackedDib)引用,所以packed DIB是在內存中儲存DIB的方便方法,您可以把指標定義為指向BYTE的指標。使用本章前面所示的結構定義,能得到所有儲存在DIB內的信息,包括色彩對照表和個別圖素位。然而,要想得到這么多信息,還需要一些程序代碼。例如,您不能通過以下敘述簡單地取得DIB的圖素寬

60、度:iWidth = ((PBITMAPINFOHEADER) pPackedDib)->biWidth ; DIB有可能是OS/2兼容格式的。在那種格式中,packed DIB以BITMAPCOREHEADER結構開始,并且DIB的圖素寬度和高度以16位WORD,而不是32位LONG儲存。因此,首先必須檢查DIB是否為舊的格式,然后進行相對應的操作:</p><p>  if(((PBITMAPCOREH

61、EADER) pPackedDib)->bcSize == sizeof (BITMAPCOREHEADER)) </p><p>  iWidth = ((PBITMAPCOREHEADER) pPackedDib)->bcWidth ; </p><p><b>  else</b></p><p>

62、  iWidth = ((PBITMAPINFOHEADER) pPackedDib)->biWidth ; </p><p>  SetDIBitsToDevice和StretchDIBits函數需要兩個指向DIB的指標,因為這兩個部分不在連續(xù)的內存塊內。確實,把DIB分成兩個內存塊是很有用的,只是我們更喜歡與整個DIB儲存在單個內存塊的packed DIB打交道。除了這兩個指標,SetDIBitsToD

63、evice和StretchDIBits函數通常也需要DIB的圖素寬度和高度。如只想顯示DIB的一部分,就不必明確地知道這些值,但它們會定義您在DIB圖素位數組內定義的矩形的上限。點對點圖素顯示 SetDIBitsToDevice函數顯示沒有延伸和縮小的DIB。DIB的每個圖素對應到輸出設備的一個圖素上,而且DIB中的圖像一定會被正確顯示出來-也就是說,圖像的頂列在上方。任何會影響設備內容的坐標轉換都影響了顯示DIB的開始位置,但不影響顯

64、示出來的圖片大小和方向。</p><p>  不要對參數的數量感到厭煩,在多數情況下,函數用起來比看起來要簡單。不過在其它用途上來說,它的用法真的是亂七八糟,不過我們將學會怎么用它。</p><p>  和GDI顯示函數一樣,SetDIBitsToDevice的第一個參數是設備內容句柄,它指出顯示DIB的設備。下面兩個參數xDst和yDst,是輸出設備的邏輯坐標,并指出了顯示DIB圖像左上

65、角的坐標(「上端」指的是視覺上的上方,并不是DIB圖素的第一行)。注意,這些都是邏輯坐標,因此它們附屬于實際上起作用的任何坐標轉換方式或-在Windows NT的情況下-設定的任何空間轉換。在內定的MM_TEXT映像方式下,可以把這些參數設為0,從顯示平面上向左向上顯示DIB圖像。 </p><p>  可以顯示整個DIB圖像或僅顯示其中的一部分,這就是后四個參數的作用。但是DIB圖素數據的由上而下的方向產生了許

66、多誤解,待會兒會談到這些。現(xiàn)在應該清楚當顯示整個DIB時,應把xSrc和ySrc設定為0,并且cxSrc和cySrc應分別等于DIB的圖素寬度和高度。注意,因為BITMAPINFOHEADER結構的biHeight字段對于由上而下的DIB來說是負的,cySrc應設定為biHeight字段的絕對值。</p><p>  pBits參數是指向DIB圖素位的指針。pInfo參數是指向DIB的BITMAPINFO結構的指

67、針。雖然BITMAPINFO結構的地址與BITMAPINFOHEADER結構的地址相同,但是SetDIBitsToDevice結構被定義為使用BITMAPINFO結構,暗示著:對于1位、4位和8位DIB,位圖信息表頭后必須跟著色彩對照表。盡管pInfo參數被定義為指向BITMAPINFO結構的指針,它也是指向BITMAPCOREINFO、BITMAPV4HEADER或BITMAPV5HEADER結構的指針。</p><

68、;p>  2.3 BMP文件的保存</p><p>  /*************************************************************************</p><p><b>  *</b></p><p><b>  * 函數名稱:</b></p>

69、<p>  * SaveDIB()</p><p><b>  *</b></p><p><b>  * 參數:</b></p><p>  * HDIB hDib - 要保存的DIB</p><p>  * CFile& file

70、 - 保存文件CFile</p><p><b>  *</b></p><p><b>  * 返回值:</b></p><p>  * BOOL - 成功返回TRUE,否則返回FALSE或者CFileException</p><p><b>  *&l

71、t;/b></p><p><b>  * 說明:</b></p><p>  * 該函數將指定的DIB對象保存到指定的CFile中。該CFile由調用程序打開和關閉。</p><p><b>  *</b></p><p>  ******************************

72、*******************************************/</p><p>  BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)</p><p><b>  {</b></p><p>  // Bitmap文件頭</p><p>  BITMA

73、PFILEHEADER bmfHdr;</p><p>  // 指向BITMAPINFOHEADER的指針</p><p>  LPBITMAPINFOHEADER lpBI;</p><p><b>  // DIB大小</b></p><p>  DWORD dwDIBSize;</p><p&

74、gt;  if (hDib == NULL)</p><p><b>  {</b></p><p>  // 如果DIB為空,返回FALSE</p><p>  return FALSE;</p><p><b>  }</b></p><p>  // 讀取BITMAPI

75、NFO結構,并鎖定</p><p>  lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);</p><p>  if (lpBI == NULL)</p><p><b>  {</b></p><p>  // 為空,返回FALSE</p>

76、<p>  return FALSE;</p><p><b>  }</b></p><p>  // 判斷是否是WIN3.0 DIB</p><p>  if (!IS_WIN30_DIB(lpBI))</p><p><b>  {</b></p><p> 

77、 // 不支持其它類型的DIB保存</p><p><b>  // 解除鎖定</b></p><p>  ::GlobalUnlock((HGLOBAL) hDib);</p><p>  // 返回FALSE</p><p>  return FALSE;</p><p><b> 

78、 }</b></p><p><b>  // 填充文件頭</b></p><p>  // 文件類型"BM"</p><p>  bmfHdr.bfType = DIB_HEADER_MARKER;</p><p>  // 計算DIB大小時,最簡單的方法是調用GlobalSize()函

79、數。但是全局內存大小并</p><p>  // 不是DIB真正的大小,它總是多幾個字節(jié)。這樣就需要計算一下DIB的真實大小。</p><p>  // 文件頭大?。伾泶笮?lt;/p><p>  // (BITMAPINFOHEADER和BITMAPCOREHEADER結構的第一個DWORD都是該結構的大?。?lt;/p><p>  dwDIB

80、Size = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI);</p><p><b>  // 計算圖像大小</b></p><p>  if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))</p><

81、p><b>  {</b></p><p>  // 對于RLE位圖,沒法計算大小,只能信任biSizeImage內的值</p><p>  dwDIBSize += lpBI->biSizeImage;</p><p><b>  }</b></p><p><b>  el

82、se</b></p><p><b>  {</b></p><p><b>  // 象素的大小</b></p><p>  DWORD dwBmBitsSize;</p><p>  // 大小為Width * Height</p><p>  dwBmBit

83、sSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;</p><p>  // 計算出DIB真正的大小</p><p>  dwDIBSize += dwBmBitsSize;</p><p>  // 更新biSizeImage(很多BMP文

84、件頭中biSizeImage的值是錯誤的)</p><p>  lpBI->biSizeImage = dwBmBitsSize;</p><p><b>  }</b></p><p>  // 計算文件大?。篋IB大小+BITMAPFILEHEADER結構大小</p><p>  bmfHdr.bfSize =

85、 dwDIBSize + sizeof(BITMAPFILEHEADER);</p><p><b>  // 兩個保留字</b></p><p>  bmfHdr.bfReserved1 = 0;</p><p>  bmfHdr.bfReserved2 = 0;</p><p>  // 計算偏移量bfOffBits

86、,它的大小為Bitmap文件頭大小+DIB頭大?。伾泶笮?lt;/p><p>  bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize</p><p>  + PaletteSize((LPSTR)lpBI);</p><p><b>  // 嘗試寫文件</b>

87、;</p><p><b>  TRY</b></p><p><b>  {</b></p><p><b>  // 寫文件頭</b></p><p>  file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));&l

88、t;/p><p>  // 寫DIB頭和象素</p><p>  file.WriteHuge(lpBI, dwDIBSize);</p><p><b>  }</b></p><p>  CATCH (CFileException, e)</p><p><b>  {</b>

89、;</p><p><b>  // 解除鎖定</b></p><p>  ::GlobalUnlock((HGLOBAL) hDib);</p><p><b>  // 拋出異常</b></p><p>  THROW_LAST();</p><p><b> 

90、 }</b></p><p><b>  END_CATCH</b></p><p><b>  // 解除鎖定</b></p><p>  ::GlobalUnlock((HGLOBAL) hDib);</p><p><b>  // 返回TRUE</b><

91、;/p><p>  return TRUE;</p><p><b>  }</b></p><p>  2.4 BMP文件的縮放</p><p>  由于放大圖象時產生了新的象素,以及浮點數的操作,得到的坐標可能并不是整數,這一點我們在介紹旋轉時就提到了。我們采用的做法是找與之最臨近的點。實際上,更精確的做法是采用插值(

92、interpolation),即利用鄰域的象素來估計新的象素值。其實我們前面的做法也是一種插值,稱為最鄰近插值(Nearest Neighbour Interpolation)。下面先介紹線形插值(Linear Interpolation)。</p><p>  線形插值使用原圖中兩個值來構造所求坐標處的值。舉一個一維的例子。如圖2.16所示,如果已經知道了兩點x0,x2處的函數值f(x0),f(x2),現(xiàn)在要求

93、x1處的函數值f(x1)。我們假設函數是線形的,利用幾何知識可以知道</p><p>  f(x1)=(f(x2)-f(x0))(x1-x0)/(x2-x0)+f(x0)</p><p>  在圖象處理中需要將線形插值擴展到二維的情況,即采用雙線形插值(Bilinear Intrepolation).</p><p>  圖2.17為雙線形插值的示意圖。</p

94、><p>  已知a、b、c、d四點的灰度,要求e點的灰度,可以先在水平方向上由a,b線形插值求出g、c、d線形插值求出f,然后在垂直方向上由g,f線形插值求出e。</p><p>  線形插值基于這樣的假設:原圖的灰度在兩個象素之間是線形變化的。一般情況下,這種插值的效果還不錯。更精確的方法是采用曲線插值(Curvilinear Interpolation),即認為象素之間的灰度變化規(guī)律符合

95、某種曲線,但這種處理的計算量是很大的。</p><p>  /*************************************************************************</p><p><b>  *</b></p><p><b>  * 函數名稱:</b></p>

96、<p>  * ZoomDIB()</p><p><b>  *</b></p><p><b>  * 參數:</b></p><p>  * LPSTR lpDIB- 指向源DIB的指針</p><p>  * float fXZoomRatio- X軸方向縮放比率

97、</p><p>  * float fYZoomRatio- Y軸方向縮放比率</p><p><b>  *</b></p><p><b>  * 返回值:</b></p><p>  * HGLOBAL - 縮放成功返回新DIB句柄,否則返回NULL。<

98、/p><p><b>  *</b></p><p><b>  * 說明:</b></p><p>  * 該函數用來縮放DIB圖像,返回新生成DIB的句柄。</p><p><b>  *</b></p><p>  ****************

99、********************************************************/</p><p>  HGLOBAL WINAPI ZoomDIB(LPSTR lpDIB, float fXZoomRatio, float fYZoomRatio)</p><p><b>  {</b></p><p>  /

100、/ 源圖像的寬度和高度</p><p>  LONGlWidth;</p><p>  LONGlHeight;</p><p>  // 縮放后圖像的寬度和高度</p><p>  LONGlNewWidth;</p><p>  LONGlNewHeight;</p><p>  /

101、/ 縮放后圖像的寬度(lNewWidth',必須是4的倍數)</p><p>  LONGlNewLineBytes;</p><p>  // 指向源圖像的指針</p><p>  LPSTRlpDIBBits;</p><p>  // 指向源象素的指針</p><p>  LPSTRlpSrc;&l

102、t;/p><p>  // 縮放后新DIB句柄</p><p>  HDIBhDIB;</p><p>  // 指向縮放圖像對應象素的指針</p><p>  LPSTRlpDst;</p><p>  // 指向縮放圖像的指針</p><p>  LPSTRlpNewDIB;</p&

103、gt;<p>  LPSTRlpNewDIBBits;</p><p>  // 指向BITMAPINFO結構的指針(Win3.0)</p><p>  LPBITMAPINFOHEADER lpbmi;</p><p>  // 指向BITMAPCOREINFO結構的指針</p><p>  LPBITMAPCOREHEAD

104、ER lpbmc;</p><p>  // 循環(huán)變量(象素在新DIB中的坐標)</p><p><b>  LONGi;</b></p><p><b>  LONGj;</b></p><p>  // 象素在源DIB中的坐標</p><p><b>  L

105、ONGi0;</b></p><p><b>  LONGj0;</b></p><p>  // 圖像每行的字節(jié)數</p><p>  LONG lLineBytes;</p><p>  // 找到源DIB圖像象素起始位置</p><p>  lpDIBBits = ::Fin

106、dDIBBits(lpDIB);</p><p>  // 獲取圖像的寬度</p><p>  lWidth = ::DIBWidth(lpDIB);</p><p>  // 計算圖像每行的字節(jié)數</p><p>  lLineBytes = WIDTHBYTES(lWidth * 8);</p><p>  //

107、獲取圖像的高度</p><p>  lHeight = ::DIBHeight(lpDIB);</p><p>  // 計算縮放后的圖像實際寬度</p><p>  // 此處直接加0.5是由于強制類型轉換時不四舍五入,而是直接截去小數部分</p><p>  lNewWidth = (LONG) (::DIBWidth(lpDIB) *

108、fXZoomRatio + 0.5);</p><p>  // 計算新圖像每行的字節(jié)數</p><p>  lNewLineBytes = WIDTHBYTES(lNewWidth * 8);</p><p>  // 計算縮放后的圖像高度</p><p>  lNewHeight = (LONG) (lHeight * fYZoomRat

109、io + 0.5);</p><p>  // 分配內存,以保存新DIB</p><p>  hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));</p><p>  // 判斷是否內存分配失敗</p>

110、<p>  if (hDIB == NULL)</p><p><b>  {</b></p><p><b>  // 分配內存失敗</b></p><p>  return NULL;</p><p><b>  }</b></p><p&

111、gt;<b>  // 鎖定內存</b></p><p>  lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB);</p><p>  // 復制DIB信息頭和調色板</p><p>  memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + ::PaletteSize

112、(lpDIB));</p><p>  // 找到新DIB象素起始位置</p><p>  lpNewDIBBits = ::FindDIBBits(lpNewDIB);</p><p><b>  // 獲取指針</b></p><p>  lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;&l

113、t;/p><p>  lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;</p><p>  // 更新DIB中圖像的高度和寬度</p><p>  if (IS_WIN30_DIB(lpNewDIB))</p><p><b>  {</b></p><p>  // 對于W

114、indows 3.0 DIB</p><p>  lpbmi->biWidth = lNewWidth;</p><p>  lpbmi->biHeight = lNewHeight;</p><p><b>  }</b></p><p><b>  else</b></p>

115、;<p><b>  {</b></p><p>  // 對于其它格式的DIB</p><p>  lpbmc->bcWidth = (unsigned short) lNewWidth;</p><p>  lpbmc->bcHeight = (unsigned short) lNewHeight;</p&g

116、t;<p><b>  }</b></p><p>  // 針對圖像每行進行操作</p><p>  for(i = 0; i < lNewHeight; i++)</p><p><b>  {</b></p><p>  // 針對圖像每列進行操作</p>&

117、lt;p>  for(j = 0; j < lNewWidth; j++)</p><p><b>  {</b></p><p>  // 指向新DIB第i行,第j個象素的指針</p><p>  // 注意此處寬度和高度是新DIB的寬度和高度</p><p>  lpDst = (char *)lpNew

118、DIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;</p><p>  // 計算該象素在源DIB中的坐標</p><p>  i0 = (LONG) (i / fYZoomRatio + 0.5);</p><p>  j0 = (LONG) (j / fXZoomRatio + 0.5);</p>

119、<p>  // 判斷是否在源圖范圍內</p><p>  if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))</p><p><b>  {</b></p><p>  // 指向源DI

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論