Initial
This commit is contained in:
226
avifile/AVIGenerator.cpp
Normal file
226
avifile/AVIGenerator.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
#include <avifile/AVIGenerator.hpp>
|
||||
|
||||
bool AVIGenerator::createAVIFile(const String &pathAVIFile,const FOURCC &fccHandler,Block<String> &pathImageNames)
|
||||
{
|
||||
Compressor compressor;
|
||||
AVIBitmap aviBitmap;
|
||||
MovieData movieData;
|
||||
PAVIFILE pFile;
|
||||
PAVISTREAM pStream;
|
||||
AVISTREAMINFO aviStreamInfo;
|
||||
HRESULT hResult;
|
||||
DWORD elapsedTime;
|
||||
|
||||
pFile=0;
|
||||
pStream=0;
|
||||
if(!pathImageNames.size())return false;
|
||||
if(!compressor.open(fccHandler))return false;
|
||||
compressor.setQuality(mQuality);
|
||||
::unlink(pathAVIFile);
|
||||
if(!getImage(pathImageNames[0],aviBitmap,movieData))return false;
|
||||
AVIFileInit();
|
||||
hResult=AVIFileOpen(&pFile,pathAVIFile,OF_WRITE|OF_CREATE,NULL);
|
||||
if(hResult!=AVIERR_OK)return false;
|
||||
::memset(&aviStreamInfo,0,sizeof(AVISTREAMINFO));
|
||||
aviStreamInfo.fccType=streamtypeVIDEO;
|
||||
// aviStreamInfo.fccHandler=0;
|
||||
aviStreamInfo.fccHandler=fccHandler;
|
||||
aviStreamInfo.dwScale=mScale;
|
||||
aviStreamInfo.dwRate=mRate;
|
||||
aviStreamInfo.dwSuggestedBufferSize=aviBitmap.sizeImage();
|
||||
SetRect(&aviStreamInfo.rcFrame,0,0,aviBitmap.width(),aviBitmap.height());
|
||||
hResult=AVIFileCreateStream(pFile,&pStream,&aviStreamInfo);
|
||||
if(hResult==AVIERR_OK)
|
||||
{
|
||||
AVIBitmap dstBitmap;
|
||||
|
||||
if(compressor.compressQuery(aviBitmap))
|
||||
{
|
||||
// if(!getBestFormat(compressor,aviBitmap,dstBitmap))
|
||||
compressor.getFormat(aviBitmap,dstBitmap);
|
||||
hResult=AVIStreamSetFormat(pStream,0,&dstBitmap.getBITMAPINFOHEADER(),
|
||||
dstBitmap.getBITMAPINFOHEADER().biSize+(dstBitmap.getBITMAPINFOHEADER().biClrUsed*sizeof(RGBQUAD)));
|
||||
if(hResult==AVIERR_OK)
|
||||
{
|
||||
for(int index=0;index<pathImageNames.size();index++)
|
||||
{
|
||||
::printf("[AVIGenerator::createAVIFile] Processing sample %d of %d\n",index+1,pathImageNames.size());
|
||||
MovieData dstMovieData;
|
||||
if(index)getImage(pathImageNames[index],aviBitmap,movieData);
|
||||
elapsedTime=::GetTickCount();
|
||||
if(!compressor.compress(aviBitmap,movieData,dstBitmap,dstMovieData,index))
|
||||
{
|
||||
::printf("[AVIGenerator::createAVIFile] Compressor failed.\n");
|
||||
break;
|
||||
}
|
||||
::printf("[AVIGenerator::createAVIFile] Compress took %d (ms)\n",::GetTickCount()-elapsedTime);
|
||||
hResult=AVIStreamWrite(pStream,index,1,
|
||||
&dstMovieData[0],
|
||||
dstMovieData.size(),
|
||||
AVIIF_KEYFRAME,0,0);
|
||||
if(hResult!=AVIERR_OK)break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pStream)AVIStreamClose(pStream);
|
||||
if(pFile)AVIFileClose(pFile);
|
||||
AVIFileExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AVIGenerator::createAVIFile(const String &pathAVIFile,Block<String> &pathImageNames)
|
||||
{
|
||||
AVIBitmap aviBitmap;
|
||||
MovieData movieData;
|
||||
PAVIFILE pFile;
|
||||
PAVISTREAM pStream;
|
||||
AVISTREAMINFO aviStreamInfo;
|
||||
HRESULT hResult;
|
||||
|
||||
pFile=0;
|
||||
pStream=0;
|
||||
if(!pathImageNames.size())return false;
|
||||
::unlink(pathAVIFile);
|
||||
if(!getImage(pathImageNames[0],aviBitmap,movieData))return false;
|
||||
AVIFileInit();
|
||||
hResult=AVIFileOpen(&pFile,pathAVIFile,OF_WRITE|OF_CREATE,NULL);
|
||||
if(hResult!=AVIERR_OK)return false;
|
||||
::memset(&aviStreamInfo,0,sizeof(AVISTREAMINFO));
|
||||
aviStreamInfo.fccType=streamtypeVIDEO;
|
||||
aviStreamInfo.fccHandler=0;
|
||||
aviStreamInfo.dwScale=mScale; // time scale
|
||||
aviStreamInfo.dwRate=mRate; // rate in integer format, dwRate/dwScale = samples per second
|
||||
aviStreamInfo.dwSuggestedBufferSize=aviBitmap.sizeImage();
|
||||
SetRect(&aviStreamInfo.rcFrame,0,0,aviBitmap.width(),aviBitmap.height());
|
||||
hResult=AVIFileCreateStream(pFile,&pStream,&aviStreamInfo);
|
||||
if(hResult==AVIERR_OK)
|
||||
{
|
||||
hResult=AVIStreamSetFormat(pStream,0,&aviBitmap.getBITMAPINFOHEADER(),
|
||||
aviBitmap.getBITMAPINFOHEADER().biSize+(aviBitmap.getBITMAPINFOHEADER().biClrUsed*sizeof(RGBQUAD)));
|
||||
if(hResult==AVIERR_OK)
|
||||
{
|
||||
for(int index=0;index<pathImageNames.size();index++)
|
||||
{
|
||||
::printf("[AVIGenerator::createAVIFile] Processing sample %d of %d\n",index+1,pathImageNames.size());
|
||||
if(index)getImage(pathImageNames[index],aviBitmap,movieData);
|
||||
hResult=AVIStreamWrite(pStream,index,1,
|
||||
&movieData[0],
|
||||
movieData.size(),
|
||||
AVIIF_KEYFRAME,0,0);
|
||||
if(hResult!=AVIERR_OK)break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pStream)AVIStreamClose(pStream);
|
||||
if(pFile)AVIFileClose(pFile);
|
||||
AVIFileExit();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AVIGenerator::getImage(const String &strPathImage,AVIBitmap &aviBitmap,MovieData &movieData)
|
||||
{
|
||||
bool returnCode=false;
|
||||
if(strPathImage.isNull())return false;
|
||||
String extension=strPathImage.betweenString('.',0);
|
||||
extension.lower();
|
||||
DWORD elapsedTime;
|
||||
|
||||
if(extension=="jpg")
|
||||
{
|
||||
JPGImage jpgImage;
|
||||
elapsedTime=::GetTickCount();
|
||||
if(!jpgImage.decode(strPathImage))return false;
|
||||
::printf("[AVIGenerator::getImage] Decode took %d (ms)\n",::GetTickCount()-elapsedTime);
|
||||
if(mResample)
|
||||
{
|
||||
elapsedTime=::GetTickCount();
|
||||
jpgImage.resample(mResamplePoint.x(),mResamplePoint.y());
|
||||
::printf("[AVIGenerator::getImage] Resample took %d (ms)\n",::GetTickCount()-elapsedTime);
|
||||
}
|
||||
elapsedTime=::GetTickCount();
|
||||
getImageData(jpgImage,movieData);
|
||||
::printf("[AVIGenerator::getImage] GetImageData took %d (ms)\n",::GetTickCount()-elapsedTime);
|
||||
(BitmapInfo&)aviBitmap=jpgImage.getBitmapInfo();
|
||||
if(aviBitmap.height()<0)aviBitmap.height(-aviBitmap.height());
|
||||
returnCode=true;
|
||||
}
|
||||
else if(extension=="bmp")
|
||||
{
|
||||
Bitmap bitmap;
|
||||
bitmap=strPathImage;
|
||||
if(!bitmap.isOkay())return false;
|
||||
(BitmapInfo&)aviBitmap=*bitmap.getInfoPtr();
|
||||
movieData.size(bitmap.getInfoPtr()->bmiHeader.biSizeImage);
|
||||
::memcpy(&movieData[0],bitmap.ptrData(),bitmap.getInfoPtr()->bmiHeader.biSizeImage);
|
||||
returnCode=true;
|
||||
}
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
void AVIGenerator::getImageData(JPGImage &jpgImage,MovieData &movieData)
|
||||
{
|
||||
if(jpgImage.getBitmapInfo().height()<0)
|
||||
{
|
||||
Array<RGB888> &rgbArray=jpgImage.getRGBArray();
|
||||
Array<RGB888> tmpArray;
|
||||
tmpArray.size(rgbArray.size());
|
||||
jpgImage.getBitmapInfo().height(-jpgImage.getBitmapInfo().height());
|
||||
for(int row=0;row<jpgImage.height();row++)
|
||||
copyRow(&tmpArray[row*jpgImage.getBitmapInfo().width()],
|
||||
&rgbArray[(jpgImage.getBitmapInfo().height()-row)*
|
||||
jpgImage.getBitmapInfo().width()-
|
||||
jpgImage.getBitmapInfo().width()],
|
||||
jpgImage.getBitmapInfo().width());
|
||||
movieData.size(tmpArray.size()*3);
|
||||
::memcpy(&movieData[0],&tmpArray[0],tmpArray.size()*3);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array<RGB888> &rgbArray=jpgImage.getRGBArray();
|
||||
movieData.size(rgbArray.size()*3);
|
||||
::memcpy(&movieData[0],&rgbArray[0],rgbArray.size()*3);
|
||||
}
|
||||
}
|
||||
|
||||
void AVIGenerator::copyRow(RGB888 *pDstArray,RGB888 *pSrcArray,int length)
|
||||
{
|
||||
// for(unsigned long count=0;count<length;count++)*pDstArray++=*pSrcArray++;
|
||||
::memcpy(&pDstArray[0],&pSrcArray[0],length*sizeof(RGB888));
|
||||
}
|
||||
|
||||
bool AVIGenerator::getBestFormat(Compressor &compressor,AVIBitmap &srcBitmap,AVIBitmap &dstBitmap)
|
||||
{
|
||||
dstBitmap.width(srcBitmap.width());
|
||||
dstBitmap.height(srcBitmap.height());
|
||||
dstBitmap.compression(BitmapInfo::BiCompression(FOURCC("MPG1").toDWORD()));
|
||||
dstBitmap.colorUsed(0);
|
||||
dstBitmap.colorImportant(0);
|
||||
dstBitmap.bitCount(BitmapInfo::Bit16);
|
||||
if(compressor.compressQuery(srcBitmap,dstBitmap))
|
||||
{
|
||||
::printf("can compress to %s\n",dstBitmap.toString().str());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
::printf("can't compress to %s\n",dstBitmap.toString().str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
getBestFormat(compressor,aviBitmap);
|
||||
dstBitmap.width(aviBitmap.width());
|
||||
dstBitmap.height(aviBitmap.height());
|
||||
dstBitmap.bitCount(BitmapInfo::Bit8);
|
||||
dstBitmap.compression(BitmapInfo::BiCompression(FOURCC("cvid").toDWORD()));
|
||||
dstBitmap.colorUsed(0);
|
||||
dstBitmap.colorImportant(0);
|
||||
::printf("%s\n",dstBitmap.toString().str());
|
||||
if(compressor.compressQuery(aviBitmap,dstBitmap))
|
||||
{
|
||||
::printf("can compress to 8 bit\n");
|
||||
}
|
||||
else ::printf("can't compress to 8 bit");
|
||||
*/
|
||||
Reference in New Issue
Block a user