当前位置:网站首页>C语言读取BMP文件
C语言读取BMP文件
2022-07-06 09:14:00 【imxlw00】
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
边栏推荐
- Copie maître - esclave MySQL, séparation lecture - écriture
- Error connecting to MySQL database: 2059 - authentication plugin 'caching_ sha2_ The solution of 'password'
- Ansible practical Series II_ Getting started with Playbook
- A trip to Macao - > see the world from a non line city to Macao
- Test objects involved in safety test
- Punctual atom stm32f103zet6 download serial port pin
- Remember a company interview question: merge ordered arrays
- Swagger, Yapi interface management service_ SE
- Principes JDBC
- QT creator create button
猜你喜欢
一键提取pdf中的表格
MySQL主從複制、讀寫分離
Basic use of redis
Django运行报错:Error loading MySQLdb module解决方法
软件测试与质量学习笔记3--白盒测试
Postman uses scripts to modify the values of environment variables
QT creator create button
Deoldify项目问题——OMP:Error#15:Initializing libiomp5md.dll,but found libiomp5md.dll already initialized.
Use dapr to shorten software development cycle and improve production efficiency
How to build a new project for keil5mdk (with super detailed drawings)
随机推荐
Picture coloring project - deoldify
Solve the problem of installing failed building wheel for pilot
AI benchmark V5 ranking
AcWing 179.阶乘分解 题解
JDBC原理
Project practice - background employee information management (add, delete, modify, check, login and exit)
Deoldify项目问题——OMP:Error#15:Initializing libiomp5md.dll,but found libiomp5md.dll already initialized.
Codeforces Round #771 (Div. 2)
The virtual machine Ping is connected to the host, and the host Ping is not connected to the virtual machine
Classes in C #
[recommended by bloggers] background management system of SSM framework (with source code)
Tcp/ip protocol (UDP)
SSM整合笔记通俗易懂版
MySQL主从复制、读写分离
[recommended by bloggers] C WinForm regularly sends email (with source code)
Windows cannot start the MySQL service (located on the local computer) error 1067 the process terminated unexpectedly
How to build a new project for keil5mdk (with super detailed drawings)
Attention apply personal understanding to images
数数字游戏
一键提取pdf中的表格