VC6.0讀取位圖、顯示位圖與保存位圖之全攻略知識講解_第1頁
VC6.0讀取位圖、顯示位圖與保存位圖之全攻略知識講解_第2頁
VC6.0讀取位圖、顯示位圖與保存位圖之全攻略知識講解_第3頁
VC6.0讀取位圖、顯示位圖與保存位圖之全攻略知識講解_第4頁
VC6.0讀取位圖、顯示位圖與保存位圖之全攻略知識講解_第5頁
已閱讀5頁,還剩21頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Good is good, but better carries it.精益求精,善益求善。VC6.0讀取位圖、顯示位圖與保存位圖之全攻略-作者:彭軍一、了解位圖的文件結(jié)構(gòu)我這里要說的主要是如何讀入8位或24位位圖。因?yàn)檫@兩種格式的位圖更加具有代表性。如32位位圖也只是多了一個透明度的分量罷了。其跟24位位圖的格式相比變化不大。我們常說進(jìn)行數(shù)字圖像處理,其實(shí)主要是處理位圖的像素數(shù)據(jù)和采用何種算法去處理像素數(shù)據(jù)。可是,要想處理像素數(shù)據(jù),首先就是要讀入位圖的數(shù)據(jù)。不然,處理從何談起。下面我將詳細(xì)的說明BMP位圖的文件結(jié)構(gòu),相信看完之后,對于讀入位圖就不是什么難事了。當(dāng)然,我這里的前提是你熟悉如何讀

2、入文件。好了,廢話不多說了。我們開始吧。BMP位圖的第一部分就是文件頭。下面是它的結(jié)構(gòu):typedefstructtagBITMAPFILEHEADERWORDbfType;DWORDbfSize;WORDbfReserved1;WORDbfReserved2;DWORDbfOffBits;BITMAPFILEHEADER,*PBITMAPFILEHEADER;上面的這個文件頭的結(jié)構(gòu)體是摘自MSDN。它的各項(xiàng)的含義如下:bfType代表的是文件格式,就是“BM”,用十六進(jìn)制的數(shù)表示是0 x4d42,用十進(jìn)制的數(shù)表示就是19778。所以,從BMP文件的前兩個字節(jié)我們就可以判斷我們要打開的圖片是不

3、是位圖,如果不是的話,我們就可以不用讀了。bfSize代表的是該位圖文件的大?。ò募^、信息頭、調(diào)色板(如果有)、像素數(shù)據(jù))。它是一個DWORD類型,占4個字節(jié)。bfReserved1和bfReserved2都是保留量,因此它們應(yīng)該都為0。它們合起來占4個字節(jié)。bfOffBits代表的是像素數(shù)據(jù)距離文件頭的位置,也就是偏移地址。如果我們想直接讀像素數(shù)據(jù)的話,可以把文件指針偏移bfOffBits個字節(jié),然后讀取就可以了,知道讀到文件結(jié)尾。這樣算起來,文件頭一共占了2+4+2+2+4=14字節(jié)。所以,這個文件頭的大小固定是14字節(jié)的。而且,還有重要的一點(diǎn)是,其實(shí)在保存BMP文件的時候,保存的順

4、序也是按照bfType、bfSize、bfReserved1、bfReserved2、bfOffBits的順序的。因此,如果我們不想用微軟的這個結(jié)構(gòu)體的話,你可以按照上面的順序依次的讀入各項(xiàng),用不用這個結(jié)構(gòu)體,關(guān)系不是很大。不過只是說,用結(jié)構(gòu)體的話,可能會帶來一些方便罷了。這一點(diǎn),在當(dāng)你用C或Java來讀取的時候,會感覺更深刻。因?yàn)樵贑或Java中沒有微軟提供的這個結(jié)構(gòu)體,要么自己構(gòu)造這個結(jié)構(gòu)體,要么你就按找順序和字節(jié)數(shù)依次讀出各項(xiàng)的值。后面有我的C和Java讀入位圖的例子,你可以參看下。BMP位圖的第二部分就是信息頭。下面是它的結(jié)構(gòu):typedefstructtagBITMAPINFOHEA

5、DERDWORDbiSize;LONGbiWidth;LONGbiHeight;WORDbiPlanes;WORDbiBitCount;DWORDbiCompression;DWORDbiSizeImage;LONGbiXPelsPerMeter;LONGbiYPelsPerMeter;DWORDbiClrUsed;DWORDbiClrImportant;BITMAPINFOHEADER,*PBITMAPINFOHEADER;當(dāng)然了,這個結(jié)構(gòu)體還是來自MSDN的。biSize代表的是該結(jié)構(gòu)體的大小,即40字節(jié)。biWidth代表的是位圖的寬度,以像素為單位。biHeight代表的是位圖的高度,

6、以像素為單位。biPlanes代表的位圖的平面數(shù),平面數(shù)不同,RGB各分量所排列的順序不一樣。一般常見的是1,也就是RGB各分量是按照BGR的順序在像素數(shù)據(jù)中排列的。biBitCount代表的是位圖的位數(shù),有1、16、8、24、32等。biCompression代表是位圖的壓縮方法,由于BMP位圖是沒有壓縮的,所以通常情況下它的值都為0。biSizeImage代表的是位圖像素數(shù)據(jù)的大小,就是高度乘上每行像素所占的字節(jié)數(shù)。biXPelsPerMeter代表的是水平方向的分辨率,以米為單位。這個參數(shù)沒有什么太大的意義,至少現(xiàn)在我還沒發(fā)現(xiàn)。所以,它通常情況下都為0,不是0也沒有關(guān)系。biYPelsP

7、erMeter代表的是垂直方向的分辨率,以米為單位,通常為0。biClrUsed代表的是位圖用到的顏色數(shù),可以設(shè)置為0,代表的是全部用到了。biClrImportant代表的是位圖中重要的顏色數(shù),可以設(shè)置為0,代表的是全部都很重要。LONG和DWORD都占4個字節(jié),WORD占2個字節(jié),因此,該結(jié)構(gòu)體(也就是信息頭)共占40字節(jié)。還要說明的一點(diǎn)是,在保存位圖的時候,我們也可以按照上面的結(jié)構(gòu)體中各項(xiàng)的順序來保存位圖。在讀入位圖的時候,也可以按字節(jié)和上面的順序來依次讀入各項(xiàng)。用不用結(jié)構(gòu)體,關(guān)系不大。還是那句話,當(dāng)你用C或Java讀入信息頭的時候,就會理解這個順序的重要性了。typedefstruct

8、tagRGBQUADBYTErgbBlue;BYTErgbGreen;BYTErgbRed;BYTErgbReserved;RGBQUAD同樣,上面的這個結(jié)構(gòu)體仍然來自MSDN。首先要說明的一點(diǎn)是,只有8位位圖具有調(diào)色板。而調(diào)色板是有若干項(xiàng)(最多256項(xiàng))構(gòu)成的,而每一項(xiàng)都是一個RGBQUAD的結(jié)構(gòu)體,也就是說每一項(xiàng)都有一個藍(lán)色、綠色、紅色和保留量。而在8位位圖中,如果我們讀到的biClrUsed不為0,代表沒有全部用上256中顏色的話,那代表像素數(shù)據(jù)的偏移地址就不是1078(14+40+256*4=1078)。這樣其實(shí)也完全沒有影響,我們在讀入和保存位圖的時候,對于8位位圖來說,完全沒有必要

9、去讀入調(diào)色板。因?yàn)槲覀兺耆梢宰约喝?gòu)造一個調(diào)色板,如下面的程序:RGBQUAD*pal=newRGBQUAD256;for(inti=0;i1000#pragmaonce#endif/_MSC_VER1000/CReadImageDlgdialogclassCReadImageDlg:publicCDialog/Constructionpublic:BYTE*m_pPixel;BYTE*m_pBmInfo;BITMAPFILEHEADER*m_pBmfh;CReadImageDlg(CWnd*pParent=NULL);/standardconstructor/DialogData/AFX_

10、DATA(CReadImageDlg)enumIDD=IDD_READIMAGE_DIALOG;/NOTE:theClassWizardwilladddatamembershere/AFX_DATA/ClassWizardgeneratedvirtualfunctionoverrides/AFX_VIRTUAL(CReadImageDlg)protected:virtualvoidDoDataExchange(CDataExchange*pDX);/DDX/DDVsupport/AFX_VIRTUAL/Implementationprotected:HICONm_hIcon;/Generate

11、dmessagemapfunctions/AFX_MSG(CReadImageDlg)virtualBOOLOnInitDialog();afx_msgvoidOnSysCommand(UINTnID,LPARAMlParam);afx_msgvoidOnPaint();afx_msgHCURSOROnQueryDragIcon();/AFX_MSGDECLARE_MESSAGE_MAP();/AFX_INSERT_LOCATION/MicrosoftVisualC+willinsertadditionaldeclarationsimmediatelybeforethepreviousline

12、.#endif/!defined(AFX_READIMAGEDLG_H_FD65CF60_4E3C_4111_B736_CD4B51F1CE63_INCLUDED_)CReadImageDlg的構(gòu)造函數(shù)中添加一句程序:m_pBmfh=newBITMAPFILEHEADER;添加完成后,其構(gòu)造函數(shù)為:CReadImageDlg:CReadImageDlg(CWnd*pParent/*=NULL*/):CDialog(CReadImageDlg:IDD,pParent)/AFX_DATA_INIT(CReadImageDlg)/NOTE:theClassWizardwilladdmemberini

13、tializationhere/AFX_DATA_INIT/NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32m_hIcon=AfxGetApp()-LoadIcon(IDR_MAINFRAME);/為位圖文件頭指針分配一個空間m_pBmfh=newBITMAPFILEHEADER;然后為Read按鈕添加單擊的響應(yīng)函數(shù),在下面寫入如下程序:voidCReadImageDlg:OnBtnRead()/TODO:Addyourcontrolnotificationhandlercodehere/用打開對話框獲得要打開位圖的路徑CF

14、ileDialogdlg(true,*.bmp,NULL,OFN_OVERWRITEPROMPT|OFN_HIDEREADONLY,BMPfiles(*.bmp)|*.bmp|);if(dlg.DoModal()!=IDOK)return;/新建一個CFile類的對象dib,并以讀的模式打開CFiledib(dlg.GetPathName(),CFile:modeRead);/讀入位圖文件頭dib.Read(m_pBmfh,sizeof(BITMAPFILEHEADER);/為位圖信息(信息頭+調(diào)色板(如果有的話)分配空間m_pBmInfo=newBYTEm_pBmfh-bfOffBits-1

15、4;/讀入位圖信息,其大小為像素數(shù)據(jù)的偏移地址-位圖文件頭大小dib.Read(m_pBmInfo,m_pBmfh-bfOffBits-14);/下面的程序的目的是計算像素矩陣的大小,就是為了得到height和LineBytes/新建一個位圖信息頭變量BITMAPINFOHEADERbmih;/拷貝一個信息頭大小的字節(jié)到該變量中memcpy(&bmih,m_pBmInfo,sizeof(BITMAPINFOHEADER);/從信息頭中獲取位圖的信息longwidth=bmih.biWidth;/獲取寬度intbitCount=bmih.biBitCount;/獲取位數(shù)longheight=bm

16、ih.biHeight;/獲取高度longLineBytes=(width*bitCount+31)/32*4;/計算每行像素所占的字節(jié)數(shù)/為像素矩陣分配空間m_pPixel=newBYTEheight*LineBytes;/讀入位圖的像素矩陣dib.Read(m_pPixel,height*LineBytes);/關(guān)閉文件dib.Close();為Show按鈕添加一個響應(yīng)函數(shù),其代碼如下:voidCReadImageDlg:OnBtnShow()/TODO:AddyourcontrolnotificationhandlercodehereBITMAPINFOHEADERbmih;memcpy

17、(&bmih,m_pBmInfo,sizeof(BITMAPINFOHEADER);longwidth=bmih.biWidth;longheight=bmih.biHeight;StretchDIBits(GetDC()-m_hDC,0,0,width,height,0,0,width,height,m_pPixel,(BITMAPINFO*)m_pBmInfo,DIB_RGB_COLORS,SRCCOPY);為Save按鈕添加一個響應(yīng)函數(shù),其代碼如下:voidCReadImageDlg:OnBtnSave()/TODO:Addyourcontrolnotificationhandlerco

18、dehere/用保存對話框獲取保存路徑CFileDialogdlg(false,*.bmp,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,BMPfiles(*.bmp)|*.bmp|);if(dlg.DoModal()!=IDOK)return;/以寫二進(jìn)制數(shù)據(jù)的方式,打開文件CFiledib(dlg.GetPathName(),CFile:modeCreate|CFile:modeWrite|CFile:typeBinary);/寫入已經(jīng)讀入的文件頭dib.Write(m_pBmfh,sizeof(BITMAPFILEHEADER);/寫入已經(jīng)讀入的位圖信息(信息頭+調(diào)色板(如果有的話)dib.Write(m_pBmInfo,m_pBmfh-bfOffBits-14);/下面的程

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論