您的位置:首页 > 编程语言

FFmpeg转YUV420数据为BGR24后存bmp图片(代码片段)

2018-03-13 19:13 323 查看
SwsContext *_imgContext = nullptr;
std::vector<uint8_t> _pictureBuffer;
AVFrame _picture = {0};
int linesize[3] = {0};
int _trueWidth;
int _trueHeight;

typedef struct                       /**** BMP file header structure ****/
{
unsigned int bfSize;           /* Size of file */
unsigned short bfReserved1;      /* Reserved */
unsigned short bfReserved2;      /* ... */
unsigned int bfOffBits;        /* Offset to bitmap data */
} BITMAPFILEHEADER;

typedef struct                       /**** BMP file info structure ****/
{
unsigned int biSize;           /* Size of info header */
int biWidth;          /* Width of image */
int biHeight;         /* Height of image */
unsigned short biPlanes;         /* Number of color planes */
unsigned short biBitCount;       /* Number of bits per pixel */
unsigned int biCompression;    /* Type of compression to use */
unsigned int biSizeImage;      /* Size of image data */
int biXPelsPerMeter;  /* X pixels per meter */
int biYPelsPerMeter;  /* Y pixels per meter */
unsigned int biClrUsed;        /* Number of colors used */
unsigned int biClrImportant;   /* Number of important colors */
} BITMAPINFOHEADER;

typedef struct {
unsigned char rgbBlue;//蓝色的亮度(值范围为0-255)
unsigned char rgbGreen;//绿色的亮度(值范围为0-255)
unsigned char rgbRed;//红色的亮度(值范围为0-255)
unsigned char rgbReserved;//保留,必须为0
} RGBQUAD;

/**
* 保存一帧YUV420P数据为bmp图片
* @param filename
* @param data
* @param width
* @param height
* @return
*/
int saveBmpToFile(const char *filename, uint8_t **data, int width, int height) {
linesize[0] = static_cast<int>(width / 16) % 2 != 0 ? width + 16 : width;
linesize[1] = linesize[0] / 2;
linesize[2] = linesize[0] / 2;
_trueWidth = width;
_trueHeight = height;

if (_imgContext) {
sws_freeContext(_imgContext);
_imgContext = nullptr;
}

CHECK_LOG_RETURN_COMMON(_imgContext)

_pictureBuffer.resize(
static_cast<size_t>(av_image_get_buffer_size(AV_PIX_FMT_RGB24, _trueWidth, _trueHeight,
1)));
av_image_fill_arrays(_picture.data, _picture.linesize, _pictureBuffer.data(), AV_PIX_FMT_RGB24,
_trueWidth, _trueHeight, 1);

_imgContext = sws_getContext(width, height, AV_PIX_FMT_YUV420P, width, height,
AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

sws_scale(_imgContext, data, linesize, 0, height, _picture.data, _picture.linesize);
width = _trueWidth;
height = _trueHeight;

BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
/* Magic number for file. It does not fit in the header structure due to alignment requirements, so put it outside */
unsigned short bfType = 0x4d42;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfSize = 2 + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + width * height * 3;
bfh.bfOffBits = 0x36;

bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = width;
bih.biHeight = -height; //上下翻转
bih.biPlanes = 1;
bih.biBitCount = 24;
bih.biCompression = 0;
bih.biSizeImage = 0;
bih.biXPelsPerMeter = 5000;
bih.biYPelsPerMeter = 5000;
bih.biClrUsed = 0;
bih.biClrImportant = 0;

int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0777);
if (-1 == fd) {
return -1;
}
write(fd, &bfType, sizeof(bfType));
write(fd, &bfh, sizeof(bfh));
write(fd, &bih, sizeof(bih));
write(fd, _pictureBuffer.data(), (size_t)width * height * 3);
close(fd);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: