BMP图的格式以及C语言读取8位灰度图

      BMP文件的格式:BMP文件在实际存储中包含以下的数据:

                  1.位图文件头 占用14个字节

//文件信息
unsigned short bfType;//文件类型,ASCII字符BM;

//位图文件头   
typedef struct{
	unsigned long bfSize;//文件大小
	unsigned short bfReserved1;//备用
	unsigned short bfReserved2;//备用
	unsigned long bfOffBits;//图像开始处的字节偏移
	
}BitMapFileHeader;
          本来 那个unsigned short bfType数据是在位图文件头之中的,在实际的编程中,需要考虑到结构的对齐原则,呵呵
,本人在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;
                                      接下来是调色板了,占用了的字节数是不确定的.2位灰度图占用8个字节,4为灰度图占用64个字节,8位灰度图占用1024个字节.算法如下:

/调色板
typedef struct
{
	unsigned char rgbBlue; //该颜色的蓝色分量  
	unsigned char rgbGreen; //该颜色的绿色分量  
	unsigned char rgbRed; //该颜色的红色分量  
	unsigned char rgbReserved; //保留值  
} RGBQuad;
在调色板数据结构中,有4个分量分别是红绿蓝和一个保留值,每个分量占用一个字节,8位灰度图实际上有0~255个数据,每个数据4个字节,所以是1024个字节.(白色是由三种颜色绘出来的)

                                  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;
}


  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是读取8位灰度像的bmp文件的C语言代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <stdint.h> #pragma pack(push, 1) // 禁用对齐 struct bmp_file_header { uint16_t magic_num; // 文件类型标识符 uint32_t size; // 文件大小 uint16_t reserved1; // 保留字段1 uint16_t reserved2; // 保留字段2 uint32_t offset; // 数据偏移量 }; struct bmp_info_header { uint32_t header_size; // 位信息头大小 int32_t width; // 像宽度 int32_t height; // 像高度 uint16_t planes; // 颜色平面数 uint16_t bit_depth; // 颜色位深度 uint32_t compression; // 压缩类型 uint32_t image_size; // 压缩像大小 int32_t x_resolution; // 水平分辨率 int32_t y_resolution; // 垂直分辨率 uint32_t color_palette; // 调色板颜色数 uint32_t important_colors; // 重要颜色数 }; #pragma pack(pop) // 恢复对齐 int main() { FILE *fp = fopen("example.bmp", "rb"); if (!fp) { perror("failed to open file"); exit(1); } // 读取文件头信息 struct bmp_file_header file_header; fread(&file_header, sizeof(file_header), 1, fp); // 读取信息头信息 struct bmp_info_header info_header; fread(&info_header, sizeof(info_header), 1, fp); // 确保是8位灰度像 if (info_header.bit_depth != 8) { fprintf(stderr, "Not an 8-bit grayscale image\n"); exit(1); } // 读取调色板信息 uint8_t palette[1024]; fread(palette, sizeof(palette), 1, fp); // 读取像素数据 uint8_t *data = malloc(info_header.image_size); fseek(fp, file_header.offset, SEEK_SET); fread(data, info_header.image_size, 1, fp); // 关闭文件 fclose(fp); // 显示像 // TODO: 使用第三方库或自行实现像显示 // 释放内存 free(data); return 0; } ``` 这段代码使用了C语言的文件读写API和结构体来解析bmp文件头、位信息头和调色板信息,然后使用`malloc()`函数动态分配内存并读取像素数据。如果需要显示像,可以使用第三方库或自行实现像显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值