根据工作要求,得到视频数据。那么怎么证明视频数据是对的?转为BMP最简单了。这样一个想法,折腾了吾很久,找到了快10种代码,结果都不能用。后来终于找到了一个可用的(代码是部分的),看到保存出来的BMP图片,终于松了一口气。
想直接用的朋友,去这里:github.com/quantum6/Rg…
个人发现关键地方有:
文件头。
文件头的对齐。
每行数据的对齐。
取之于网络,用之于网络,吾将代码公布出来:
1、这里处理的是ARGB,如果是RGB,注意差异。
2、宽度最好是32的倍数。如果不是,注意bytesPerLine对数据区的越界影响。
主代码
看着这么整齐的代码,是不是赏心悦目?这么好的做法,阁下应该学习使用。
#include <stdlib.h>
#include <string.h>
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef int LONG;
#define BITS_PER_PIXCEL 24
#define FORMAT_RGBA 4
#define FORMAT_RGB 3
/** must needed. pack */
#pragma pack(1)
typedef struct
{
WORD bfType;
DWORD bfSize;
WORD bfReserved1;
WORD bfReserved2;
DWORD bfOffBits;
} BMP_FILE_HEADER;
typedef struct{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BMP_INFO_HEADER;
#pragma pack()
int rgbaToBmpFile(const char *pFileName, const char* pRgbaData, const int nWidth, const int nHeight, const int format)
{
BMP_FILE_HEADER bmpHeader;
BMP_INFO_HEADER bmpInfo;
FILE* fp = NULL;
char* pBmpSource = NULL;
char* pBmpData = NULL;
int i = 0, j=0;
//4 bytes pack. must be 4 times per line。
int bytesPerLine = (nWidth*BITS_PER_PIXCEL+31)/32*4;
int pixcelBytes = bytesPerLine*nHeight;
bmpHeader.bfType = 0x4D42;
bmpHeader.bfReserved1 = 0;
bmpHeader.bfReserved2 = 0;
bmpHeader.bfOffBits = sizeof(BMP_FILE_HEADER) + sizeof(BMP_INFO_HEADER);
bmpHeader.bfSize = bmpHeader.bfOffBits + pixcelBytes;
bmpInfo.biSize = sizeof(BMP_INFO_HEADER);
bmpInfo.biWidth = nWidth;
/** 这样图片才不会倒置 */
bmpInfo.biHeight = -nHeight;
bmpInfo.biPlanes = 1;
bmpInfo.biBitCount = BITS_PER_PIXCEL;
bmpInfo.biCompression = 0;
bmpInfo.biSizeImage = pixcelBytes;
bmpInfo.biXPelsPerMeter = 100;
bmpInfo.biYPelsPerMeter = 100;
bmpInfo.biClrUsed = 0;
bmpInfo.biClrImportant = 0;
/** convert in memort, then write to file. */
pBmpSource = (char*)malloc(pixcelBytes);
if (!pBmpSource)
{
return -1;
}
/** open file */
fp = fopen(pFileName,"wb+");
if (!fp)
{
return -1;
}
fwrite(&bmpHeader, sizeof(BMP_FILE_HEADER), 1, fp);
fwrite(&bmpInfo, sizeof(BMP_INFO_HEADER), 1, fp);
/** Here you should consider color format. RGBA ? RGB? BGR?
Param format is RGBA, format for file is BGR */
pBmpData = pBmpSource;
for (i=0; i<nHeight; i++)
{
for (j=0; j<nWidth; j++)
{
pBmpData[0] = pRgbaData[2];
pBmpData[1] = pRgbaData[1];
pBmpData[2] = pRgbaData[0];
pRgbaData += format;
pBmpData += FORMAT_RGB;
}
//pack for 4 bytes
pBmpData +=(bytesPerLine - nWidth*FORMAT_RGB);
}
fwrite(pBmpSource, pixcelBytes, 1, fp);
/** close and release。 */
fclose(fp);
free(pBmpSource);
return 0;
}
复制代码
剪裁
const int nWidth, const int nHeight, const int format,
const int nClipLeft, const int nClipTop, const int nClipWidth, const int nClipHeight)
{
char* pClipSource = NULL;
char* pClipData = NULL;
int pixcelBytes = nClipWidth*nClipHeight*format;
int i = 0;
pClipSource = (char*)malloc(pixcelBytes);
if (!pClipSource)
{
return -1;
}
//move to right position
pRgbaData += nClipTop * nWidth * format;
pRgbaData += nClipLeft * format;
pClipData = pClipSource;
for (i=0; i<nClipHeight; i++)
{
memcpy(pClipData, pRgbaData, nClipWidth*format);
pRgbaData += nWidth * format;
pClipData += nClipWidth* format;
}
rgbaToBmpFile(pFileName, pClipSource, nClipWidth, nClipHeight, format);
//release
free(pClipSource);
return 0;
}
复制代码
调用范例
此文貌似是网上第一个正确产生BMP的代码。很多人搜索到了之后,说是不知道怎么用。本来吾以为这是很简单的事情。从评论中看到有的朋友对编程都不是太了解,于是,吾决定加个调用范例。
以下代码通过测试,可以产生红色BMP图片。各位修改宽高颜色等。
{
int width = 640;
int height = 360;
int format = FORMAT_RGB;
char colorR = 0xFF;
char colorG = 0x00;
char colorB = 0x00;
int size=width*height*format;
char* pRgb=(char*)malloc(size);
for (int i=0; i<width*height; i++)
{
pRgb[i*format] = colorR;
pRgb[i*format+1] = colorG;
pRgb[i*format+2] = colorB;
}
rgbaToBmpFile((char*)"test.bmp", pRgb, width, height, format);
free(pRgb);
}
复制代码
编译
rgb2bmp.cpp \
-o rgb2bmp
复制代码
祝愿大家身体健康,工作顺利。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END