數(shù)字圖象處理計算機畢業(yè)論文
《數(shù)字圖象處理計算機畢業(yè)論文》由會員分享,可在線閱讀,更多相關(guān)《數(shù)字圖象處理計算機畢業(yè)論文(31頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、 摘要 圖片的合成和縮放我們實現(xiàn)了其基本的算法,本文通過bmp位圖數(shù)據(jù)源,通過采用雙線形插值,后處理操作和合成算法實現(xiàn)了對圖片的基本操作,并以此為基礎(chǔ)實現(xiàn)了對bmp位圖的讀寫。試驗結(jié)果表明,我們所實現(xiàn)的算法適用于對BMP位圖文件的基本操作。 在實現(xiàn)數(shù)字圖象處理的過程中,主要是通過對圖像中的每一個像素點運用各種圖像處理算法來達到預(yù)期的效果,所以進行圖像處理的第一步,也是我們最關(guān)心的問題,是如何得到圖像中每一個像素點的亮度值;為了觀察和驗證處理的圖像效果,另一個需要解決的問題是如何將處理前后的圖像正確的顯示出來。我們就是解決這些問題。 關(guān)鍵詞:圖片的合成和縮放;雙線形插值;bmp位圖;
2、數(shù)字圖象處理 vc++ picture processing implementation 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 synthesis algorithm has re
3、alized 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 to the BMP position chart document elementary operation. In the realization digital image processing pro
4、cess, mainly is through utilizes each kind of picture processing algorithm to in the picture each 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 orde
5、r to observe with the confirmation processing picture effect, around another needs to solve how will the question is process the picture correct demonstration. We solve these problems. Key words: Picture synthesis; Double linear interpolation; Bmp position chart; Digital image processing 目 錄
6、1 圖像縮放合成處理的意義國內(nèi)外的情況綜述…………………………… ……1 2 設(shè)備無關(guān)位圖文件的讀寫存和縮放………………………………………………2 2.1 BMP文件的格式… …………………………………………………………………2 2.1.1 BMP文件組成……………………………………………………………………2 2.1.2 BMP文件頭………………………………………………………………………2 2.1.3 位圖信息頭……………………………………………………………………3 2.1.4 顏色表…………………………………………………………………………3 2.1.5 位圖數(shù)據(jù)……
7、…………………………………………………………………4 2.2 BMP文件的讀寫……… ……………………………………………………………4 2.3 BMP文件的保存……… …………………………………………………………10 2.4 BMP文件的縮放…… ……………………………………………………………15 3 圖像合成的具體方法… ……………………………………………………………21 3.1 圖片合成算法詳解…………………………………………………………………21 3.2 圖片合成算法集的實現(xiàn) …… ……………………………………………………22 3.3 圖片合成檢查步驟……………
8、……………………………………………………24 4 試驗數(shù)據(jù)與展望 …… ………………………………………………………………25 4.1試驗數(shù)據(jù)…………………… ………………………………………………………25 4.2展望…………………………… ……………………………………………………26 參考文獻……………………………………………………………………………………28 致謝………… ………………………………………………………………………………30 引 言 數(shù)字圖像處理技術(shù)與理論是計算機應(yīng)用的一個重要領(lǐng)域,許多工程應(yīng)用都涉及到圖像處理,一直有一個強烈的愿望,想系統(tǒng)
9、的寫一個關(guān)于數(shù)字圖像處理的講座,由于工作學(xué)習(xí)很忙,時至今日才得以實現(xiàn)。 1 圖片縮放合成的意義,國內(nèi)外的情況綜述 “圖”是物體透射光或反射光的分布,“像”是人的視覺系統(tǒng)對圖的接收在大腦中形成的印象或認識。圖像是兩者的結(jié)合。人類獲取外界信息是靠聽覺、視覺、觸覺、嗅覺、味覺等,但絕大部分(約80%左右)來自視覺所接收的圖像信息。圖像處理就是對圖像信息進行加工處理,以滿足人的視覺心理和實際應(yīng)用的需要。簡單的說,依靠計算機對圖像進行各種目的的處理我們就稱之為數(shù)字圖像處理。早期的數(shù)字圖像處理的目的是以人為對象,為了滿足人的視覺效果而改善圖像的質(zhì)量,處理過程中輸入的是質(zhì)量差的圖像,輸出的是質(zhì)量好的
10、圖像,常用的圖像處理方法有圖像增強、復(fù)原等。隨著計算機技術(shù)的發(fā)展,有一類圖像處理是以機器為對象,處理的目的是使機器能夠自動識別目標,這稱之為圖像的識別,因為這其中要牽涉到一些復(fù)雜的模式識別的理論,討論其中最基本的內(nèi)容。由于在許多實際應(yīng)用的編程中往往都要涉及到數(shù)字圖像處理,涉及到圖像合成算法,討論如何利用微軟的Visual C++開發(fā)工具來實現(xiàn)一些常用的數(shù)字圖像處理算法,論述了圖像處理的理論,同時給出了VC實現(xiàn)的源代碼。 傳統(tǒng)的電腦只能處理文字、數(shù)字,最多是簡單的圖形。近年來,隨著電腦硬件技術(shù)的飛速發(fā)展和更新,使得計算機處理圖形圖像的能力大大增強。以前要用大型圖形工作站來運行的圖形應(yīng)用軟件,或
11、是特殊文件格式的生成及對圖形所作的各種復(fù)雜的處理和轉(zhuǎn)換;如今,很普遍的家用電腦就完全可以勝任,我們可以輕易的使用PhotoShop、CorelDraw、3D MAX或是別的什么軟件做出精美的圖片或是逼真的三維物體,你甚至可以自己去做一個有趣的動畫。 在當今信息社會,以多媒體為代表的信息技術(shù)和信息產(chǎn)業(yè)的發(fā)展和應(yīng)用對人類社會產(chǎn)生的影響和作用愈來愈明顯,愈來愈重要。多媒體的發(fā)展和應(yīng)用,極大地推動了諸多工業(yè)的相互滲透和飛速發(fā)展,逐步改變了整個人類社會的工作結(jié)構(gòu)和生活方式。可以毫不夸張地說,多媒體產(chǎn)業(yè)的形成和發(fā)展,將不僅引起計算機工業(yè)的一次革命,也將影響人類社會發(fā)生一場巨大的變革。我們知道,所謂多媒
12、體,即多種信息媒介,通常包括以下幾種:文本、圖形、影像、聲音、視頻、動畫。可以看出,多媒體的應(yīng)用在很大程度當依賴于豐富多彩的圖形和圖像。也就是說,圖形圖像技術(shù)的飛速發(fā)展也將是必然趨勢,掌握圖形圖像處理技術(shù)對一個計算機操作人員是必要的。計算機圖形學(xué)是研究用計算機生成、處理和顯示圖形的一門科學(xué)。為了生成圖形,首先要有原始數(shù)據(jù)或數(shù)學(xué)模型(如工程人員構(gòu)思的草圖、地形航測數(shù)據(jù)、飛機的,總體方案模型等),這些數(shù)字化的輸入信息經(jīng)過計算機處理后變成圖形輸出。 圖形從原始數(shù)據(jù)生成圖象數(shù)據(jù)經(jīng)過了一系列變換過程,每個變換過程都可能產(chǎn)生不同于輸入數(shù)據(jù)的輸出數(shù)據(jù),這些數(shù)據(jù)需要按一定的結(jié)構(gòu)進行組織,形成一系列描述圖形數(shù)
13、據(jù)的文件,我們把這類文件稱為圖形文件(也稱為圖形圖象文件),而圖象文件是描述圖象數(shù)據(jù)的文件,它是圖形文件的一種特例。 在圖形生成過程中有多種類型的數(shù)據(jù),如模型數(shù)據(jù)、場景數(shù)據(jù)和圖象數(shù)據(jù)等,因此,圖形文件所描述的圖形層次就不一樣,這也是產(chǎn)生多種圖形文件的一個重要原因。 另一方面,在同一個描述層上,由于每種圖形軟件包使用自己的格式保存圖形數(shù)據(jù),隨著圖形應(yīng)用軟件包的不斷增多,圖形文件的格式也會越來越多,雖然國際標準化組織(ISO)為解決圖形信息的共享問題,建立了一系列圖形文件標準(如CGM),但是這些標準較難得到廣大用戶和廠商的支持,從而形成了目前這種多種圖形文件共存的局面. 圖形文件有以下特點
14、:(1)數(shù)據(jù)量大。由于現(xiàn)在數(shù)據(jù)獲取手段日趨先進,可以得到的數(shù)據(jù)越來越復(fù)雜,數(shù)據(jù)量也增大。(2)結(jié)構(gòu)性強。數(shù)據(jù)在本質(zhì)上分為數(shù)字化的和模擬的兩種。模擬信息可以轉(zhuǎn)換為數(shù)字信息。數(shù)字系統(tǒng)中的最基本單位為位(bit),其他結(jié)構(gòu)單位都以位為礎(chǔ)。在較低層次上可以是“構(gòu)造塊”(如浮點數(shù)、整數(shù)和字符);在較高層次上可以是記錄(如Pascal中)或結(jié)構(gòu)(如C語言中),而圖形文件就是由特定的結(jié)構(gòu)或記錄組成的。每種圖形文件都按自己的方式組織圖形信息,由于圖形文件包含的數(shù)據(jù)量大,所以很多圖形文件都使用一定的壓縮算法來壓縮圖形數(shù)據(jù)。 2 設(shè)備無關(guān)位圖文件的讀寫存和縮放 2.1 BMP文件的格式 2.1.1 BMP文
15、件組成 BMP文件由文件頭、位圖信息頭、顏色信息和圖形數(shù)據(jù)四部分組成。文件頭主要包含文件的大小、文件類型、圖像數(shù)據(jù)偏離文件頭的長度等信息;位圖信息頭包含圖象的尺寸信息、圖像用幾個比特數(shù)值來表示一個像素、圖像是否壓縮、圖像所用的顏色數(shù)等信息。顏色信息包含圖像所用到的顏色表,顯示圖像時需用到這個顏色表來生成調(diào)色板,但如果圖像為真彩色,既圖像的每個像素用24個比特來表示,文件中就沒有這一塊信息,也就不需要操作調(diào)色板。文件中的數(shù)據(jù)塊表示圖像的相應(yīng)的像素值,需要注意的是:圖像的像素值在文件中的存放順序為從左到右,從下到上,也就是說,在BMP文件中首先存放的是圖像的最后一行像素,最后才存儲圖像的第
16、一行像素,但對與同一行的像素,則是按照先左邊后右邊的的順序存儲的;另外一個需要讀者朋友關(guān)注的細節(jié)是:文件存儲圖像的每一行像素值時,如果存儲該行像素值所占的字節(jié)數(shù)為4的倍數(shù),則正常存儲,否則,需要在后端補0,湊足4的倍數(shù)。 2.1.2 BMP文件頭 BMP文件頭數(shù)據(jù)結(jié)構(gòu)含有BMP文件的類型、文件大小和位圖起始位置等信息。其結(jié)構(gòu)定義如下: typedef struct tagBITMAPFILEHEADER { WORD bfType; // 位圖文件的類型,必須為"BM" DWORD bfSize; // 位圖文件的大小,以字節(jié)為單位 WORD bfReserve
17、d1; // 位圖文件保留字,必須為0 WORD bfReserved2; // 位圖文件保留字,必須為0 DWORD bfOffBits; // 位圖數(shù)據(jù)的起始位置,以相對于位圖文件頭的偏移量表示,以字節(jié)為單位 } BITMAPFILEHEADER;該結(jié)構(gòu)占據(jù)14個字節(jié)。 2.1.3 位圖信息頭 BMP位圖信息頭數(shù)據(jù)用于說明位圖的尺寸等信息。其結(jié)構(gòu)如下: typedef struct tagBITMAPINFOHEADER{ DWORD biSize; // 本結(jié)構(gòu)所占用字節(jié)數(shù) LONG biWidth; // 位圖的寬度,以像素為單位 LONG b
18、iHeight; // 位圖的高度,以像素為單位 WORD biPlanes; // 目標設(shè)備的平面數(shù)不清,必須為1 WORD biBitCount// 每個像素所需的位數(shù),必須是1(雙色), 4(16色),8(256色)或24(真彩色)之一 DWORD biCompression; // 位圖壓縮類型,必須是 0(不壓縮),1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一 DWORD biSizeImage; // 位圖的大小,以字節(jié)為單位 LONG biXPelsPerMeter; // 位圖水平分辨率,每米像素數(shù) LONG biYPelsPerMet
19、er; // 位圖垂直分辨率,每米像素數(shù) DWORD biClrUsed;// 位圖實際使用的顏色表中的顏色數(shù) DWORD biClrImportant;// 位圖顯示過程中重要的顏色數(shù) } BITMAPINFOHEADER;該結(jié)構(gòu)占據(jù)40個字節(jié)。 注意:對于BMP文件格式,在處理單色圖像和真彩色圖像的時候,無論圖象數(shù)據(jù)多么龐大,都不對圖象數(shù)據(jù)進行任何壓縮處理,一般情況下,如果位圖采用壓縮格式,那么16色圖像采用RLE4壓縮算法,256色圖像采用RLE8壓縮算法。 2.1.4 顏色表 顏色表用于說明位圖中的顏色,它有若干個表項,每一個表項是一個RGBQUAD
20、類型的結(jié)構(gòu),定義一種顏色。RGBQUAD結(jié)構(gòu)的定義如下: typedef struct tagRGBQUAD { BYTErgbBlue;// 藍色的亮度(值范圍為0-255) BYTErgbGreen; // 綠色的亮度(值范圍為0-255) BYTErgbRed; // 紅色的亮度(值范圍為0-255) BYTErgbReserved;// 保留,必須為0 } RGBQUAD; 顏色表中RGBQUAD結(jié)構(gòu)數(shù)據(jù)的個數(shù)由BITMAPINFOHEADER 中的biBitCount項來確定,當biBitCount=1,4,8時,分別有2,16,256個顏色表項,當b
21、iBitCount=24時,圖像為真彩色,圖像中每個像素的顏色用三個字節(jié)表示,分別對應(yīng)R、G、B值,圖像文件沒有顏色表項。位圖信息頭和顏色表組成位圖信息,BITMAPINFO結(jié)構(gòu)定義如下: typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; // 位圖信息頭 RGBQUAD bmiColors[1]; // 顏色表 } BITMAPINFO; 注意:RGBQUAD數(shù)據(jù)結(jié)構(gòu)中,增加了一個保留字段rgbReserved,它不代表任何顏色,必須取固定的值為"0",同時, RGBQUAD結(jié)構(gòu)中定義的顏色值中,紅色
22、、綠色和藍色的排列順序與一般真彩色圖像文件的顏色數(shù)據(jù)排列順序恰好相反,既:若某個位圖中的一個像素點的顏色的描述為"00,00,ff,00",則表示該點為紅色,而不是藍色。 2.1.5 位圖數(shù)據(jù) 位圖數(shù)據(jù)記錄了位圖的每一個像素值或該對應(yīng)像素的顏色表的索引值,圖像記錄順序是在掃描行內(nèi)是從左到右,掃描行之間是從下到上。這種格式我們又稱為Bottom_Up位圖,當然與之相對的還有Up_Down形式的位圖,它的記錄順序是從上到下的,對于這種形式的位圖,也不存在壓縮形式。位圖的一個像素值所占的字節(jié)數(shù):當biBitCount=1時,8個像素占1個字節(jié);當biBitCount=4時,2個像素占
23、1個字節(jié);當 biBitCount=8時,1個像素占1個字節(jié);當biBitCount=24時,1個像素占3個字節(jié),此時圖像為真彩色圖像。當圖像不是為真彩色時,圖像文件中包含顏色表,位圖的數(shù)據(jù)表示對應(yīng)像素點在顏色表中相應(yīng)的索引值,當為真彩色時,每一個像素用三個字節(jié)表示圖像相應(yīng)像素點彩色值,每個字節(jié)分別對應(yīng)R、G、B分量的值,這時候圖像文件中沒有顏色表。上面我已經(jīng)講過了,Windows規(guī)定圖像文件中一個掃描行所占的字節(jié)數(shù)必須是4的倍數(shù)(即以字為單位),不足的以0填充,圖像文件中一個掃描行所占的字節(jié)數(shù)計算方法: DataSizePerLine= (biWidth* biBitCount+31)/
24、8;// 一個掃描行所占的字節(jié) 位圖數(shù)據(jù)的大小按下式計算(不壓縮情況下): DataSize= DataSizePerLine* biHeight。 2.2 BMP文件的讀寫 如今Windows(3.x以及95,98,NT)系列已經(jīng)成為絕大多數(shù)用戶使用的操作系統(tǒng),它比DOS成功的一個重要因素是它可視化的漂亮界面。那么Windows是如何顯示圖象的呢?這就要談到位圖(bitmap)。 我們知道,普通的顯示器屏幕是由許許多多點構(gòu)成的,我們稱之為象素。顯示時采用掃描的方法:電子槍每次從左到右掃描一行,為每個象素著色,然后從上到下這樣掃描若干行,就掃過了一屏。為了防止閃爍,每秒要重復(fù)上述過
25、程幾十次。例如我們常說的屏幕分辨率為640480,刷新頻率為70Hz,意思是說每行要掃描640個象素,一共有480行,每秒重復(fù)掃描屏幕70次。我們稱這種顯示器為位映象設(shè)備。所謂位映象,就是指一個二維的象素矩陣,而位圖就是采用位映象方法顯示和存儲的圖象。舉個例子,圖1.1是一幅普通的黑白位圖,圖1.2是被放大后的圖,圖中每個方格代表了一個象素。我們可以看到:整個骷髏就是由這樣一些黑點和白點組成的。 先來說說三元色RGB概念。我們知道,自然界中的所有顏色都可以由紅、綠、藍(R,G,B)組合而成。有的顏色含有紅色成分多一些,如深紅;有的含有紅色成分少一些,如淺紅。針對含有紅色成分的多少,可以分成0
26、到255共256個等級,0級表示不含紅色成分;255級表示含有100%的紅色成分。同樣,綠色和藍色也被分成256級。這種分級概念稱為量化。 這樣,根據(jù)紅、綠、藍各種不同的組合我們就能表示出256256256,約1600萬種顏色。這么多顏色對于我們?nèi)搜蹃碚f已經(jīng)足夠豐富了。 表1.1 常見顏色的RGB組合值 顏色 R G B 紅 255 0 0 藍 0 255 0 綠 0 0 255 黃 255 255 0 紫 255 0 255 青 0 255 255 白 255 255 255 黑 0 0 0 灰 128
27、 128 128 在實現(xiàn)數(shù)字圖象處理的過程中,主要是通過對圖像中的每一個像素點運用各種圖像處理算法來達到預(yù)期的效果,所以進行圖像處理的第一步,也是我們最關(guān)心的問題,是如何得到圖像中每一個像素點的亮度值;為了觀察和驗證處理的圖像效果,另一個需要解決的問題是如何將處理前后的圖像正確的顯示出來。我們這章內(nèi)容就是解決這些問題。 隨著科技的發(fā)展,圖像處理技術(shù)已經(jīng)滲透到人類生活的各個領(lǐng)域并得到越來越多的應(yīng)用,但是突出的一個矛盾是圖像的格式也是越來越多,目前圖像處理所涉及的主要的圖像格式就有很多種,如TIF、JEMP、BMP等等,一般情況下,為了處理簡單方便,進行數(shù)字圖像處理所采用的都
28、是BMP格式的圖像文件(有時也稱為DIB格式的圖像文件),并且這種格式的文件是沒有壓縮的。我們通過操作這種格式的文件,可以獲取正確顯示圖像所需的調(diào)色板信息,圖像的尺寸信息,圖像中各個像素點的亮度信息等等,有了這些數(shù)據(jù),開發(fā)人員就可以對圖像施加各種處理算法,進行相應(yīng)的處理。如果特殊情況下需要處理其它某種格式的圖像,如GIF、JEMP等格式的圖象文件,可以首先將該格式轉(zhuǎn)換為BMP格式,然后再進行相應(yīng)的處理。這一點需要讀者清楚。 BMP格式的圖像文件又可以分為許多種類,如真彩色位圖、256色位圖,采用RLE(游程編碼)壓縮格式的BMP位圖等等。由于在實際的工程應(yīng)用和圖像算法效果驗證中經(jīng)常要處
29、理的是256級并且是沒有壓縮的BMP灰度圖像,例如通過黑白采集卡采集得到的圖像就是這種格式,所以我們在整個講座中范例所處理的文件格式都是BMP灰度圖像。如果讀者對這種格式的位圖能夠作到熟練的操作,那么對于其余形式的BMP位圖的操作也不會很困難。 BMP灰度圖像作為Windows環(huán)境下主要的圖像格式之一,以其格式簡單,適應(yīng)性強而倍受歡迎。正如我們在上一講中介紹過的那樣,這種文件格式就是每一個像素用8bit表示,顯示出來的圖像是黑白效果,最黑的像素的灰度(也叫作亮度)值為"0",最白的像素的灰度值為"255",整個圖像各個像素的灰度值隨機的分布在"0"到"255"的區(qū)間中,越黑的像素,其灰
30、度值越接近于"0",越白(既越亮)的像素,其灰度值越接近于"255";與此對應(yīng)的是在該文件類型中的顏色表項的各個RGB分量值是相等的,并且顏色表項的數(shù)目是256個。 在進行圖像處理時,操作圖像中的像素值就要得到圖像陣列;經(jīng)過處理后的圖像的像素值需要存儲起來;顯示圖像時要正確實現(xiàn)調(diào)色板、得到位圖的尺寸信息等。 可以根據(jù)BMP位圖文件的結(jié)構(gòu),操作BMP位圖文件并讀入圖像數(shù)據(jù),為此我們充分利用了VC的對話框結(jié)構(gòu),自己新建ReadDIBFile()函數(shù),這樣用戶就可以在自動生成程序的打開文件對話框中選擇所要打開的位圖文件,然后程序?qū)⒆詣诱{(diào)用該函數(shù)執(zhí)行讀取數(shù)據(jù)的操作。該函數(shù)的實現(xiàn)代碼如下所示
31、 HDIB WINAPI ReadDIBFile(CFile& file) { BITMAPFILEHEADER bmfHeader; DWORD dwBitsSize; HDIB hDIB; LPSTR pDIB; // 獲取DIB(文件)長度(字節(jié)) dwBitsSize = file.GetLength(); // 嘗試讀取DIB文件頭 if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader)) { // 大小不對,返回NULL。 return NUL
32、L; } // 判斷是否是DIB對象,檢查頭兩個字節(jié)是否是"BM" if (bmfHeader.bfType != DIB_HEADER_MARKER) { // 非DIB對象,返回NULL。 return NULL; } // 為DIB分配內(nèi)存 hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize); if (hDIB == 0) { // 內(nèi)存分配失敗,返回NULL。 return NULL; } // 鎖定 pDIB = (L
33、PSTR) ::GlobalLock((HGLOBAL) hDIB); // 讀象素 if (file.ReadHuge(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) != dwBitsSize - sizeof(BITMAPFILEHEADER) ) { // 大小不對。 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 釋放內(nèi)存 ::GlobalFree((HGLOBAL) hDIB); // 返回NULL。 return
34、NULL; } // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDIB); // 返回DIB句柄 return hDIB; } 呼叫兩個函數(shù)之一來顯示DIB時,您需要幾個關(guān)于圖像的信息。如果除了文件表頭外,整個文件被儲存在內(nèi)存的連續(xù)區(qū)塊中,指向該內(nèi)存塊開始處(也就是信息表頭的開頭)的指標被稱為指向packed DIB的指標。因為整個DIB由單個指標(如pPackedDib)引用,所以packed DIB是在內(nèi)存中儲存DIB的方便方法,您可以把指標定義為指向BYTE的指標。使用本章前面所示的結(jié)構(gòu)定義,能得到所有儲存在DIB內(nèi)的信息,包括色彩對照表
35、和個別圖素位。然而,要想得到這么多信息,還需要一些程序代碼。例如,您不能通過以下敘述簡單地取得DIB的圖素寬度:iWidth = ((PBITMAPINFOHEADER) pPackedDib)->biWidth ; DIB有可能是OS/2兼容格式的。在那種格式中,packed DIB以BITMAPCOREHEADER結(jié)構(gòu)開始,并且DIB的圖素寬度和高度以16位WORD,而不是32位LONG儲存。因此,首先必須檢查DIB是否為舊的格式,然后進行相對應(yīng)的操作: if(((PBITMAPCOREHEADER) pPackedDib)->bcSize == sizeof (BITMAPCOREHE
36、ADER)) iWidth = ((PBITMAPCOREHEADER) pPackedDib)->bcWidth ; else iWidth = ((PBITMAPINFOHEADER) pPackedDib)->biWidth ; SetDIBitsToDevice和StretchDIBits函數(shù)需要兩個指向DIB的指標,因為這兩個部分不在連續(xù)的內(nèi)存塊內(nèi)。確實,把DIB分成兩個內(nèi)存塊是很有用的,只是我們更喜歡與整個DIB儲存在單個內(nèi)存塊的packed DIB打交道。除了這兩個指標,SetDIBitsToDevice和StretchDIBit
37、s函數(shù)通常也需要DIB的圖素寬度和高度。如只想顯示DIB的一部分,就不必明確地知道這些值,但它們會定義您在DIB圖素位數(shù)組內(nèi)定義的矩形的上限。點對點圖素顯示 SetDIBitsToDevice函數(shù)顯示沒有延伸和縮小的DIB。DIB的每個圖素對應(yīng)到輸出設(shè)備的一個圖素上,而且DIB中的圖像一定會被正確顯示出來-也就是說,圖像的頂列在上方。任何會影響設(shè)備內(nèi)容的坐標轉(zhuǎn)換都影響了顯示DIB的開始位置,但不影響顯示出來的圖片大小和方向。 不要對參數(shù)的數(shù)量感到厭煩,在多數(shù)情況下,函數(shù)用起來比看起來要簡單。不過在其它用途上來說,它的用法真的是亂七八糟,不過我們將學(xué)會怎么用它。 和GDI顯示函數(shù)一樣,Set
38、DIBitsToDevice的第一個參數(shù)是設(shè)備內(nèi)容句柄,它指出顯示DIB的設(shè)備。下面兩個參數(shù)xDst和yDst,是輸出設(shè)備的邏輯坐標,并指出了顯示DIB圖像左上角的坐標(「上端」指的是視覺上的上方,并不是DIB圖素的第一行)。注意,這些都是邏輯坐標,因此它們附屬于實際上起作用的任何坐標轉(zhuǎn)換方式或-在Windows NT的情況下-設(shè)定的任何空間轉(zhuǎn)換。在內(nèi)定的MM_TEXT映像方式下,可以把這些參數(shù)設(shè)為0,從顯示平面上向左向上顯示DIB圖像。 可以顯示整個DIB圖像或僅顯示其中的一部分,這就是后四個參數(shù)的作用。但是DIB圖素數(shù)據(jù)的由上而下的方向產(chǎn)生了許多誤解,待會兒會談到這些?,F(xiàn)在應(yīng)該清楚當顯
39、示整個DIB時,應(yīng)把xSrc和ySrc設(shè)定為0,并且cxSrc和cySrc應(yīng)分別等于DIB的圖素寬度和高度。注意,因為BITMAPINFOHEADER結(jié)構(gòu)的biHeight字段對于由上而下的DIB來說是負的,cySrc應(yīng)設(shè)定為biHeight字段的絕對值。 pBits參數(shù)是指向DIB圖素位的指針。pInfo參數(shù)是指向DIB的BITMAPINFO結(jié)構(gòu)的指針。雖然BITMAPINFO結(jié)構(gòu)的地址與BITMAPINFOHEADER結(jié)構(gòu)的地址相同,但是SetDIBitsToDevice結(jié)構(gòu)被定義為使用BITMAPINFO結(jié)構(gòu),暗示著:對于1位、4位和8位DIB,位圖信息表頭后必須跟著色彩對照表。盡管p
40、Info參數(shù)被定義為指向BITMAPINFO結(jié)構(gòu)的指針,它也是指向BITMAPCOREINFO、BITMAPV4HEADER或BITMAPV5HEADER結(jié)構(gòu)的指針。 2.3 BMP文件的保存 /************************************************************************* * * 函數(shù)名稱: * SaveDIB() * * 參數(shù): * HDIB hDib - 要保存的DIB * CFile& file - 保存文件CFile * * 返回值
41、: * BOOL - 成功返回TRUE,否則返回FALSE或者CFileException * * 說明: * 該函數(shù)將指定的DIB對象保存到指定的CFile中。該CFile由調(diào)用程序打開和關(guān)閉。 * *************************************************************************/ BOOL WINAPI SaveDIB(HDIB hDib, CFile& file) { // Bitmap文件頭 BITMAPFILEHEADER bmfHdr;
42、 // 指向BITMAPINFOHEADER的指針 LPBITMAPINFOHEADER lpBI; // DIB大小 DWORD dwDIBSize; if (hDib == NULL) { // 如果DIB為空,返回FALSE return FALSE; } // 讀取BITMAPINFO結(jié)構(gòu),并鎖定 lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib); if (lpBI == NULL) { // 為空,返回FALSE return F
43、ALSE; } // 判斷是否是WIN3.0 DIB if (!IS_WIN30_DIB(lpBI)) { // 不支持其它類型的DIB保存 // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib); // 返回FALSE return FALSE; } // 填充文件頭 // 文件類型"BM" bmfHdr.bfType = DIB_HEADER_MARKER; // 計算DIB大小時,最簡單的方法是調(diào)用GlobalSize()函數(shù)。但是全局內(nèi)存大小并 // 不是DIB
44、真正的大小,它總是多幾個字節(jié)。這樣就需要計算一下DIB的真實大小。 // 文件頭大小+顏色表大小 // (BITMAPINFOHEADER和BITMAPCOREHEADER結(jié)構(gòu)的第一個DWORD都是該結(jié)構(gòu)的大?。? dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // 計算圖像大小 if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4)) { // 對于RLE位圖,沒法計算大小,只能信任biSizeI
45、mage內(nèi)的值 dwDIBSize += lpBI->biSizeImage; } else { // 象素的大小 DWORD dwBmBitsSize; // 大小為Width * Height dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * lpBI->biHeight; // 計算出DIB真正的大小 dwDIBSize += dwBmBitsSize; // 更新biSizeImage(很多BMP文件頭中biSizeIm
46、age的值是錯誤的) lpBI->biSizeImage = dwBmBitsSize; } // 計算文件大?。篋IB大小+BITMAPFILEHEADER結(jié)構(gòu)大小 bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER); // 兩個保留字 bmfHdr.bfReserved1 = 0; bmfHdr.bfReserved2 = 0; // 計算偏移量bfOffBits,它的大小為Bitmap文件頭大?。獶IB頭大?。伾泶笮? bmfHdr.bfOffBits = (DWORD)sizeof(
47、BITMAPFILEHEADER) + lpBI->biSize + PaletteSize((LPSTR)lpBI); // 嘗試寫文件 TRY { // 寫文件頭 file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER)); // 寫DIB頭和象素 file.WriteHuge(lpBI, dwDIBSize); } CATCH (CFileException, e) { // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib);
48、 // 拋出異常 THROW_LAST(); } END_CATCH // 解除鎖定 ::GlobalUnlock((HGLOBAL) hDib); // 返回TRUE return TRUE; } 2.4 BMP文件的縮放 由于放大圖象時產(chǎn)生了新的象素,以及浮點數(shù)的操作,得到的坐標可能并不是整數(shù),這一點我們在介紹旋轉(zhuǎn)時就提到了。我們采用的做法是找與之最臨近的點。實際上,更精確的做法是采用插值(interpolation),即利用鄰域的象素來估計新的象素值。其實我們前面的做法也是一種插值,稱為最鄰近插值(Nearest Nei
49、ghbour Interpolation)。下面先介紹線形插值(Linear Interpolation)。 線形插值使用原圖中兩個值來構(gòu)造所求坐標處的值。舉一個一維的例子。如圖2.16所示,如果已經(jīng)知道了兩點x0,x2處的函數(shù)值f(x0),f(x2),現(xiàn)在要求x1處的函數(shù)值f(x1)。我們假設(shè)函數(shù)是線形的,利用幾何知識可以知道 f(x1)=(f(x2)-f(x0))(x1-x0)/(x2-x0)+f(x0) 在圖象處理中需要將線形插值擴展到二維的情況,即采用雙線形插值(Bilinear Intrepolation). 圖2.17為雙線形插值的示意圖。 圖2.16 線形插值的示意圖
50、 圖.217 雙線形插值的示意圖 已知a、b、c、d四點的灰度,要求e點的灰度,可以先在水平方向上由a,b線形插值求出g、c、d線形插值求出f,然后在垂直方向上由g,f線形插值求出e。 線形插值基于這樣的假設(shè):原圖的灰度在兩個象素之間是線形變化的。一般情況下,這種插值的效果還不錯。更精確的方法是采用曲線插值(Curvilinear Interpolation),即認為象素之間的灰度變化規(guī)律符合某種曲線,但這種處理的計算量是很大的。 /*************************************************************************
51、 * * 函數(shù)名稱: * ZoomDIB() * * 參數(shù): * LPSTR lpDIB - 指向源DIB的指針 * float fXZoomRatio - X軸方向縮放比率 * float fYZoomRatio - Y軸方向縮放比率 * * 返回值: * HGLOBAL - 縮放成功返回新DIB句柄,否則返回NULL。 * * 說明: * 該函數(shù)用來縮放DIB圖像,返回新生成DIB的句柄。 * *********************************************
52、***************************/ HGLOBAL WINAPI ZoomDIB(LPSTR lpDIB, float fXZoomRatio, float fYZoomRatio) { // 源圖像的寬度和高度 LONG lWidth; LONG lHeight; // 縮放后圖像的寬度和高度 LONG lNewWidth; LONG lNewHeight; // 縮放后圖像的寬度(lNewWidth,必須是4的倍數(shù)) LONG lNewLineBytes; // 指向源圖像的指針 LPSTR lp
53、DIBBits; // 指向源象素的指針 LPSTR lpSrc; // 縮放后新DIB句柄 HDIB hDIB; // 指向縮放圖像對應(yīng)象素的指針 LPSTR lpDst; // 指向縮放圖像的指針 LPSTR lpNewDIB; LPSTR lpNewDIBBits; // 指向BITMAPINFO結(jié)構(gòu)的指針(Win3.0) LPBITMAPINFOHEADER lpbmi; // 指向BITMAPCOREINFO結(jié)構(gòu)的指針 LPBITMAPCOREHEADER lpbmc; // 循環(huán)變量(
54、象素在新DIB中的坐標) LONG i; LONG j; // 象素在源DIB中的坐標 LONG i0; LONG j0; // 圖像每行的字節(jié)數(shù) LONG lLineBytes; // 找到源DIB圖像象素起始位置 lpDIBBits = ::FindDIBBits(lpDIB); // 獲取圖像的寬度 lWidth = ::DIBWidth(lpDIB); // 計算圖像每行的字節(jié)數(shù) lLineBytes = WIDTHBYTES(lWidth * 8); // 獲取圖像的高度 lHeight
55、= ::DIBHeight(lpDIB); // 計算縮放后的圖像實際寬度 // 此處直接加0.5是由于強制類型轉(zhuǎn)換時不四舍五入,而是直接截去小數(shù)部分 lNewWidth = (LONG) (::DIBWidth(lpDIB) * fXZoomRatio + 0.5); // 計算新圖像每行的字節(jié)數(shù) lNewLineBytes = WIDTHBYTES(lNewWidth * 8); // 計算縮放后的圖像高度 lNewHeight = (LONG) (lHeight * fYZoomRatio + 0.5); // 分配內(nèi)存,以保存新D
56、IB hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB)); // 判斷是否內(nèi)存分配失敗 if (hDIB == NULL) { // 分配內(nèi)存失敗 return NULL; } // 鎖定內(nèi)存 lpNewDIB = (char * )::GlobalLock((HGLOBAL) hDIB); // 復(fù)制DIB信息頭和調(diào)色板 memcpy(lpNewDIB, lpDIB, *(
57、LPDWORD)lpDIB + ::PaletteSize(lpDIB)); // 找到新DIB象素起始位置 lpNewDIBBits = ::FindDIBBits(lpNewDIB); // 獲取指針 lpbmi = (LPBITMAPINFOHEADER)lpNewDIB; lpbmc = (LPBITMAPCOREHEADER)lpNewDIB; // 更新DIB中圖像的高度和寬度 if (IS_WIN30_DIB(lpNewDIB)) { // 對于Windows 3.0 DIB lpbmi->biWidth = lNew
58、Width; lpbmi->biHeight = lNewHeight; } else { // 對于其它格式的DIB lpbmc->bcWidth = (unsigned short) lNewWidth; lpbmc->bcHeight = (unsigned short) lNewHeight; } // 針對圖像每行進行操作 for(i = 0; i < lNewHeight; i++) { // 針對圖像每列進行操作 for(j = 0; j < lNewWidth; j++) { // 指
59、向新DIB第i行,第j個象素的指針 // 注意此處寬度和高度是新DIB的寬度和高度 lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j; // 計算該象素在源DIB中的坐標 i0 = (LONG) (i / fYZoomRatio + 0.5); j0 = (LONG) (j / fXZoomRatio + 0.5); // 判斷是否在源圖范圍內(nèi) if( (j0 >= 0) && (j0 < lWidth) && (i0 >=
60、0) && (i0 < lHeight)) { // 指向源DIB第i0行,第j0個象素的指針 lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0; // 復(fù)制象素 *lpDst = *lpSrc; } else { // 對于源圖中沒有的象素,直接賦值為255 * ((unsigned char*)lpDst) = 255; } } } // 返回 r
61、eturn hDIB; } 3 圖像合成的具體方法 3.1 圖片合成算法詳解 首先,要能取得前景圖與背景圖顏色的 RGB三基色,然后用r,g,b 為最后取得的顏色值;r1,g1,b1是上層的顏色值;r2,g2,b2是下層顏色值 r = r1/2 + r2/2; g = g1/2 + g2/2; b = b1/2 + b2/2; 以上為50%透明。若要使用不同的透明度用以下算法(ALPHA=透明度): (50%以下) r = r1 - r1/ALPHA + r2/ALPHA; g = g1 - g1/ALPHA + g2/ALPHA; b = b1 - b1/ALPHA
62、+ b2/ALPHA; (50%以上) r = r1/ALPHA + r2 - r2/ALPHA; g = g1/ALPHA + g2 - g2/ALPHA; b = b1/ALPHA + b2 - b2/ALPHA; 在32/64K色模式下,由于每個點的RGB值是放在一個字里,以16位色為例,一般是按RGB或BGR 565存放。傳統(tǒng)的軟件Alpha混合算法是先將RGB分離出來,分開運算,然后再合成。這造成了16位模式下的alpha混合比24位模式下慢 的現(xiàn)象,但使用16位色真的那么慢嗎?我認為如果不使用MMX指令,15/16的比24位的快。因為我們可以使用一個小的技巧來同時計算RG
63、B。而24位顏色,除非使用MMX指令,否則必須分開計算R、G、B。 先設(shè)顏色(color)是RGB 565的,那么按二進制看,這個顏色字是這樣分布的: RRRRR GGGGGG BBBBB 5位 6位 5位 RGB成分 而386以上CPU都有32位的寄存器,我們只需要將16位RGB變形為: 00000 GGGGGG 00000 RRRRR 000000 BBBBB 5位 6位 5位 5位 6位 5位 變形后的RGB成分 儲存在32位寄存器中,(就是把綠色提到前16位里)由于64K色下顏色深度是32級的,所以alpha也只用分32級就能滿足
64、需要。那么對上面變形過的雙字處理,可以同時算RGB了。(Color1*Alpha+Color2*(32-Alpha))/32能不能簡化為(Color1-Color2)*Alpha/32+Color2. 以為減法將產(chǎn)生負數(shù),這樣再算乘法時有可能出問題,但是經(jīng)過測試,這樣簡化似乎又沒有問題。畢竟極小的誤差是可以忽略的。 3.2 圖片合成算法集的實現(xiàn) m_dibMake=m_dibBack; CPalette m_palette; ::CreateDIBPalette(m_dibMake , &m_palette); LPSTR lpDIB = (LPSTR) ::Glob
65、alLock((HGLOBAL) m_dibMake ); // 獲取DIB寬度 int cxDIB = (int) ::DIBWidth(lpDIB); // 獲取DIB高度 int cyDIB = (int) ::DIBHeight(lpDIB); ::GlobalUnlock((HGLOBAL) m_dibMake); CDC *pDC; CWnd *pWnd0= GetDlgItem(IDC_MAKE); pDC = pWnd0->GetDC(); CRect rc; pDC->GetWindow()->GetCl
66、ientRect(&rc); CRect rcDIB; rcDIB.top = rcDIB.left=0; rcDIB.right = cxDIB; rcDIB.bottom = cyDIB; HBITMAP hBitmap_front=DIBToBitmap(m_dibFront, m_palette); HBITMAP hBitmap_back=DIBToBitmap(m_dibBack, m_palette); CBitmap bmp1,bmp2; BITMAP bmpX,bmpY; bmp1.Attach(hBitmap_front); bmp2.Attach(hBitmap_back); bmp1.GetBitmap(&bmpX); UINT* bmpBuffer=(UINT*)GlobalAlloc(GPTR,bmpX.bmWidthBytes*bmpX.bmHeight); bmp1.GetBitmapB
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 《有機化合物的合成》
- 某知名化妝品公司各部門職責(zé)
- 八年級數(shù)學(xué)上冊 第13章 全等三角形 13.4 三角形的尺規(guī)作圖優(yōu)質(zhì)課件 (新版)冀教版
- 化學(xué)九上人教版第六單元課題3第1課時
- 長春版小學(xué)五年級下《桂林山水甲天下》
- 現(xiàn)代社會更需要通才-攻辯
- 海底兩萬里(康塞爾)
- 客戶經(jīng)理積分考核介紹
- 現(xiàn)代教育技術(shù)培訓(xùn)
- 混凝土預(yù)制樁、鋼樁施工
- 氨基酸類藥物
- 威尼斯建筑與藝術(shù)雙年展掠影
- 地產(chǎn)營銷操作手冊課件
- 15機械的效率和自鎖222
- 建筑施工事故案例分析