AVDataProcess/rgb24_to_bmp.cpp

100 lines
4.2 KiB
C++
Raw Normal View History

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int BOOL;
#define TRUE 1
#define FALSE 0
//位图文件头结构体
//这个结构体的长度是固定的14个字节。
//考虑到结构体的字节对齐将bfType单独提取出来否则会造成该结构体为16个字节。
static unsigned short bfType = 0x4D42;//指定文件类型必须是0x424D
//即字符串“BM”也就是说所有.bmp文件的头两个字节都是“BM”。
//'BM'表示这是Windows支持的位图格式。
typedef struct {
unsigned int bfSize; //指定文件大小以字节为单位包括这14个字节。
unsigned short bfReserved1; //为保留字,不用考虑
unsigned short bfReserved2; //为保留字,不用考虑
unsigned int bfOffBits; //位图文件头到数据的偏移量,以字节为单位
}BmpHead;
//位图信息头结构体
typedef struct {
unsigned int biSize; //该结构大小字节为单位一般为40个字节
unsigned int biWidth; //指定图象的宽度,单位是象素。
unsigned int biHeight; //指定图象的高度,单位是象素。
//注:这个值除了用于描述图像的高度之外,它还有另一个用处,
//就是指明该图像是倒向的位图,还是正向的位图。
//如果该值是一个正数,说明图像是倒向的,如果该值是个负数,则说明图像是正向的。
//大多数的BMP文件都是倒向的位图也就是高度值是一个正数。
unsigned short biPlanes; //为目标设备说明颜色平面数必须为1不用考虑
unsigned short biBitCount; //颜色深度,每个象素所需要的位数
unsigned int biCompression; //位图的压缩类型
unsigned int biSizeImage; //位图的大小,以字节为单位
unsigned int biXPelsPerMeter; //位图水平分辨率,每米像素数
unsigned int biYPelsPerMeter; //位图垂直分辨率,每米像素数
unsigned int biClrUsed; //位图实际使用的颜色表中的颜色数
unsigned int biClrImportant; //位图显示过程中重要的颜色数
}InfoHead;
BOOL rgb24_to_bmp(const char *file, int width, int height)
{
if (file == NULL) {
return FALSE;
}
FILE *fpRgb24 = fopen(file, "rb");
FILE *fpBmp = fopen("./out/output_rgb24_to_bmp.bmp", "wb");
//从文件中读取RGB数据
unsigned char *rgb24Buf = (unsigned char *)malloc(width*height*3);
memset(rgb24Buf, 0, width*height*3);
fread(rgb24Buf, 1, width*height*3, fpRgb24);
int headSize = sizeof(BmpHead) + sizeof(InfoHead) + sizeof(bfType);
BmpHead bmpHead = {0};
InfoHead bmpInfoHead = {0};
bmpHead.bfSize = width*height*3 + headSize;
bmpHead.bfOffBits = headSize;
bmpInfoHead.biSize = sizeof(InfoHead);
bmpInfoHead.biWidth = width;
bmpInfoHead.biHeight = -height;//BMP存储像素数据在Y轴方向从下到上。
bmpInfoHead.biPlanes = 1;
bmpInfoHead.biBitCount = 24;
bmpInfoHead.biSizeImage = width*height*3;
fwrite(&bfType, 1, sizeof(bfType), fpBmp);
fwrite(&bmpHead, 1, sizeof(bmpHead), fpBmp);
fwrite(&bmpInfoHead, 1, sizeof(bmpInfoHead), fpBmp);
//BMP采用的是小端Little Endian存储方式。
//这种存储方式中“RGB24”格式的像素的分量存储的先后顺序为B、G、R。
//由于RGB24格式存储的顺序是R、G、B所以需要将“R”和“B”顺序作一个调换再进行存储。
for (int i=0; i<height; i++) {
for (int j=0; j<width; j++) {
unsigned char tmp = rgb24Buf[(i*width+j)*3+2];
rgb24Buf[(i*width+j)*3+2] = rgb24Buf[(i*width+j)*3+0];
rgb24Buf[(i*width+j)*3+0] = tmp;
}
}
fwrite(rgb24Buf, width*height*3, 1, fpBmp);
free(rgb24Buf);
fclose(fpBmp);
fclose(fpRgb24);
return TRUE;
}
int main(int argc, char *argv[])
{
if (argc == 4) {
rgb24_to_bmp(argv[1], atoi(argv[2]), atoi(argv[3]));
}
return 0;
}