FFMPEG開發中的常用功能代碼①BMP文件的讀取、轉正並寫入AVFrame的data

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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章