#include <stdio.h> #include <stdlib.h> #include <string.h> #define BYTE unsigned char #define WORD short #define DWORD long #define SUCCESS 0 #define FAILURE 0xFFFFFFFF #define VOID void #define CHECK_NULL_POINT(x) { if(NULL == (x)) return FAILURE;} #define CHECK_NULL_RETURN(x) { if(0 == (x)) return FAILURE; } #define CHECK_FALSE_RETURN(x) { if(!(x)) return FAILURE; } #define CHECK_FAIL_RETURN(x) { if(FAILURE == (x)) return FAILURE; } #define GET_RGB_QUAD_SIZE(x) (1 == (x) ? 2 : (4 == (x) ? 16 : (8 == (x) ? 256 : (16 == (x) ? 65536 : 0)))) #define LOG_ERR(format, ...) do { printf("[ ERR ]: "); printf(format, ##__VA_ARGS__); } while (0) #define LOG_DBG(format, ...) do { printf("[ DBG ]: "); printf(format, ##__VA_ARGS__); } while (0) #define LOG_INF(format, ...) do { printf("[ INF ]: "); printf(format, ##__VA_ARGS__); } while (0) typedef struct tagBitmapFileHeader { WORD bfAlign; //字节对齐 WORD bfType;//位图文件的类型,必须为BM(1-2字节) DWORD bfSize;//位图文件的大小,以字节为单位(3-6字节,低位在前) WORD bfReserved1;//位图文件保留字,必须为0(7-8字节) WORD bfReserved2;//位图文件保留字,必须为0(9-10字节) DWORD bfOffBits;//位图数据的起始位置,以相对于位图(11-14字节,低位在前) //文件头的偏移量表示,以字节为单位 }BitmapFileHeader; typedef struct tagBitmapInfoHeader{ DWORD biSize;//本结构所占用字节数(15-18字节) DWORD biWidth;//位图的宽度,以像素为单位(19-22字节) DWORD biHeight;//位图的高度,以像素为单位(23-26字节) WORD biPlanes;//目标设备的级别,必须为1(27-28字节) WORD biBitCount;//每个像素所需的位数,必须是1(双色),(29-30字节) //4(16色),8(256色)16(高彩色)或24(真彩色)之一 DWORD biCompression;//位图压缩类型,必须是0(不压缩),(31-34字节) //1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 DWORD biSizeImage;//位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节) DWORD biXPelsPerMeter;//位图水平分辨率,每米像素数(39-42字节) DWORD biYPelsPerMeter;//位图垂直分辨率,每米像素数(43-46字节) DWORD biClrUsed;//位图实际使用的颜色表中的颜色数(47-50字节) DWORD biClrImportant;//位图显示过程中重要的颜色数(51-54字节) }BitmapInfoHeader; /** * 当biBitCount = 1, 4, 8时,分别有2, 16, 256个表项; * 当biBitCount = 24时,没有颜色表项。 */ typedef struct tagRgbQuad{ BYTE rgbBlue;//蓝色的亮度(值范围为0-255) BYTE rgbGreen;//绿色的亮度(值范围为0-255) BYTE rgbRed;//红色的亮度(值范围为0-255) BYTE rgbReserved;//保留,必须为0 }RgbQuad; typedef struct tagBitmapInfo{ BitmapInfoHeader biInfoHeader;//位图信息头 RgbQuad *rgbQuad; //颜色表 WORD rgbQuadSize; // 颜色表大小 }BitmapInfo; typedef struct tagBitmapHandle{ BitmapFileHeader biFileHeader; // 文件头 BitmapInfo biInfo; // 位图信息头 + 颜色表 BYTE **bPixelMatrix; // 像素矩阵 }BitmapHandle; DWORD InitBitmapHandle(BitmapHandle *biHandle) { CHECK_NULL_POINT(biHandle); memset(biHandle, 0, sizeof(BitmapHandle)); return SUCCESS; } DWORD CheckBitmapFileHeader(BitmapFileHeader *biFileHeader) { CHECK_NULL_POINT(biFileHeader); CHECK_FALSE_RETURN(0x4D42 == biFileHeader->bfType); return SUCCESS; } DWORD CheckBitmapInfoHeader(BitmapInfoHeader *biInfoHeader) { WORD biBitCount; CHECK_NULL_POINT(biInfoHeader); CHECK_FALSE_RETURN(1 == biInfoHeader->biPlanes); biBitCount = biInfoHeader->biBitCount; CHECK_FALSE_RETURN(1 == biBitCount || 4 == biBitCount || 8 == biBitCount || 16 == biBitCount || 24 == biBitCount); CHECK_FALSE_RETURN(0 == biInfoHeader->biCompression); return SUCCESS; } DWORD ReadBmpInfo(FILE *pBmpFile, BitmapHandle *biHandle) { DWORD dRet; BitmapFileHeader *biFileHeader; BitmapInfo *biInfo; BitmapInfoHeader *biInfoHeader; LOG_DBG("....start ReadBmpInfo.... "); CHECK_NULL_POINT(pBmpFile); CHECK_NULL_POINT(biHandle); biFileHeader = &biHandle->biFileHeader; biInfo = &biHandle->biInfo; biInfoHeader = &biInfo->biInfoHeader; dRet = fread(&biFileHeader->bfType, sizeof(BitmapFileHeader)-sizeof(WORD), 1, pBmpFile); CHECK_NULL_RETURN(dRet); LOG_DBG("ReadBmpInfo: read bitmap file header success! "); dRet = CheckBitmapFileHeader(biFileHeader); CHECK_FAIL_RETURN(dRet); LOG_DBG("ReadBmpInfo: check bitmap file header success! "); dRet = fread(biInfoHeader, sizeof(BitmapInfoHeader), 1, pBmpFile); CHECK_NULL_RETURN(dRet); LOG_DBG("ReadBmpInfo: read bitmap info header success! "); dRet = CheckBitmapInfoHeader(biInfoHeader); CHECK_FAIL_RETURN(dRet); LOG_DBG("ReadBmpInfo: check bitmap info header success! "); biInfo->rgbQuadSize = GET_RGB_QUAD_SIZE(biInfoHeader->biBitCount); biInfo->rgbQuad = (biInfo->rgbQuadSize == 0) ? NULL : ((RgbQuad*)malloc(biInfo->rgbQuadSize*sizeof(RgbQuad))); CHECK_NULL_POINT(biInfo->rgbQuad); LOG_DBG("ReadBmpInfo: start read RGB quad... "); dRet = fread(biInfo->rgbQuad, sizeof(RgbQuad), biInfo->rgbQuadSize, pBmpFile); CHECK_FAIL_RETURN(dRet); LOG_DBG("ReadBmpInfo: read RGB quad success! "); LOG_DBG("....end ReadBmpInfo.... "); return SUCCESS; } DWORD ReadBmpData(FILE *pBmpFile, BitmapHandle *biHandle) { DWORD biWidth; DWORD biHeight; WORD biBitCount; DWORD dwRowBits; DWORD dwRowBytes; WORD loop; BYTE *buff; DWORD dRet; BitmapInfo *biInfo; BitmapInfoHeader *biInfoHeader; LOG_DBG("....start ReadBmpData.... "); CHECK_NULL_POINT(pBmpFile); CHECK_NULL_POINT(biHandle); biInfo = &biHandle->biInfo; CHECK_NULL_POINT(biInfo); biInfoHeader = &biHandle->biInfo.biInfoHeader; CHECK_NULL_POINT(biInfoHeader); biWidth = biInfoHeader->biWidth; biHeight = biInfoHeader->biHeight; biBitCount = biInfoHeader->biBitCount; dwRowBits = biWidth * biBitCount; dwRowBytes = dwRowBits >> 3 + ((dwRowBits & 0x7) == 0 ? 0 : 1); // dwRowBits / 8 + (dwRowBits % 8 == 0 ? 0 : 1) dwRowBytes = dwRowBytes + ((4 - (dwRowBytes & 0x3)) & 0x3); // dwRowBytes + (4 - dwRowBytes % 4) % 4 buff = (BYTE*)malloc(dwRowBytes*biHeight*sizeof(BYTE)); CHECK_NULL_POINT(buff); LOG_DBG("ReadBmpData: alloc buff for pixel matrix success! "); LOG_DBG("ReadBmpData: Width|%d,RowBytes|%d,Height|%d,Size|%d ", biWidth, dwRowBytes, biHeight, dwRowBytes*biHeight); dRet = fread(buff, dwRowBytes, biHeight, pBmpFile); CHECK_NULL_RETURN(dRet); LOG_DBG("ReadBmpData: read pixel matrix success! dRet|%d ", dRet); biHandle->bPixelMatrix = (BYTE**)malloc(biHeight*sizeof(BYTE*)); CHECK_NULL_POINT(biHandle->bPixelMatrix); for(loop = 0; loop < biHeight; loop++) { biHandle->bPixelMatrix[loop] = &buff[loop*dwRowBytes]; } LOG_DBG("....end ReadBmpData.... "); return SUCCESS; } DWORD ReleaseBmpSpace(BitmapHandle *biHandle) { LOG_DBG("....start ReleaseBmpSpace.... "); CHECK_NULL_POINT(biHandle); if(biHandle->biInfo.rgbQuad != NULL) free(biHandle->biInfo.rgbQuad); if(biHandle->bPixelMatrix != NULL) { if(biHandle->bPixelMatrix[0] != NULL) free(biHandle->bPixelMatrix[0]); free(biHandle->bPixelMatrix); } // free(biHandle); LOG_DBG("....end ReleaseBmpSpace.... "); return SUCCESS; } DWORD LogBmpInfo(BitmapHandle *biHandle) { BitmapFileHeader *biFileHeader; BitmapInfo *biInfo; BitmapInfoHeader *biInfoHeader; RgbQuad * rgbQuad; CHECK_NULL_POINT(biHandle); biFileHeader = &biHandle->biFileHeader; biInfo = &biHandle->biInfo; biInfoHeader = &biInfo->biInfoHeader; rgbQuad = biInfo->rgbQuad; LOG_INF("BitmapFileHeader: Type|%x,Size|%d,Offset|%d ",biFileHeader->bfType, biFileHeader->bfSize, biFileHeader->bfOffBits); LOG_INF("BitmapInfoHeader: Size|%d,Width|%d,Height|%d,Planes|%d,BitCount|%d,Compression|%d ", biInfoHeader->biSize,biInfoHeader->biWidth,biInfoHeader->biHeight,biInfoHeader->biPlanes,biInfoHeader->biBitCount,biInfoHeader->biCompression); LOG_INF("BitmapInfoHeader: SizeImage|%d,XPelsPerM|%d,YPelsPerM|%d,ClrUsed|%d,ClrImportant|%d ", biInfoHeader->biSizeImage,biInfoHeader->biXPelsPerMeter,biInfoHeader->biYPelsPerMeter,biInfoHeader->biClrUsed,biInfoHeader->biClrImportant); LOG_INF("RgbQuad: %d ", (rgbQuad == NULL ? 0 : sizeof(rgbQuad)/sizeof(RgbQuad))); return SUCCESS; } int main(int argc, char *argv[]) { FILE *pBmpFile; BitmapHandle biHandle; /* printf("short:%d ", sizeof(short)); printf("long: %d ", sizeof(long)); printf("BitmapFileHeader:%d ", sizeof(BitmapFileHeader)); printf("BitmapInfoHeader:%d ", sizeof(BitmapInfoHeader)); printf("RgbQuad:%d ", sizeof(RgbQuad)); DWORD dwRowBits; DWORD dwRowBytes; dwRowBits = 8448; dwRowBytes = (dwRowBits & 0x7 == 0 ? 0 : 1) + (dwRowBits >> 3); printf("dwRowBytes:%d,%d ", ((dwRowBits & 0x7) == 0 ? 0 : 1), (dwRowBits >> 3)); system("pause"); */ // CHECK_FAIL_RETURN(2 == argc); // pBmpFile = fopen(argv[1], "rb"); pBmpFile = fopen("C:\Users\10207695\Documents\Visual Studio 2010\Projects\desp\Debug\01.bmp", "rb"); CHECK_NULL_POINT(pBmpFile); LOG_DBG("Main: open bitmap file success! "); ReadBmpInfo(pBmpFile, &biHandle); ReadBmpData(pBmpFile, &biHandle); fclose(pBmpFile); LogBmpInfo(&biHandle); system("pause"); ReleaseBmpSpace(&biHandle); return 0; }