1.BMP基本格式(仅24,32位)
BMP格式图像由文件头(BITMAPFILEHEADER)、信息头(BITMAPINFOHEADER)和像素数据(RGB)构成,在文件中依次存放,读/写 BMP文件时也依次操作即可。其中在windows系统下,“windows.h”中已包含此三种结构体。
2.BMP读取代码:
//BMP文件格式固定,读取方式大同小异,读取BMP部分是我直接从不知道哪个哥们的博客COPY的,后面加了转正图片和写入AVFrame
//如果中途要转换YUV420,就不要在这里转正了,网上有个高效的YUV420转正的代码,我这个有点慢
//另外,由于要用FFMPEG操作,内存分配也用的FFMPEG的,可以直接换了
//不要在这里把bmpBuffer释放,但是用完AVFrame数据后,不止要释放AVFrame,还要释放AVFrame->data[0]
AVFrame* readBmp2FrameMap(const char*bmpPath,int num)
{
//二进制读方式打开指定的图像文件
FILE *fp=fopen(bmpPath,"rb");
if(fp==0) return 0;
//跳过位图文件头结构BITMAPFILEHEADER
fseek(fp, sizeof(BITMAPFILEHEADER),0);
//定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
BITMAPINFOHEADER head;
fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
//获取图像宽、高、每像素所占位数等信息
int biWidth = head.biWidth;
int biHeight = head.biHeight;
int biBitCount = head.biBitCount;
//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
int lineByte=(biWidth * biBitCount/8+3)/4*4;
//位图深度
if(biBitCount != 24 && biBitCount != 32)
{
printf("bmp file: %s is not 24 or 32 bit\n ", bmpPath);
return 0;
}
//申请位图数据所需要的空间,读位图数据进内存
uint8_t* bmpBuffer = (uint8_t* )av_malloc(lineByte* biHeight);
QTime time_;
time_.start();
fread(bmpBuffer,1,lineByte * biHeight,fp);
//关闭文件
fclose(fp);
std::cout<<"read time: "<<time_.elapsed()<<"\n";
//倒置(转正)
uint8_t* tempData = (uint8_t*)av_malloc(lineByte*biHeight);
for(int h=0; h<biHeight; h++)
{
memcpy(tempData+(biHeight-1-h)*lineByte, bmpBuffer+(h*lineByte), lineByte);
}
memcpy(bmpBuffer,tempData,lineByte*biHeight);
av_free(tempData);
//
AVFrame* rgbFrame = av_frame_alloc();
AVPixelFormat pixFmt ;
if(biBitCount == 24)
pixFmt = AV_PIX_FMT_RGB24;
else if(biBitCount == 32)
pixFmt = AV_PIX_FMT_RGB32;
avpicture_fill((AVPicture *)rgbFrame, bmpBuffer,pixFmt, biWidth, biHeight);
rgbFrame->width = biWidth;
rgbFrame->height = biHeight;
rgbFrame->linesize[0] = lineByte;
rgbFrame->format = pixFmt;
return rgbFrame;
}