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;
}