对于图像处理来说,如何从一幅bmp图像中读取它包含的信息,是十分重要的。对于matlab,只需要一句语句,足以。
im=imread('a.bmp');
而对于c++如何将文件读取到内存,或者将数据保存为bmp黑白图像,则需要研究图像是如何进行存储的。
一般的,黑白图像由文件头,信息头,调色板,最后才是位图矩阵信息组成。
文件头由图像的标识,大小,偏移量等组成,其定义为:
typedef struct tagBITMAPFILEHEADER {
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;
而信息头则由文件的长宽等信息组成,其定义为:
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;
其后为调色板,黑白图像调色板则为:
typedef struct tagRGBQUAD {
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;
最后才是我们比较关注的二维图像信息,其中,信息的位数一般为8bit,最大值为255。
对于读取BMP黑白图像,程序可以这么写:
bool LoadFromFile(const char* str, unsigned char* & data, int & width, int & height)
{
//以二进制方式打开图像文件
ifstream fin(str,ios::in|ios::_Nocreate|ios::binary);
if(!fin)
return false;
fin.seekg(0, ios::end);
DWORD size = fin.tellg();
//如果文件的大小小于1024+1024+40则放弃读入
if(size < 14+1024+40)
{
return false;
}
pAllData = new BYTE[size];
memset(pAllData, 0, size);
fin.seekg(0, ios::beg);
fin.read((char*)pAllData, size);
//如果文件的头信息不为0x4d42,则不读入
LPBITMAPFILEHEADER pBitMapFileHeader = (LPBITMAPFILEHEADER)pAllData;
if(pBitMapFileHeader->bfType != 0x4d42)
{
pBitMapFileHeader = NULL;
delete [] pAllData;
return false;
}
//读取位图文件的宽和高
LPBITMAPINFO pBitMapInfo = (LPBITMAPINFO) (pAllData + 14);
width = pBitMapInfo->bmiHeader.biWidth;
height = pBitMapInfo->bmiHeader.biHeight;
//将位图矩阵读入内存
data = new unsigned char[width*height];
memcpy(data, pAllData + 14 + 40 + 1024, width*height);
//删除数据,防止内存泄漏
delete [] pAllData;
return true;
}
对于将数据写到BMP黑白文件中去,程序可以这么写:
bool FiberWriteBitmap(UINT8* pImage, int biHeight , int biWidth, CString csPath)
{
BITMAPFILEHEADER BitmapFileHead;
BITMAPINFOHEADER BitmapInfoHead;
BitmapInfoHead.biSize = 40;
BitmapInfoHead.biBitCount = 8;
BitmapInfoHead.biClrUsed = 256;
BitmapInfoHead.biCompression = 0;
BitmapInfoHead.biHeight = biHeight ;
BitmapInfoHead.biPlanes = 1;
BitmapInfoHead.biClrImportant = 0;
BitmapInfoHead.biWidth = biWidth;
BitmapInfoHead.biXPelsPerMeter = 2835;// 72 dpi
BitmapInfoHead.biYPelsPerMeter = 2835;
BitmapInfoHead.biSizeImage = (DWORD)biHeight*biWidth;
static RGBQUAD palette[256];
for ( unsigned int i = 0; i< 256; i++ )
{
palette[i].rgbBlue = i;
palette[i].rgbGreen = i;
palette[i].rgbRed = i;
}
// Build fileheader and write
BitmapFileHead.bfType=('M' << 8) + 'B';
BitmapFileHead.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
256*sizeof(RGBQUAD);
BitmapFileHead.bfSize = BitmapFileHead.bfOffBits + BitmapInfoHead.biSizeImage;
BitmapInfoHead.biClrUsed=256;
BitmapInfoHead.biClrImportant=0;
BitmapFileHead.bfReserved1=0;
BitmapFileHead.bfReserved2=0;
CFile file;
if(!file.Open(csPath, CFile::modeCreate|CFile::modeWrite))
return false;
file.Write(&BitmapFileHead,sizeof(BITMAPFILEHEADER));
file.Write(&BitmapInfoHead,sizeof(BITMAPINFOHEADER));
file.Write(palette,sizeof(RGBQUAD)*256);
file.Write(pImage,biHeight*biWidth);
file.Close();
return TRUE;
}
将矩阵信息以黑白格式显示到屏幕上,程序为:
bool ShowDataToWindow(CDC *pDC,DWORD width, DWORD height, LPBYTE lpData, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight)
{
if(lpData == NULL)
return false;
LPBITMAPINFO lpBitMapInfo = (LPBITMAPINFO)new BYTE[40+1024];
lpBitMapInfo->bmiHeader.biSize = 40;
lpBitMapInfo->bmiHeader.biBitCount = 8;
lpBitMapInfo->bmiHeader.biClrUsed = 256;
lpBitMapInfo->bmiHeader.biCompression = 0;
lpBitMapInfo->bmiHeader.biHeight = height;
lpBitMapInfo->bmiHeader.biPlanes = 1;
lpBitMapInfo->bmiHeader.biClrImportant = 0;
lpBitMapInfo->bmiHeader.biWidth = width;
lpBitMapInfo->bmiHeader.biXPelsPerMeter = 2835;
lpBitMapInfo->bmiHeader.biYPelsPerMeter = 2835;
lpBitMapInfo->bmiHeader.biSizeImage = (DWORD)height*width;
LPBYTE lpQuad = (LPBYTE)lpBitMapInfo;
for(int i = 0;i<256;++i)
{
*(lpQuad+40+i*4+0) = (BYTE)i;
*(lpQuad+40+i*4+1) = (BYTE)i;
*(lpQuad+40+i*4+2) = (BYTE)i;
*(lpQuad+40+i*4+3) = 0xcc;
}
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(), xDest, yDest, DestWidth, DestHeight,
xSrc, ySrc, SrcWidth, SrcHeight, lpData, lpBitMapInfo, DIB_RGB_COLORS, SRCCOPY);
delete[] lpBitMapInfo;
return true;
}