線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:5576
推到 Plurk!
推到 Facebook!

有關於bmp圖檔的格式和讀檔問題(附程式!)

尚未結案
mayroro
一般會員


發表:1
回覆:3
積分:0
註冊:2007-01-29

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-02-11 12:58:00 IP:220.129.xxx.xxx 訂閱
小弟最近正在趕專題----「影像處理」,我是用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 << "開檔失敗!!失敗中的失敗!"< exit(0);
}

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

附加檔案:45cea258662ff_002.bmp
fatmoon1
初階會員


發表:3
回覆:29
積分:36
註冊:2004-05-24

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-02-12 00:59:51 IP:61.63.xxx.xxx 訂閱
圖像數據大小好像是存於 biImageSize 這個值
不是單純 寬乘於高
所以 FileSize 應該等於 bfOffBits biImageSize
------
才疏學淺
mayroro
一般會員


發表:1
回覆:3
積分:0
註冊:2007-01-29

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-02-12 17:56:33 IP:220.129.xxx.xxx 訂閱

===================引 用 文 章===================
圖像數據大小好像是存於 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

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-02-12 22:26:04 IP:61.63.xxx.xxx 訂閱
我對bmp格式也不懂
只是我去看別人的Source Code
有看到 biImageSize 是如此給值的
biImageSize = (((biWidth * BitCount 31) div 32) * 4) * biHeight;
------
才疏學淺
mayroro
一般會員


發表:1
回覆:3
積分:0
註冊:2007-01-29

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-02-13 01:58:49 IP:220.129.xxx.xxx 訂閱

===================引 用 文 章===================






可以貼一下,那個你說那篇文章的來源嗎!?@@
拜託了...大大....orz
fatmoon1
初階會員


發表:3
回覆:29
積分:36
註冊:2004-05-24

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-02-13 03:25:22 IP:61.63.xxx.xxx 訂閱
你可以使用以下連結去搜尋本站有關 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

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-02-15 20:37:02 IP:220.129.xxx.xxx 訂閱

===================引 用 文 章===================


感謝大大的回覆....orz...我努力慢慢研究中.....
系統時間:2024-05-04 19:03:44
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!