BMP无压缩封装为AVI视频

    因为组内测试序列制作需要,需要将制作好的BMP位图,无压缩封装为AVI视频,并附有多种要求(基准和实验序列交替出现、随机组合等)。因此,需要实现BMP到AVI的无压缩封装。

    由于整个测试序列集有大概几千张图片,需要统一的命令规范。因此,无论是采用命令行还是批处理,都还是不够简洁。

    早期,针对这个封装需求,尝试使用的是ffmpeg,无压缩封装。整个过程虽然较为简单,但是却出了一些BUG。

    1.FFmpeg识别RGB24格式为BGR24,且处理时由于与标准RGB的存储不一致,会导致图像颠倒。

    2.将BMP封装为AVI,原图像素会产生位移。

    以下为我使用ffmpeg产生    基准——空白——试验    测试序列的批处理文件。(其中list.txt为拼接视频列表)

ffmpeg.exe -i 100.bmp -r 1 -c:v copy 1.avi
ffmpeg.exe -i 100.bmp -r 1 -c:v copy 2.avi
ffmpeg.exe -i 100.bmp -r 1 -c:v copy 3.avi
ffmpeg.exe -i 100.bmp -r 1 -c:v copy 4.avi
ffmpeg.exe -i 100.bmp -r 1 -c:v copy 5.avi
ffmpeg.exe -i gray.bmp -r 1 -c:v copy 6.avi
ffmpeg.exe -i 50.bmp -r 1 -c:v copy 7.avi
ffmpeg.exe -i 50.bmp -r 1 -c:v copy 8.avi
ffmpeg.exe -i 50.bmp -r 1 -c:v copy 9.avi
ffmpeg.exe -i 50.bmp -r 1 -c:v copy 10.avi
ffmpeg.exe -i 50.bmp -r 1 -c:v copy 11.avi
ffmpeg.exe -f concat -i list.txt -c copy output.avi
pause

直接使用ffmpeg处理的BMP图片如上。

由于是主观图像质量评价测试,因此图片不能有二次转码、压缩、额外处理操作。

此时,参考了许多解决办法。由于需要处理海量图片、命名格式又不一致,因此还是决定自己写个程序解决。

直接上代码好了……

1.简单实用了MFC框架,遍历文件夹

2.实用AVI服务,直接封装BMP图片

3.根据需要设置了1帧/秒和十张图片组成一个AVI视频的写入方法

// RandomAviOutput.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <afx.h>
#include <atlimage.h>
#include "Vfw.h"
#include  <direct.h>  
#include  <stdio.h> 
#include <string>
//#include "afx.h"

void ImageToAVI(CString AviPath, CString ImgPath);
void CreateAVI(CImage img, CString name, int videoWidth, int videoHeight, int bpp);
//argv[1]=输入BMP文件夹,argv[2]=输出文件名
int main(int argc, char *argv[])
{
	printf("input BMP DirPath %s\n", argv[1]);
	printf("output AVI Path %s\n", argv[2]);
	if (argc < 2)
	{
		printf("check input argv\n");
		return 0;
	}
	char rootpath[MAX_PATH];
	_getcwd(rootpath, MAX_PATH);
	CString path = rootpath;
	CString input,output;
	if (argc = 3)
	{
		input = argv[1];
		output = argv[2];
	}
	else
	{
		input = rootpath;
		output = rootpath;
	}

	ImageToAVI(output, input);
	printf("BMP to AVI All Done! \n");
	return 0;
}
//======================================================================================
//
// 功能 : 将目录中的BMP图像无压缩封装为AVI视频
//
//======================================================================================
void ImageToAVI(CString AviPath, CString ImgPath)
{
	// 初始化AVI 库
	AVIFileInit();

	CFileFind finder;
	CString ImgDir=ImgPath+"\\*.bmp";
	BOOL bFind = finder.FindFile(ImgDir);
	//遍历文件夹路径中所有的*.bmp文件
	while (bFind)
	{
		bFind = finder.FindNextFile();
		if (!finder.IsDots() && !finder.IsDirectory())//若不为空且非文件夹
		{
			// 获取图像文件绝对路径
			CString str = finder.GetFilePath();
			CString title = finder.GetFileTitle();
			CString name = AviPath + "\\"+title+".avi";
			//拷贝bmp图片文件名作为生成avi文件名
			//
			// Open Image and get image info & data
			//使用CImage读取图片信息
			CImage img;		
			if (FAILED(img.Load(str)))
			{
				TRACE("Warning : fail to load file %s!!!\n", str);
				continue;
			}
			int w, h,bpp;
			w = img.GetWidth();
			h = img.GetHeight();
			bpp = img.GetBPP();
			//img.Destroy();
			//释放CImage,使用FILE读写图片数据
			//std::string s = CT2A(str.GetBuffer(0));
			//FILE *fp;
			//fopen_s(&fp,s.c_str(), "rb");
			CreateAVI(img,name,w,h,bpp);//创建avi视频函数
			printf("BMP to AVI Done and Go Next! \n");
			
		}
	}

	AVIFileExit();

}
void CreateAVI(CImage img,CString name, int videoWidth, int videoHeight, int bpp)
{
	//
	// Create AVI file
	//
	PAVIFILE pAviFile = NULL;
	HRESULT hr = AVIFileOpen(&pAviFile, name, OF_WRITE | OF_CREATE, NULL);
	if (0 != hr)
	{
		return;
	}

	//
	// Create AVI video stream
	//
	AVISTREAMINFO strhdr;
	memset(&strhdr, 0, sizeof(strhdr));

	strhdr.fccType = streamtypeVIDEO;
	strhdr.fccHandler = mmioFOURCC('X', 'V', 'I', 'D');
	strhdr.dwScale = 1;
	strhdr.dwRate = 0.1;
	//设置帧速 1秒/帧

	UINT pitch = (videoWidth * bpp + 31) / 32 * 4;
	UINT biSizeImage = (videoWidth * bpp + 31) / 32 * 4 * videoHeight;
	strhdr.dwSuggestedBufferSize = biSizeImage;

	SetRect(&strhdr.rcFrame, 0, 0, videoWidth, videoHeight);

	// And create the stream;
	PAVISTREAM pAviStream = NULL;
	hr = AVIFileCreateStream(pAviFile, &pAviStream, &strhdr);
	if (0 != hr)
	{
		AVIFileRelease(pAviFile);
		pAviFile = NULL;
		return;
	}

	//
	// Set stream format
	//
	BITMAPINFOHEADER bih;
	memset(&bih, 0, sizeof(BITMAPINFOHEADER));

	bih.biBitCount = bpp;
	bih.biClrImportant = 0;
	bih.biClrUsed = 0;
	bih.biCompression = BI_RGB;
	bih.biPlanes = 1;
	bih.biSize = 40;
	bih.biXPelsPerMeter = 0;
	bih.biYPelsPerMeter = 0;
	bih.biWidth = videoWidth;
	bih.biHeight = videoHeight;
	bih.biSizeImage = biSizeImage;

	hr = AVIStreamSetFormat(pAviStream, 0, &bih, sizeof(bih));

	if (0 != hr)
	{

		AVIStreamClose(pAviStream);
		pAviStream = NULL;

		AVIFileRelease(pAviFile);
		pAviFile = NULL;
	}

	// 图像数据缓冲区
	BYTE * pData = new BYTE[biSizeImage];
	if (pData)
	{
		memset(pData, 0, biSizeImage);
	}

	//
	// 读取图像数据,更新AVI视频帧
	//
	if (pData)
	{
		for (int nFrames = 0; nFrames < 1; nFrames++)//同一图像拷贝10帧,由图像生成10秒avi视频
		{
			for (int i = 0; i < videoHeight; i++)
			{
				for (int j = 0; j < videoWidth; j++)
				{
					COLORREF clr = img.GetPixel(j, videoHeight - 1 - i);//(j,i)  
					pData[i * pitch + j * (bpp / 8) + 0] = GetBValue(clr);
					pData[i * pitch + j * (bpp / 8) + 1] = GetGValue(clr);
					pData[i * pitch + j * (bpp / 8) + 2] = GetRValue(clr);

				}
			}
			hr = AVIStreamWrite(pAviStream, nFrames, 1, pData, biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
		}
	}


	if (pData != NULL)
	{
		delete[] pData;
		pData = NULL;
	}

	if (pAviStream != NULL)
	{
		AVIStreamClose(pAviStream);
		pAviStream = NULL;
	}

	if (pAviFile != NULL)
	{
		AVIFileRelease(pAviFile);
		pAviFile = NULL;
	}
}

github:https://github.com/EthanXzhang/BmpToAvi


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值