// Image Processing
: Homework #2 - BMP Gray Scale Image Saving //
// Deadline
: 3/10/2004
_____________________________________________________________________________________
題目: 將經處理過後的二維陣列結果, 顯示在電腦螢幕上,
並存成灰階模式的 BMP 影像檔。
_____________________________________________________________________________________
// 將存有處理結果的
2D 陣列, 秀到一個影像物件 GrayImage 中
GrayImage->Height=
ImageHeight;
GrayImage->Width= ImageWidth;
// 要把 GrayImage 影像物件的
property AutoSize 設為 false 才行
for (i=0;i<ImageHeight;i++)
for (j=0;j<ImageWidth;j++)
GrayImage->Canvas->Pixels[j][i]=(TColor)RGB(GrayMatrix[i][j],GrayMatrix[i][j],GrayMatrix[i][j]);
// 將一個彩色影像物件,
儲存成彩色 BMP 檔案格式的指令
if ( SavePictureDialog1->Execute()
)
{
Image->Picture->SaveToFile(SavePictureDialog1->FileName);
}
_____________________________________________________________________________________
// 因為 BMP 的儲存格式中,
影像的寬度內定為 4 的倍數, 用一個變數 BMPImageWigth4 紀錄
int
BMPImageWidth4;
Mod4 = ImageWidth %
4;
if ( Mod4 == 0 )
BMPImageWigth4 = ImageWidth;
else
BMPImageWigth4 = (((int)((ImageWidth-Mod4)/4))+ 1) * 4 ;
_____________________________________________________________________________________
// 宣告及釋放一個一維陣列的記憶體,
// 在將影像 output
為 Gray BMP file , 將二維影像轉為一維資料時, 暫存之用
unsigned char *BMPImage;
// free
if (BMPImageOpen
== 1)
{
delete[] BMPImage;
BMPImageOpen = 0;
}
// allocate
try {
BMPImage = new unsigned char [BMPImageWigth4*ImageHeight];
BMPImageOpen = 1;
}
catch (std::bad_alloc)
{ // #include <iostream.h>
ShowMessage("Could not allocate memory...Bye");
BMPImageOpen = 0;
exit(-1);
}
_____________________________________________________________________________________
FILE
*BMPOutput;
char
BMPFileName[45];
// 宣告一個資料型態
BMP_Header_TYPE,
其結構為 BMP 檔頭中, 有關 File Information 的部分
typedef struct {
unsigned char bfTYPE[2];
// 固定為 'BM', 用以辨認是否為 DIB
unsigned char bfSIZE[4];
// 檔案長度
short bfRESERVED1;
// 固定為 0 , 保留未用
short bfRESERVED2;
// 固定為 0 , 保留未用
unsigned char bfOFFSET[4];
// 儲存圖像資料到檔頭的距離
} BMP_Header_TYPE;
// 宣告一個變數 Header[1],
其型態為剛剛宣告的 BMP_Header_TYPE
BMP_Header_TYPE
Header[1];
// 宣告一個資料型態
BitmapInfoHeader_TYPE
,
// 其結構為 BMP 檔頭中,
有關 Bitmap Information 的部分
typedef struct {
unsigned char biSIZE[4];
// 宣告圖像基本資料的大小 ( = 40 )
unsigned char biWIDTH[4];
// 圖像的寬度, 以 pixel 為單位
unsigned char biHEIGHT[4];
// 圖像的高度, 以 pixel 為單位
unsigned char biPLANES[2];
// 固定存入 1
unsigned char biBITCOUNT[2];
// 宣告每個 pixel 需要多少 bit 儲存
unsigned char biCOMPRESSIOM[4];
// 宣告圖像壓縮方式, 可能的值有 3 種 : 0,
1, 2
unsigned char biSIZEIMAGE[4];
// 影像大小, 以 Byte 為單位 ( W*H*BitCount
/ 8 )
unsigned char biXPELSPERMETER[4]; //
宣告圖像在 X 方向於 1 公尺有多少 pixel ,
unsigned char biYPELSPERMETER[4]; //
宣告圖像在 Y 方向於 1 公尺有多少 pixel ,
unsigned char biCOLORUSED[4];
// 宣告圖像資料實際用到的顏色數目 ( 0表示用光
)
unsigned char biCOLORIMPORTANT[4]; //
宣告調色盤中, 多少顏色在顯示時是重要的
} BitmapInfoHeader_TYPE;
// 宣告一個變數 BitmapInfoHeader[1],
// 其型態為剛剛宣告的
BitmapInfoHeader_TYPE
BitmapInfoHeader_TYPE
BitmapInfoHeader[1];
// 宣告一個資料型態
Palette_COLOR_TYPE
,
// 其結構為 BMP 檔頭中,
有關 Palette 的部分
typedef struct {
unsigned char BLUE;
unsigned char GREEN;
unsigned char RED;
unsigned char RESERVED;
} Palette_COLOR_TYPE;
// 宣告 256 個變數 PaletteColors[256]
用來儲存調色盤的顏色,
// 型態為剛宣告的 Palette_COLOR_TYPE
Palette_COLOR_TYPE
PaletteColors[256];
// 宣告 2 個變數; 儲存檔案結束控制碼
unsigned char FILEEND[2];
// 檔案的最後有 2 個 byte 的 0
_____________________________________________________________________________________
int i,j;
int BMPFileSize, BMPImageSize;
int BMPHeight, BMPWidth;
if ( BMPSaveDialog->Execute() )
{
strcpy(BMPFileName,BMPSaveDialog->FileName.c_str());
if ((BMPOutput = fopen(BMPFileName,"wb"))==NULL)
{
ShowMessage("Can't Open"+BMPSaveDialog->FileName);
if ( errno==ENOENT ) //
必須要加入此行 #include <errno.h>
在程式最前面才行
ShowMessage(IntToStr(errno));
close(1);
// 必須要加入此行 #include
<io.h> 在程式最前面才行
}
}
Header[0].bfTYPE[0] = 66;
//"B"
Header[0].bfTYPE[1] = 77;
//"M"
BMPFileSize = 1080
+ ImageWidth * ImageHeight;
Header[0].bfSIZE[0]= (unsigned char)(BMPFileSize % 256);
BMPFileSize = BMPFileSize >> 8;
Header[0].bfSIZE[1]=(unsigned char)(BMPFileSize % 256);
BMPFileSize = BMPFileSize >> 8;
Header[0].bfSIZE[2]=(unsigned char)(BMPFileSize % 256);
BMPFileSize = BMPFileSize >> 8;
Header[0].bfSIZE[3]=(unsigned char)(BMPFileSize % 256);
Header[0].bfRESERVED1 = 0;
Header[0].bfRESERVED2 = 0;
Header[0].bfOFFSET[0] = 54;
// 4 * 256 + 54 = 1078
Header[0].bfOFFSET[1] = 4;
Header[0].bfOFFSET[2] = 0;
Header[0].bfOFFSET[3] = 0;
fwrite(Header,1,14,BMPOutput);
BitmapInfoHeader[0].biSIZE[0] = 40;
BitmapInfoHeader[0].biSIZE[1] = 0;
BitmapInfoHeader[0].biSIZE[2] = 0;
BitmapInfoHeader[0].biSIZE[3] = 0;
BMPWidth = ImageWidth;
BitmapInfoHeader[0].biWIDTH[0]= (unsigned char)(BMPWidth % 256);
BMPWidth = BMPWidth >> 8;
BitmapInfoHeader[0].biWIDTH[1]=(unsigned char)(BMPWidth % 256);
BMPWidth = BMPWidth >> 8;
BitmapInfoHeader[0].biWIDTH[2]=(unsigned char)(BMPWidth % 256);
BMPWidth = BMPWidth >> 8;
BitmapInfoHeader[0].biWIDTH[3]=(unsigned char)(BMPWidth % 256);
BMPHeight = ImageHeight;
BitmapInfoHeader[0].biHEIGHT[0]= (unsigned char)(BMPHeight % 256);
BMPHeight = BMPHeight >> 8;
BitmapInfoHeader[0].biHEIGHT[1]=(unsigned char)(BMPHeight % 256);
BMPHeight = BMPHeight >> 8;
BitmapInfoHeader[0].biHEIGHT[2]=(unsigned char)(BMPHeight % 256);
BMPHeight = BMPHeight >> 8;
BitmapInfoHeader[0].biHEIGHT[3]=(unsigned char)(BMPHeight % 256);
BitmapInfoHeader[0].biPLANES[0] = 1;
BitmapInfoHeader[0].biPLANES[1] = 0;
BitmapInfoHeader[0].biBITCOUNT[0] = 8;
BitmapInfoHeader[0].biBITCOUNT[1] = 0;
BitmapInfoHeader[0].biCOMPRESSIOM[0] = 0; //
沒有壓縮
BitmapInfoHeader[0].biCOMPRESSIOM[1] = 0;
BitmapInfoHeader[0].biCOMPRESSIOM[2] = 0;
BitmapInfoHeader[0].biCOMPRESSIOM[3] = 0;
BMPImageSize = ImageHeight*ImageWidth;
BitmapInfoHeader[0].biSIZEIMAGE[0]= (unsigned char)(BMPImageSize % 256);
BMPImageSize = BMPImageSize >> 8;
BitmapInfoHeader[0].biSIZEIMAGE[1]=(unsigned char)(BMPImageSize % 256);
BMPImageSize = BMPImageSize >> 8;
BitmapInfoHeader[0].biSIZEIMAGE[2]=(unsigned char)(BMPImageSize % 256);
BMPImageSize = BMPImageSize >> 8;
BitmapInfoHeader[0].biSIZEIMAGE[3]=(unsigned char)(BMPImageSize % 256);
BitmapInfoHeader[0].biXPELSPERMETER[0] = 18;
//
72 dpi , (100 / 2.54)*72 = 2834
BitmapInfoHeader[0].biXPELSPERMETER[1] = 11;
BitmapInfoHeader[0].biXPELSPERMETER[2] = 0;
BitmapInfoHeader[0].biXPELSPERMETER[3] = 0;
BitmapInfoHeader[0].biYPELSPERMETER[0] = 18;
//
72 dpi
BitmapInfoHeader[0].biYPELSPERMETER[1] = 11;
BitmapInfoHeader[0].biYPELSPERMETER[2] = 0;
BitmapInfoHeader[0].biYPELSPERMETER[3] = 0;
BitmapInfoHeader[0].biCOLORUSED[0] = 0;
BitmapInfoHeader[0].biCOLORUSED[1] = 0;
BitmapInfoHeader[0].biCOLORUSED[2] = 0;
BitmapInfoHeader[0].biCOLORUSED[3] = 0;
BitmapInfoHeader[0].biCOLORIMPORTANT[0] = 0;
BitmapInfoHeader[0].biCOLORIMPORTANT[1] = 0;
BitmapInfoHeader[0].biCOLORIMPORTANT[2] = 0;
BitmapInfoHeader[0].biCOLORIMPORTANT[3] = 0;
fwrite(BitmapInfoHeader,1,40,BMPOutput);
//
設定灰階影像調色盤的值
for (i=0;i<256;i++)
{
PaletteColors[i].BLUE = (unsigned char) i ;
PaletteColors[i].GREEN = (unsigned char) i;
PaletteColors[i].RED = (unsigned char) i;
PaletteColors[i].RESERVED = (unsigned char) 0;
}
// 將調色盤寫入檔案中
fwrite(PaletteColors,256,4,BMPOutput);
//
將二維的影像資料轉成一維的資料,
方便輸出
for (i=0;i<ImageHeight;i++)
for (j=0;j<ImageWidth;j++)
BMPImage[i*BMPImageWigth4+j]
= ImageMatrix[ImageHeight-i-1][j];
fwrite(BMPImage,1,ImageHeight*BMPImageWigth4,BMPOutput);
FILEEND[0] = 0;
FILEEND[1] = 0;
fwrite(FILEEND,2,1,BMPOutput);
fclose(BMPOutput);
__________________________________________________________________________________
Last Modification
: 02/22/2004
by Yeuan-Kuen
Lee, CSIE, MCU
|