当我们要将RGB24格式保存为bmp图片格式时,根据bmp图片格式需要在图片数据之前添加两个结构体
分别为 BITMAPFILEHEADER、BITMAPINFOHEADER
BITMAPFILEHEADER bmpFileHeader = {0};
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfType = 0x4D42;
bmpFileHeader.bfSize = sizeof(bmpFileHeader) + sizeof(BITMAPINFOHEADER) + pic.linesize[0] * frame->height;
bmpFileHeader.bfOffBits = sizeof(bmpFileHeader) + sizeof(BITMAPINFOHEADER);
BITMAPINFOHEADER bmiHeader = { 0 };
bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth = frame->width;
bmiHeader.biHeight = 0 - frame->height;
bmiHeader.biPlanes = 1;
// bmp图片位深
bmiHeader.biBitCount = 24;
bmiHeader.biCompression = BI_RGB;
// 像素点数目
bmiHeader.biSizeImage = pic.linesize[0] * frame->height;
bmiHeader.biXPelsPerMeter = 0;
bmiHeader.biYPelsPerMeter = 0;
bmiHeader.biClrUsed = 0;
bmiHeader.biClrImportant = 0;
fwrite( &bmpFileHeader, 1, sizeof(bmpFileHeader), pf );
fwrite( &bmiHeader, 1, sizeof(bmiHeader), pf );
fwrite( pic.data[0], 1, pic.linesize[0] * frame->height, pf );
fclose( pf );
int AVFrame_create_bmp(AVFrame *pAVFrame,int width,int height,int bpp = 24)
{
//{
struct SwsContext *img_convert_ctx;
AVFrame *pFrameRGB;
pFrameRGB=avcodec_alloc_frame();
if(pFrameRGB==NULL)return 0 ;
int numBytes = avpicture_get_size(PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height);
uint8_t * buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
avpicture_fill((AVPicture *)pFrameRGB, buffer, /*PIX_FMT_RGB24*/PIX_FMT_BGR24,m_pCodecCtx->width, m_pCodecCtx->height);
img_convert_ctx = sws_getContext(
m_pCodecCtx->width,
m_pCodecCtx->height,
m_pCodecCtx->pix_fmt,
m_pCodecCtx->width,
m_pCodecCtx->height,
/*PIX_FMT_RGB24*/PIX_FMT_BGR24,//PIX_FMT_YUV420P,
SWS_BICUBIC, NULL, NULL, NULL);
sws_scale (img_convert_ctx, pAVFrame->data, pAVFrame->linesize,
0, m_pCodecCtx->height,
((AVPicture *)pFrameRGB)->data, ((AVPicture *)pFrameRGB)->linesize );
sws_freeContext(img_convert_ctx);
av_free(buffer);
//}
DWORD w = m_pCodecCtx->width;
DWORD h = m_pCodecCtx->height;
DWORD BufferLen = WIDTHBYTES(w*24)*h; //当然,如果仔细考虑,还要考虑位图字节对齐;
BYTE * pBuffer = new BYTE[BufferLen];
memset(pBuffer,0,BufferLen);
for(int i =0; idata[0]+i*pFrameRGB->linesize[0],width*3);
}
LPBYTE pbmp = new BYTE[sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+BufferLen];
BITMAPFILEHEADER bitmapfileheader; memset( &bitmapfileheader, 0, sizeof( BITMAPFILEHEADER ) );
bitmapfileheader.bfType = 'MB';
bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+BufferLen ;
bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
memcpy(pbmp,&bitmapfileheader,sizeof(BITMAPFILEHEADER));
BITMAPINFOHEADER fmtFrame; memset(&fmtFrame, 0, sizeof(fmtFrame));
fmtFrame.biSize = sizeof(fmtFrame);
fmtFrame.biPlanes = 1;
fmtFrame.biBitCount = 24;
fmtFrame.biWidth = w;
fmtFrame.biHeight = -h;//注意,这里的bmpinfo.bmiHeader.biHeight变量的正负决定bmp文件的存储方式,如果为负值,表示像素是倒过来的*/
fmtFrame.biSizeImage = BufferLen;
memcpy(pbmp+sizeof(BITMAPFILEHEADER),&fmtFrame,sizeof(BITMAPINFOHEADER));
memcpy(pbmp+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER),pBuffer, BufferLen);
FILE * f = fopen("frame.bmp","w+b");
fwrite(pbmp,1,sizeof(BITMAPFILEHEADER)+sizeof(fmtFrame)+BufferLen, f );
fclose(f) ;
delete [] pbmp; pbmp = NULL;
delete [] pBuffer; pBuffer = NULL;
}