有關於bmp圖檔的格式和讀檔問題(附程式!) |
尚未結案
|
mayroro
一般會員 發表:1 回覆:3 積分:0 註冊:2007-01-29 發送簡訊給我 |
小弟最近正在趕專題----「影像處理」,我是用C++去寫的(我用VC++,BCB我沒特地去學)。
現在我卡在兩個問題上面,希望大大們能夠一下小弟我....>< 問題一: bmp圖檔的文件格式,我大概了解了 [bmpfileheader → bmpinfoheader →調色盤→圖像數據] bmpfileheader bmpinfoheader = 54byte 在那個bmpfileheader 底下有兩個數據: 「bfsize」 = 圖檔大小 「bfOffBits」 = 調色盤 bmpfileheader bmpinfoheader (三樣數據所佔的byte) 然後小弟我,現在是卡在: 理論上,只要將「bfSize」 - 「bfOffBits」 = 圖像數據的大小 = Width * Height (圖檔的寬長,單位像素) 可是在我讀一些8bit 的bmp檔的時候卻不是這樣,會多出來。 例如: 我讀一個427*427的8bit 灰階圖檔,在我的程式下卻顯示: FileSize = 183562 DataOffset = 806 (bfOffBits) [PS:之後底下我會貼上程式,我先貼比較重要的數據。] 先算427*427 = 182329(圖像數據),根據上面的理論 1833562 - 806 = 182756 182756 - 182329 = 427 (這個427byte怎麼多出來的ㄚ...不懂...) 其他的4bit 和一些8bit的彩色就比較沒這個問題。 這個多出來的數據是哪裡的ㄚ?如果這個沒辦法解開的話,我就不知道這張圖的「圖像數據」該怎麼讀了。 問題二: 先附上程式: # include # include # include # include using namespace std; typedef long INT32; typedef unsigned short int INT16; typedef unsigned char U_CHAR; #define UCH(x) ((int) (x)) #define GET_2B(array,offset) ((INT16) UCH(array[offset]) \ (((INT16) UCH(array[offset 1])) << 8)) #define GET_4B(array,offset) ((INT32) UCH(array[offset]) \ (((INT32) UCH(array[offset 1])) << 8) \ (((INT32) UCH(array[offset 2])) << 16) \ (((INT32) UCH(array[offset 3])) << 24)) int main() { char pf= 'y'; while(pf == 'y' || pf == 'Y') { FILE *input_file = 0 ,*output_file = 0; U_CHAR bmpfileheader[14] = { 0 } ; U_CHAR bmpinfoheader[40] = { 0 } ; unsigned char *pbmprgbquad; unsigned char *pbmppixel; char filename[32]; short int i,j; /* 以下為bmp圖檔的格式 */ INT32 FileSize = 0 ; INT32 bfOffBits =0 ; INT32 headerSize =0 ; INT32 biWidth = 0 ; INT32 biHeight = 0 ; INT16 biPlanes = 0 ; INT16 BitCount = 0 ; INT32 biCompression = 0 ; INT32 biImageSize = 0; INT32 biXPelsPerMeter = 0 ,biYPelsPerMeter = 0 ; INT32 biClrUsed = 0 ; INT32 biClrImp = 0 ; /*********************************************************/ cout<< "請輸入圖檔名(只能用8bit以下):"; cin >> filename; if( ( input_file = fopen(filename,"rb") ) == NULL ){ cout << "開檔失敗!!失敗中的失敗!"< } fread(bmpfileheader,1,14,input_file); fread(bmpinfoheader,1,40,input_file); if (GET_2B(bmpfileheader,0) == 0x4D42) /* 'BM' */ fprintf(stdout,"BMP file.\n"); else{ fprintf(stdout,"Not bmp file.\n"); exit(0); } FileSize = GET_4B(bmpfileheader,2); bfOffBits = GET_4B(bmpfileheader,10); headerSize = GET_4B(bmpinfoheader,0); biWidth = GET_4B(bmpinfoheader,4); biHeight = GET_4B(bmpinfoheader,8); biPlanes = GET_2B(bmpinfoheader,12); BitCount = GET_2B(bmpinfoheader,14); biCompression = GET_4B(bmpinfoheader,16); biImageSize = GET_4B(bmpinfoheader,20); biXPelsPerMeter = GET_4B(bmpinfoheader,24); biYPelsPerMeter = GET_4B(bmpinfoheader,28); biClrUsed = GET_4B(bmpinfoheader,32); biClrImp = GET_4B(bmpinfoheader,36); printf("FileSize = %ld \n" "DataOffset = %ld \n" "HeaderSize = %ld \n" "Width = %ld \n" "Height = %ld \n" "Planes = %d \n" "BitCount = %d \n" "Compression = %ld \n" "ImageSize = %ld \n" "XpixelsPerM = %ld \n" "YpixelsPerM = %ld \n" "ColorsUsed = %ld \n" "ColorsImportant = %ld \n",FileSize,bfOffBits,headerSize,biWidth,biHeight,biPlanes, BitCount,biCompression,biImageSize,biXPelsPerMeter,biYPelsPerMeter,biClrUsed,biClrImp); i = bfOffBits-54; j = FileSize-bfOffBits; cout << "再輸入一次檔名吧:"; cin >> filename; if((output_file = fopen(filename,"wb")) == NULL) { cout << "囧!沒開成功!!!"; exit(0); } pbmprgbquad = new unsigned char[ i ]; pbmppixel = new unsigned char[ j ]; fread(pbmprgbquad,1,i,input_file); fread(pbmppixel,1,j,input_file); cout < fwrite(bmpfileheader,1,14,output_file); fwrite(bmpinfoheader,1,40,output_file); fwrite(pbmprgbquad,1,i,output_file); fwrite(pbmppixel,1,j,output_file); fclose (input_file); fclose(output_file); delete [] pbmprgbquad; delete [] pbmppixel; cout << "還要再來一次嗎?!(y / 其他鍵):"; cin >> pf; cout << endl; } return 0; } =============================================================================== 這個程式,等於是複製一個bmp檔就對了。 然後現在是卡在,在讀比小圖檔ok(例:100*100 以下的) 可是用在大圖檔的時候(427*427以上),就掛了。 讀圖檔ok,可是在寫數據到新圖檔的時候,電腦就說「readbmp.exe 發生問題」,之後就關閉了。 我是我的寫法有問題,就在那個紅字的地方。 小弟才剛學C 沒多久,對指標和記憶體配置真的不是很懂(我連用指標有啥好處,我都不知道~~QQ) ,這個程式還是去參考別人才會寫的,所以希望大大們能救救我一下。 以上這兩個問題,就拜託大大們了...QQ [PS:我有附那個上面所述的427*427的bmp檔,拜託各位大大幫小弟測試一下吧...orz] [PS:上面程式的include 部分,我貼不出來 ,我寫在下面好了 iostream.h stdio.h stdlib.h iomanip.h 請各位大大包涵了...orz |
fatmoon1
初階會員 發表:3 回覆:29 積分:36 註冊:2004-05-24 發送簡訊給我 |
|
mayroro
一般會員 發表:1 回覆:3 積分:0 註冊:2007-01-29 發送簡訊給我 |
===================引 用 文 章=================== 圖像數據大小好像是存於 biImageSize 這個值 不是單純 寬乘於高 所以 FileSize 應該等於 bfOffBits biImageSize =================================================== 問題二的部份,我已經解決了....orz 就只是單純把 i 和 j 的型態改回 「int 」就好.......orz (427*427 遠遠大過於2byte 所能儲存的數字。) 嗯....這個部分我就去查過。有些圖片的卻顯示bilmageSize = 0,這倒滿奇怪的~~@@ 網路上的資料也說這個部份不太重要就是了。 但是唯一可以肯定的就是「FileSize 應該等於 bfOffBits biImageSize」這是對的。 biimageSize >= 長*寬 那這樣的話,當此情形發生的時候 ,那我又該怎麼確定,哪些數據是真正控制該圖長、寬的pixel? 譬如說: 以我原本所說的那張圖為例,它是一張8bit的圖,控制一個pixel 只要一個byte就好, 換言之,(427*427 = 182329) 這張427*427的圖,我只要182329個byte 就好了。 可是,FileSize -bfOffBits = 182756 (182756 -182329 = 427 ) 這個427byte到底是啥ㄚ!?orz...不懂...可不可以請大大再賜教一下..還是不懂... 或者可以貼一連結給小弟一下,小弟現在目前對bmp圖檔格式還不是說很懂.... (PS:感謝上面的大大回覆...orz) |
fatmoon1
初階會員 發表:3 回覆:29 積分:36 註冊:2004-05-24 發送簡訊給我 |
|
mayroro
一般會員 發表:1 回覆:3 積分:0 註冊:2007-01-29 發送簡訊給我 |
|
fatmoon1
初階會員 發表:3 回覆:29 積分:36 註冊:2004-05-24 發送簡訊給我 |
你可以使用以下連結去搜尋本站有關 bmp 的文章
http://www.google.com.tw/search?q=bmp圖檔的格式 site:delphi.ktop.com.tw&hl=zh-TW&client=opera&rls=zh-tw 關於我看的Source Code是 Delphi 的 RX元件 的 RxGraph.pas , 節錄如下 <textarea class="delphi" rows="10" cols="60" name="code"> procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var BI: TBitmapInfoHeader; PixelFormat: TPixelFormat); var BM: WinTypes.TBitmap; begin GetObject(Bitmap, SizeOf(BM), @BM); with BI do begin biSize := SizeOf(BI); biWidth := BM.bmWidth; biHeight := BM.bmHeight; case PixelFormat of pf1bit: biBitCount := 1; pf4bit: biBitCount := 4; pf8bit: biBitCount := 8; pf24bit: biBitCount := 24; else biBitCount := BM.bmBitsPixel * BM.bmPlanes; end; biPlanes := 1; biXPelsPerMeter := 0; biYPelsPerMeter := 0; biClrUsed := 0; biClrImportant := 0; biCompression := BI_RGB; if biBitCount in [9..32] then biBitCount := 24; biSizeImage := (((biWidth * biBitCount 31) div 32) * 4) * biHeight; end; end;</textarea>
------
才疏學淺 |
mayroro
一般會員 發表:1 回覆:3 積分:0 註冊:2007-01-29 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |