BMP文件的格式:BMP文件在实际存储中包含以下的数据:
1.位图文件头 占用14个字节
- //文件信息
- unsigned short bfType;//文件类型,ASCII字符BM;
- //位图文件头
- typedef struct{
- unsigned long bfSize;//文件大小
- unsigned short bfReserved1;//备用
- unsigned short bfReserved2;//备用
- unsigned long bfOffBits;//图像开始处的字节偏移
- }BitMapFileHeader;
,本人在vs2013中没有学会如何设置结构体的对齐原则(用代码进行设置不行,#pragme pack(2),,,,#pragme pop),所以只好将那个数据提出位图信息头了.所以结构体占用了12个字节,bfType占用了2个字节
2.位图信息 位图信息包含两部分内容一个是位图信息头,另一个是调色板
位图信息头 占用40个字节
- //文图信息头
- typedef struct{
- unsigned long biSize;//信息头大小
- unsigned long biWidth;//图像宽度,以像素为单位
- unsigned long biHeight;//图像高度,以像素为单位
- unsigned short biPlanes;//位平面数,为1;
- unsigned short biBitCount;//每像素位数,1,4,8,24
- unsigned long biCompression;//压缩类型,0为非压缩
- unsigned long biSizeImage;//压缩图像大小
- unsigned long biXpelspermeter;//水平分辨率
- unsigned long biYpelspermeter;//垂直分辨率
- unsigned long biClrUsed;//使用的色彩数
- unsigned long biClrImportant;//重要色彩数
- }BitMapInforHeader;
- /调色板
- typedef struct
- {
- unsigned char rgbBlue; //该颜色的蓝色分量
- unsigned char rgbGreen; //该颜色的绿色分量
- unsigned char rgbRed; //该颜色的红色分量
- unsigned char rgbReserved; //保留值
- } RGBQuad;
3.像素数据,实际上就是0~255的数值,
- //像素数据
- unsigned char * * ImgData;//二维数组
这儿定义了一个二维数组来存储数据
4. 其他数据. 在实际的图像存储过程中会有以下其他数据
- //其他数据
- typedef struct OtherData
- {
- unsigned char extradata;
- struct OtherData *next;
- }OtherData;
这儿用一个链表来存储,但是有一个缺点就是在链表中只有一个有用的数据,所以结构体的利用率有点低,解决办法是在一个结构体数组中多设置几个数据项.
接下来是第二部分C语言来读取8位BMP灰度图
- int main()
- {
- FILE* fp;
- errno_t err;
- unsigned int j, k;
- BitMapFileHeader FileHeader;
- BitMapInforHeader InfoHeader;
- RGBQuad *IpRGBQuad;
- char FileName[30];
- OtherData *Otherdata, *temp,*SavePreCursor;
- /*图像的读取顺序是从下到上,从左到右*/
- IpRGBQuad = (RGBQuad *)malloc(256*sizeof(RGBQuad));//灰度图为8位的调色板数据为256个结构,1024个字节
- Otherdata = (OtherData*)malloc(sizeof(OtherData));
- SavePreCursor = Otherdata;//保存当前指针游标,目的就是保存链表头结点
- Otherdata->extradata = NULL;
- Otherdata->next = NULL;
- strcpy_s(FileName, "图像灰度.bmp");
- err = fopen_s(&fp,FileName, "rb");
- if( err!=0 )
- {
- printf_s("cannot open this file");
- return 0;
- }
- //拥有1024个调色板数据
- //printf("%d\n", sizeof(FileHeader));
- //fread(&FileHeader, sizeof(FileHeader), 1, fp);//读取位图文件头
- fread(&bfType, sizeof(unsigned short), 1, fp);//读取位图文件头
- if (bfType == 0x4D42)
- {
- printf_s("\n\n------------------------位图文件头----------------------------------------\n\n");
- fread(&FileHeader, sizeof(FileHeader), 1, fp);//读取位图文件头
- printf_s("文件类型%X\n",bfType);
- //printf_s("%X\n", FileHeader.bfType);
- printf_s("文件大小(单位字节):%X\n", FileHeader.bfSize);
- printf_s("备用:%X\n", FileHeader.bfReserved1);
- printf_s("备用:%X\n", FileHeader.bfReserved2);
- printf_s("图像开始处的字节偏移:%X\n", FileHeader.bfOffBits);
- //读取位图信息头
- printf_s("\n\n-------------------------位图信息头----------------------------------------\n\n");
- fread(&InfoHeader, sizeof(InfoHeader), 1, fp);
- printf_s("信息头大小:%X\n", InfoHeader.biSize);
- printf_s("图像宽度:%d\n", InfoHeader.biWidth);
- printf_s("图像高度:%d\n", InfoHeader.biHeight);
- printf_s("位平面数:%X\n", InfoHeader.biPlanes);
- printf_s("每像素位数:%X\n", InfoHeader.biBitCount);
- printf_s("压缩类型:%X\n", InfoHeader.biCompression);
- printf_s("压缩图像大小的字节数:%X\n", InfoHeader.biSizeImage);
- printf_s("水平分辨率:%X\n", InfoHeader.biXpelspermeter);
- printf_s("垂直分辨率:%X\n", InfoHeader.biYpelspermeter );
- printf_s("使用的色彩数:%X\n", InfoHeader.biClrUsed);
- printf_s("重要色彩数:%X\n", InfoHeader.biClrImportant);
- //读取调色板数据
- printf_s("\n\n-----------------------------调色板------------------------------------------\n\n");
- printf_s("\t红\t绿\t蓝\n");
- fread(IpRGBQuad, sizeof(RGBQuad), 256, fp);
- for (int i = 0; i < 256; i++)
- {
- printf("\t%X\t%X\t%X\n",IpRGBQuad[i].rgbBlue , IpRGBQuad[i].rgbGreen , IpRGBQuad[i].rgbRed );
- }
- //读取像素数据
- InfoHeader.biHeight++;
- InfoHeader.biWidth += 2;
- ImgData = new unsigned char *[InfoHeader.biHeight];
- for (j = 0; j < InfoHeader.biHeight; j++)
- {
- ImgData[j] = new unsigned char [InfoHeader.biWidth];//定义像素数组ImgData[InfoHeader.biHeight][InfoHeader.biWidth]
- }
- for ( j = 0; j < InfoHeader.biHeight; j++)
- {
- for ( k = 0; k < InfoHeader.biWidth; k++)
- {
- fread(&ImgData[j][k], sizeof(unsigned char), 1, fp);
- //
- }
- }
- //读取其他数据
- temp = (OtherData*)malloc(sizeof(OtherData));
- while (!feof(fp))
- {
- temp = (OtherData*)malloc(sizeof(OtherData));
- fread(&temp->extradata, sizeof(unsigned char), 1, fp);
- Otherdata->next = temp;
- Otherdata = Otherdata->next;
- }
- Otherdata->next = NULL;//置末尾为空,判断条件
- Otherdata = SavePreCursor;//使Otherdata重新指向头部
- }
- fclose(fp);
- system("pause");
- return 0;
- }