IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言读取BMP文件 -> 正文阅读

[C++知识库]C语言读取BMP文件

BMP图像编码

BMP即bitmap,也就是位图,一般由4部分组成:文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区。

在图像数据之前,如图所示,共有54位数据
在这里插入图片描述
其中,0x424d在十进制为19778,对应的ASCII码为BM,表示这是个bitmap文件。

Windows的数据是倒着念的,这是PC电脑的特色。如果一段数据为42 4D,倒着念就是4D 42,即0x4D42。
因此,如果bfSize的数据为A2 1E 04 00,实际上就成了0x00041EA2,也就是0x41EA2。

文件信息头[14字节]

存储着文件类型,文件大小等信息

// 文件信息头结构体
typedef struct tagBITMAPFILEHEADER{
    unsigned short bfType;        //必为"BM"
    unsigned int   bfSize;        //文件字节数(2-5)
    unsigned int bfReserved;    //位图文件保留字,必为0(6-9)
    unsigned int   bfOffBits;   //像素数据偏移 (10-13)
} bmpHeader;

图像描述信息[40字节]

#define uint unsigned int
#define ushort unsigned short
//图像信息头结构体
typedef struct tagBITMAPINFOHEADER{
    uint    biSize;          // 结构体尺寸 (14-17)
    int     biWidth;         // 图像宽度  (18-21)
    int     biHeight;        // 图像高度  (22-25)
    ushort  biPlanes;        // 目标设备的级别,为1(26-27)
    ushort  biBitCount;      // 像素位数,为1、4、8或24(28-29)
    uint    biCompression;   // 位图压缩类型,0为不压缩、1为BI_RLE8、2为BI_RLE4(30-33)
    uint    biSizeImage;     // 单像素数据大小,等于bfSize-bfOffBits (34-37)
    int     biXPelsPerMeter; // 水平分辨率,一般为0 (38-41)
    int     biYPelsPerMeter; // 垂直分辨率,一般为0 (42-45)
    uint    biClrUsed;       // 位图颜色表中的颜色数,0表示使用所有调色板项(46-49)
    uint    biClrImportant;  // 重要颜色索引的数目,0表示都重要(50-53)
} infoHeader;

像素信息结构体

typedef struct _PixelInfo {
	unsigned char rgbBlue;   //蓝色分量  (0-255)
	unsigned char rgbGreen;  //绿色分量  (0-255)
	unsigned char rgbRed;    //红色分量  (0-255)
	//unsigned char rgbReserved;// 保留,必须为0
} PixelInfo;

vs 2019 设置结构体对齐规则

在这里插入图片描述

示例图片

请添加图片描述

读取图像

int main()
{
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;
	PixelInfo pixel;

	FILE* fp;
	fp = fopen("images/123456.bmp", "rb");
	//fp = fopen("images/b44.bmp", "rb");

	fread(&fileHeader, sizeof(fileHeader), 1, fp);
	fread(&infoHeader, sizeof(infoHeader), 1, fp);
	if (fileHeader.bfType != 19778)
	{
		printf("%s", "err");

	}
	printf("%d\n", fileHeader.bfType);
	printf("%d\n", fileHeader.bfSize);
	unsigned char b;
	unsigned char g;
	unsigned char r;
	unsigned char gray;
	int x, y, count = 0;
	int w = infoHeader.biWidth;
	int	h = infoHeader.biHeight;
	char info[] = "* ";
	int len = w * h + h + 1;
	char* out = (char*)malloc(len * sizeof(char));
	for (y = 0; y < h; y++)
	{
		for (x = 0; x < w; x++)
		{
			
			fread(&pixel, sizeof(pixel), 1, fp);
			//printf("%d, %d , %d \n", pixel.rgbRed, pixel.rgbGreen, pixel.rgbBlue);
			b = pixel.rgbBlue;
			g = pixel.rgbGreen;
			r = pixel.rgbRed;
			gray = (int)(r * 0.299 + g * 0.587 + b * 0.114);
			out[count++] = info[gray * strlen(info) / 256];
		}
		out[count++] = '\n';
	}
	out[count] = '\0';

	printf("%s\n", out);

	printf("helloWorld\n");
	return 0;
}

在这里插入图片描述
由于坐标系不同,需要修改读取像素顺序

int main3()
{
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;
	PixelInfo pixel;

	FILE* fp;
	fp = fopen("images/123456.bmp", "rb");
	//fp = fopen("images/b44.bmp", "rb");

	fread(&fileHeader, sizeof(fileHeader), 1, fp);
	fread(&infoHeader, sizeof(infoHeader), 1, fp);
	if (fileHeader.bfType != 19778)
	{
		printf("%s", "err");

	}
	printf("%d\n", fileHeader.bfType);
	printf("%d\n", fileHeader.bfSize);
	unsigned char b;
	unsigned char g;
	unsigned char r;
	unsigned char gray;
	int x, y,count=0;
	int w = infoHeader.biWidth;
	int	h = infoHeader.biHeight;

	char info[] = "* ";
	int len = w * h + h+1;
	char* out = (char*)malloc(len * sizeof(char));

	for (y = h - 1; y >= 0; y--)
	{
		count = (w + 1) * y;
		for (x = 0; x < w; x++)
		{

			fread(&pixel, sizeof(pixel), 1, fp);
			b = pixel.rgbBlue;
			g = pixel.rgbGreen;
			r = pixel.rgbRed;
			gray = (int)(r * 0.299 + g * 0.587 + b * 0.114);
			out[count++] = info[gray * strlen(info) / 256];
		}
		
		out[count++] = '\n';
	}
	out[len-1] = '\0';


	printf("%s\n", out);

	printf("helloWorld\n");
	return 0;
}

在这里插入图片描述

图像变形

Windows规定一个扫描行所占的字节数必须是 4的倍数(即以long为单位),不足的以0填充。

一个扫描行所占的字节数计算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/44; // 字节数必须是4的倍数
位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine
biHeight;


int main()
{
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;
	PixelInfo pixel;

	FILE* fp;
	fp = fopen("images/123456.bmp", "rb");
	//fp = fopen("images/b44.bmp", "rb");

	fread(&fileHeader, sizeof(fileHeader), 1, fp);
	fread(&infoHeader, sizeof(infoHeader), 1, fp);
	if (fileHeader.bfType != 19778)
	{
		printf("%s", "err");

	}
	printf("%d\n", fileHeader.bfType);
	printf("%d\n", fileHeader.bfSize);
	unsigned char b;
	unsigned char g;
	unsigned char r;
	unsigned char gray;
	int x, y,count=0;
	int w = infoHeader.biWidth;
	int	h = infoHeader.biHeight;
	int DataSizePerLine = (w * infoHeader.biBitCount + 31) / 8 / 4 * 4;   //   字节数必须是4的倍数 
	char info[] = "* ";
	int len = w * h + h+1;
	char* out = (char*)malloc(len * sizeof(char));
	for (y = h - 1; y >= 0; y--)
	{
		count = (w + 1) * y;
		for (x = 0; x < w; x++)
		{

			fread(&pixel, sizeof(pixel), 1, fp);
			b = pixel.rgbBlue;
			g = pixel.rgbGreen;
			r = pixel.rgbRed;
			gray = (int)(r * 0.299 + g * 0.587 + b * 0.114);
			out[count++] = info[gray * strlen(info) / 256];
		}
		if (w % 4 != 0)
		{
			fseek(fp, DataSizePerLine - 3 * w,SEEK_CUR);
		}
		out[count++] = '\n';
	}
	out[len-1] = '\0';


	printf("%s\n", out);

	printf("helloWorld\n");
	return 0;
}

参考链接 https://blog.csdn.net/qq_39400113/article/details/104750460
参考大牛视频 https://www.bilibili.com/video/BV1n5411N7T4?spm_id_from=333.999.0.0

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-01 15:00:47  更:2022-06-01 15:01:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 4:03:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码