如何转换位图视频? [英] How to convert bitmaps to video?
问题描述
我的应用程序创建从分形图像和我爱的飞行围绕一个分形的感觉。我曾经救过约2000位图文件,并使用premiere创建的AVI如此。经验是相当令人沮丧,但我成功地创建了电影。这是壮观。当然,我想从我的应用程序创建一个视频。我其实并不关心codeC的niftyness,COM pression或什么的。我只是想有,我可以在大多数系统上重放视频。
在过去,我试过,但没有成功。我被一个<一个触发href=\"http://stackoverflow.com/questions/9584025/creating-a-motion-jpeg-frame-by-frame-with-variable-frame-rate\">question最近,但可惜无法得到FFmpeg的运行。
更新
我决定稍微适应的问题,并把赏金吧。我见过几个解决方案,但最有吸引力的(因为它的简单)在我看来TAviWrite。我试着TAviWriter,但没有成功。在程序TAviWriter.Write;围绕线函数调用370
AVIERR:= AVISaveV(S,
// PChar类型(文件名),
零,//文件处理程序
零,//回调
nStreams,//流数
流,
CompOptions);对于视频流//的COM preSS选项
不返回AVIERR_OK。
更新2
原因上述的错误是AVISaveV的一个错误的声明,应该被声明为AVISaveVW作为TLama指出。正确的code创建AVI filoes形式的BMP文件如下公布。低于原来的code是从一个例子单元EFG 下载。
在Windows 7使用德尔福XE。
单元AviWriter;////////////////////////////////////////////////// ///////////////////////////
// //
// AviWriter - 创建基本的AVI文件的组件//
//由埃利奥特Shevin,用大块code的//
//从安德斯·梅兰德被盗//
// 1.0版。请把意见,建议和建议//
//为shevine@aol.com。 //
////////////////////////////////////////////////// ///////////////////////////接口用途
Windows的消息,SysUtils单元,类图形,控件,表格,对话框,
StdCtrls中,OLE2;////////////////////////////////////////////////// //////////////////////////////
// //
// Windows视频//
// //
////////////////////////////////////////////////// //////////////////////////////
// //
//托马斯Schimming的VFW.PAS //改编
//(三)1996年托马斯Schimming,schimmin@iee1.et.tu-dresden.de //
//(三)1998,99安德斯·梅兰德//
// //
////////////////////////////////////////////////// //////////////////////////////
// //
//剥去所有的COM / ActiveX的东西,并增加了一些AVI流功能。 //
// //
////////////////////////////////////////////////// //////////////////////////////
由阿诺德和TLama(2012)//创建统一code版本//
////////////////////////////////////////////////// //////////////////////////////类型
龙= Longint型;
PVOID =指针;常量
// TAVIFileInfo dwFlag值
AVIF_HASINDEX = $ 00000010;
AVIF_MUSTUSEINDEX = $ 00000020;
AVIF_ISINTERLEAVED = $ 00000100;
AVIF_WASCAPTUREFILE = $ 00010000;
AVIF_COPYRIGHTED = $ 00020000;
AVIF_KNOWN_FLAGS = $零零零三零一三零; AVIERR_UNSUPPORTED = $八零零四四零六五; // MAKE_AVIERR(101)
AVIERR_BADFORMAT = $八○○四四○六六; // MAKE_AVIERR(102)
AVIERR_MEMORY = $八千零四万四千零六十七; // MAKE_AVIERR(103)
AVIERR_INTERNAL = $八千零四万四千零六十八; // MAKE_AVIERR(104)
AVIERR_BADFLAGS = $八○○四四○六九; // MAKE_AVIERR(105)
AVIERR_BADPARAM = $ 8004406A; // MAKE_AVIERR(106)
AVIERR_BADSIZE = $ 8004406B; // MAKE_AVIERR(107)
AVIERR_BADHANDLE = $ 8004406C; // MAKE_AVIERR(108)
AVIERR_FILEREAD = $ 8004406D; // MAKE_AVIERR(109)
AVIERR_FILEWRITE = $ 8004406E; // MAKE_AVIERR(110)
AVIERR_FILEOPEN = $ 8004406F; // MAKE_AVIERR(111)
AVIERR_COM preSSOR = 80044070 $; // MAKE_AVIERR(112)
AVIERR_NOCOM preSSOR = 80044071 $; // MAKE_AVIERR(113)
AVIERR_READONLY = $ 80044072; // MAKE_AVIERR(114)
AVIERR_NODATA = $八○○四四○七三; // MAKE_AVIERR(115)
AVIERR_BUFFERTOOSMALL = $ 80044074; // MAKE_AVIERR(116)
AVIERR_CANTCOM $ P $ =干燥综合征$ 80044075; // MAKE_AVIERR(117)
AVIERR_USERABORT = $ 800440C6; // MAKE_AVIERR(198)
AVIERR_ERROR = $ 800440C7; // MAKE_AVIERR(199)// TAVIStreamInfo dwFlag值
AVISF_DISABLED = $ 00000001;
AVISF_VIDEO_PALCHANGES = $ 00010000;
AVISF_KNOWN_FLAGS = $ 00010001;类型
TAVIFileInfoW =记录
dwMaxBytesPerSec,//最大。传输速率
dwFlags中,//在ever- present标志
dwCaps,
dwStreams,
dwSuggestedBufferSize, dwWidth,
dwHeight, dwScale,
dwRate,// dwRate / dwScale ==采样/秒
dwLength, dwEditCount:DWORD; szFileType:数组WideChar的[0..63] //描述字符串的文件类型?
结束;
PAVIFileInfoW = ^ TAVIFileInfoW; TAVIStreamInfoW =记录
fccType,
fccHandler,
dwFlags中,//包含AVITF_ *标志
dwCaps:DWORD;
wPriority,
wLanguage:WORD;
dwScale,
dwRate,// dwRate / dwScale ==采样/秒
dwStart,
dwLength,//在上面的单位...
dwInitialFrames,
dwSuggestedBufferSize,
dwQuality,
dwSampleSize:DWORD;
rcFrame:TRect;
dwEditCount,
dwFormatChangeCount:DWORD;
szName的:数组WideChar的[0..63]
结束;
TAVIStreamInfo = TAVIStreamInfoW;
PAVIStreamInfo = ^ TAVIStreamInfo; PAVIStream =指针;
PAVIFile =指针;
TAVIStreamList =阵列PAVIStream的[0..0]
PAVIStreamList = ^ TAVIStreamList;
TAVISaveCallback =功能(nPercent:整数):长; STDCALL; TAVICom pressOptions =包装记录
fccType:DWORD;
fccHandler:DWORD;
dwKeyFrameEvery:DWORD;
dwQuality:DWORD;
dwBytesPerSecond:DWORD;
dwFlags中:DWORD;
lpFormat:指针;
cbFormat:DWORD;
lpParms:指针;
cbParms:DWORD;
dwInterleaveEvery:DWORD;
结束;
PAVICom pressOptions = ^ TAVICom pressOptions;//调色板变化数据记录
常量
RIFF_PaletteChange:DWORD = 1668293411;类型
TAVIPalChange =包装记录
bFirstEntry:字节;
bNumEntries:字节;
wFlags:WORD;
peNew:数组TPaletteEntry的(字节);
结束;
PAVIPalChange = ^ TAVIPalChange; APAVISTREAM =阵列PAVISTREAM的[0..1]
APAVICom pressOptions =阵列PAVICom pressOptions的[0..1]
程序AVIFileInit; STDCALL;
程序AVIFileExit; STDCALL;
功能AVIFileOpen(VAR ppfile:PAVIFile; szFile:PChar类型; uMode:UINT; lpHandler:指针):HRESULT; STDCALL;
功能AVIFileCreateStream(PFILE:PAVIFile; VAR ppavi:PAVISTREAM; VAR PSI:TAVIStreamInfo):HRESULT; STDCALL;
功能AVIStreamSetFormat(PAVI:PAVIStream; LPOS:LONG; lpFormat:指针; cbFormat:LONG):HRESULT; STDCALL;
功能AVIStreamReadFormat(PAVI:PAVIStream; LPOS:LONG; lpFormat:指针; VAR cbFormat:LONG):HRESULT; STDCALL;
功能AVIStreamWrite(PAVI:PAVIStream; lStart,lSamples:LONG; lpBuffer:指针; cbBuffer:LONG; dwFlags中:DWORD; VAR plSampWritten:LONG; VAR plBytesWritten:LONG):HRESULT; STDCALL;
功能AVIStreamRelease(PAVI:PAVISTREAM):ULONG; STDCALL;
功能AVIFileRelease(PFILE:PAVIFile):ULONG; STDCALL;
功能AVIFileGetStream(PFILE:PAVIFile; VAR ppavi:PAVISTREAM; fccType:DWORD; lParam的:LONG):HRESULT; STDCALL;
功能CreateEditableStream(VAR ppsEditable:PAVISTREAM; psSource:PAVISTREAM):HRESULT; STDCALL;
功能AVISaveV(szFile:PChar类型; pclsidHandler:PCLSID; lpfnCallback:TAVISaveCallback;
nStreams:整数; PAVI:APAVISTREAM; lpOptions:APAVICom pressOptions):HRESULT; STDCALL;常量
AVIERR_OK = 0; AVIIF_LIST = $ 01;
AVIIF_TWOCC = $ 02;
AVIIF_KEYFRAME = $ 10; streamtypeVIDEO = $ 73646976; // DWORD('V','我','D','S')
streamtypeAUDIO = $七千三百六十四万七千五百六十一; // DWORD('A','U','D','S')
类型
TPixelFormat =(pfDevice,pf1bit,pf4bit,pf8bit,pf15bit,pf16bit,pf24bit,pf32bit,pfCustom);类型
TAviWriter =类(TComponent)
私人的
TempFileName:字符串;
PFILE:PAVIFile;
fHeight:整数;
fWidth:整数;
fStretch:布尔;
fFrameTime:整数;
Ffilename要:字符串;
fWavFileName:字符串;
视频流:PAVISTREAM;
语音串流:PAVISTREAM; 程序AddVideo;
程序AddAudio;
程序InternalGetDIBSizes(位图:HBITMAP; VAR InfoHeaderSize:整数;
VAR IMAGESIZE:LONGINT;的PixelFormat:TPixelFormat);
功能InternalGetDIB(位图:HBITMAP;调色板:HPALETTE;
VAR BITMAPINFO; VAR位;的PixelFormat:TPixelFormat):布尔;
程序InitializeBitmapInfoHeader(位图:HBITMAP; VAR信息:TBitmapInfoHeader;
的PixelFormat:TPixelFormat);
程序SetWavFileName(价值:字符串); 上市
位图:从TList;
构造函数创建(AOwner:TComponent);覆盖;
析构函数销毁;覆盖;
程序写; 发表
属性Height:整数读fHeight写fHeight;
属性width:整数读fWidth写fWidth;
物业FRAMETIME:整数读fFrameTime写fFrameTime;
物业拉伸:Boolean读出fStretch写fStretch;
属性文件名:字符串读Ffilename要写Ffilename要;
物业WavFileName:串读fWavFileName写SetWavFileName;
结束;程序注册;履行程序AVIFileInit; STDCALL;外部avifil32.dll'名'AVIFileInit';
程序AVIFileExit; STDCALL;外部avifil32.dll'名'AVIFileExit';
功能AVIFileOpen;外部avifil32.dll'名'AVIFileOpenW';
功能AVIFileCreateStream;外部avifil32.dll'名'AVIFileCreateStreamW';
功能AVIStreamSetFormat;外部avifil32.dll'名'AVIStreamSetFormat';
功能AVIStreamReadFormat;外部avifil32.dll'名'AVIStreamReadFormat';
功能AVIStreamWrite;外部avifil32.dll'名'AVIStreamWrite';
功能AVIStreamRelease;外部avifil32.dll'名'AVIStreamRelease';
功能AVIFileRelease;外部avifil32.dll'名'AVIFileRelease';
功能AVIFileGetStream;外部avifil32.dll'名'AVIFileGetStream';
功能CreateEditableStream;外部avifil32.dll'名'CreateEditableStream';
功能AVISaveV;外部avifil32.dll'名'AVISaveVW';构造TAviWriter.Create(AOwner:TComponent);
开始
继承创建(AOwner);
fHeight:= screen.height DIV 10;
fWidth:= screen.width DIV 10;
fFrameTime:= 1000;
fStretch:=真;
Ffilename要:='';
位图:= TList.create;
AVIFileInit;
TempFileName:= {TEMPDIR +}'temp.avi';
结束;析构函数TAviWriter.Destroy;
开始
Bitmaps.free;
AviFileExit;
遗传;
结束;程序TAviWriter.Write;
VAR
ExtBitmap:TBitmap;
nstreams:整数;
我:整数;
流:APAVISTREAM;
CompOptions:APAVICom pressOptions;
AVIERR:整数;
引用次数:整数;
开始
语音串流:=零;
视频流:=零; //如果没有点阵图名单上,引发一个错误。
如果Bitmaps.count&LT; 1
然后抬起Exception.Create(下称位图列表上没有位图'); //如果对位图什么的TList是不是一个位图,提高
// 一个错误。
对于i:= 0 Bitmaps.count - 1做
开始
ExtBitmap:=位图[I]
如果不是(ExtBitmap是TBitmap)
然后抬起Exception.Create(位图['+ inttostr(I)
+]不是TBitmap');
结束; //为 尝试
AddVideo; 如果WavFileName&LT;&GT; ''
然后AddAudio; //创建输出文件。
如果WavFileName&LT;&GT; ''
然后nstreams:= 2
别的nstreams:= 1; 流[0] =视频流;
流[1]:=语音串流;
CompOptions [0] =零;
CompOptions [1]:=无; AVIERR:= AVISaveV(
PChar类型(文件名),
零,//文件处理程序
零,//回调
nStreams,//流数
流,
CompOptions);对于视频流//的COM preSS选项
如果AVIERR&LT;&GT; AVIERR_OK然后
提高Exception.Create('无法写入输出文件');
最后
如果分配(视频流)
然后AviStreamRelease(视频流);
如果分配(语音串流)
然后AviStreamRelease(语音串流); 尝试
重复
引用计数:= AviFileRelease(PFILE);
直到引用计数&LT; = 0;
除
//忽略例外
结束; // try..except 的DeleteFile(TempFileName);
结束; // try..finally
结束;程序TAviWriter.AddVideo;
VAR
Pstream:PAVISTREAM;
StreamInfo:TAVIStreamInfo;
BITMAPINFO:PBitmapInfoHeader;
BitmapInfoSize:整数;
BitmapSize:LONGINT;
BitmapBits:指针;
位图:TBitmap;
ExtBitmap:TBitmap;
Samples_Written:LONG;
Bytes_Written:LONG;
AVIERR:整数;
我:整数;
OK:Int64的;
模式:为uInt32;
FN:PCHAR;
错误:字符串;
开始
//为写打开AVI文件
PFILE:=零;
模式:= OF_CREATE或OF_WRITE或OF_SHARE_EXCLUSIVE;
FN:= PChar类型(TempFileName); OK:= AVIFileOpen(PFILE,FN,模式,无);
如果正常= AVIERR_BADFORMAT再犯错:='文件无法读取,表示文件损坏或无法识别的格式。;
如果正常= AVIERR_MEMORY再犯错:='的文件不能因为内存不足开。;
如果正常= AVIERR_FILEREAD则错误:在读取文件时发生了磁盘错误。'=;
如果正常= AVIERR_FILEOPEN则错误:打开文件时发生磁盘错误。'=;
如果正常= REGDB_E_CLASSNOTREG再犯错:='根据注册表,文件中AVIFileOpen指定的类型没有一个处理程序处理它。;
如果犯错&LT;&GT; ''再养Exception.Create(ERR); //分配位图到对位图TLIST位图
//将被复制。
位图:= TBitmap.create;
Bitmap.Height:= self.Height;
Bitmap.Width:= self.Width; //写入流头。
尝试
FillChar(StreamInfo,sizeof的(StreamInfo),0); //设置帧速率和规模
StreamInfo.dwRate:= 1000;
StreamInfo.dwScale:= fFrameTime;
StreamInfo.fccType:= streamtypeVIDEO;
StreamInfo.fccHandler:= 0;
StreamInfo.dwFlags:= 0;
StreamInfo.dwSuggestedBufferSize:= 0;
StreamInfo.rcFrame.Right:= self.width;
StreamInfo.rcFrame.Bottom:= self.height; //打开AVI数据流
如果(AVIFileCreateStream(PFILE,pStream,StreamInfo)LT;&GT; AVIERR_OK),那么
提高Exception.Create(无法创建AVI视频流'); 尝试
//写位图到流。
对于i:= 0 Bitmaps.count - 1做
开始
BITMAPINFO:=零;
BitmapBits:=零;
尝试 //位图从列表复制到AVI位图,
//如果需要伸展。如果主叫方选择不
//拉伸,使用第一像素中的位图作为一个
//如果背景颜色或者高度或
//源的宽度比输出小。
//如果绘制失败,做一个StretchDraw。
ExtBitmap:=位图[I]
如果fStretch
然后Bitmap.Canvas.StretchDraw
(矩形(0,0,self.width,self.height),ExtBitmap)
其他尝试
与Bitmap.Canvas开始做
Brush.Color:= ExtBitmap.Canvas.Pixels [0,0];
Brush.Style:= bsSolid;
FillRect(矩形(0,0,Bitmap.Width,Bitmap.Height));
绘制(0,0,ExtBitmap);
结束;
除
Bitmap.Canvas.StretchDraw
(矩形(0,0,self.width,self.height),ExtBitmap);
结束; //确定DIB的大小
InternalGetDIBSizes(Bitmap.Handle,BitmapInfoSize,BitmapSize,pf8bit);
如果(BitmapInfoSize = 0),那么
提高Exception.Create(无法检索位图信息); //获取DIB头和像素缓冲区
GetMem例程(BITMAPINFO,BitmapInfoSize);
GetMem例程(BitmapBits,BitmapSize);
InternalGetDIB
(Bitmap.Handle,0,BITMAPINFO ^,BitmapBits ^,pf8bit); //在第一次通过,设置流格式。
若i = 0,则
如果(AVIStreamSetFormat(pStream,0,BITMAPINFO,BitmapInfoSize)LT;&GT; AVIERR_OK),那么
提高Exception.Create('无法设置AVI流格式'); //写入帧到视频流
AVIERR:=
AVIStreamWrite(pStream,我,1,BitmapBits,BitmapSize,AVIIF_KEYFRAME,
Samples_Written,Bytes_Written);
如果AVIERR&LT;&GT; AVIERR_OK然后
提高Exception.Create
('无法添加相框为AVI。错误='
+ INTTOHEX(AVIERR,8));
最后
如果(BITMAPINFO&LT;&GT;无),然后
freemem在(BITMAPINFO);
如果(BitmapBits&LT;&GT;无),然后
freemem在(BitmapBits);
结束;
结束; //创建从pStream可编辑视频流。
如果CreateEditableStream(视频流,pStream)LT;&GT; AVIERR_OK然后
提高Exception.Create
(无法创建视频流');
最后
AviStreamRelease(pStream);
结束; 最后
Bitmap.free;
结束;
结束;程序TAviWriter.AddAudio;
VAR
与InputFile:PAVIFILE;
的InputStream:PAVIStream;
错误:字符串;
OK:Int64的;
开始
//打开的音频文件。
OK:= AVIFileOpen(inputFile,请PChar类型(WavFileName),OF_READ,无);
如果正常= AVIERR_BADFORMAT再犯错:='文件无法读取,表示文件损坏或无法识别的格式。;
如果正常= AVIERR_MEMORY再犯错:='的文件不能因为内存不足开。;
如果正常= AVIERR_FILEREAD则错误:在读取文件时发生了磁盘错误。'=;
如果正常= AVIERR_FILEOPEN则错误:打开文件时发生磁盘错误。'=;
如果正常= REGDB_E_CLASSNOTREG再犯错:='根据注册表,文件中AVIFileOpen指定的类型没有一个处理程序处理它。;
如果犯错&LT;&GT; ''再养Exception.Create(ERR); //打开音频流。
尝试
如果(AVIFileGetStream(inputFile,请的InputStream,0,0)下;&GT; AVIERR_OK)然后
提高Exception.Create('无法获取音频流'); 尝试
//创建语音串流为InputStream的副本
如果(CreateEditableStream(语音串流,为InputStream)LT;&GT; AVIERR_OK),那么
提高Exception.Create(无法创建可编辑的AVI音频流');
最后
AviStreamRelease(InputStream的);
结束; 最后
AviFileRelease(与InputFile);
结束;
结束;// --------------
// InternalGetDIB
// --------------
//位图以指定的PixelFormat的一个DIB转换。
//
//注意:InternalGetDIBSizes函数可以用来计算
//将BITMAPINFO位和缓冲区的大小nescessary。
//
//从graphics.pas,优化为我所用功能TAviWriter.InternalGetDIB
(
位图:HBITMAP; //源位图的句柄
调色板:HPALETTE; //源面板的手柄
VAR BITMAPINFO; //将接收DIB的TBitmapInfo结构的缓冲区。
//足够大小的缓冲区必须被分配到前
//调用这个函数
VAR位; //将接收DIB的像素数据的缓冲区
的PixelFormat:TPixelFormat //目的地DIB的像素格式
):布尔; //真正的成功,失败返回FALSE
VAR
OldPal:HPALETTE;
DC:HDC;
开始
InitializeBitmapInfoHeader(位图,TBitmapInfoHeader(BITMAPINFO)的PixelFormat);
OldPal:= 0;
直流:= CreateCompatibleDC(0);
尝试
如果(调色板&所述;大于0),那么
开始
OldPal:= SelectPalette(DC,调色板,FALSE);
RealizePalette(DC);
结束;
结果:=(的GetDIBits(DC,位图,0,ABS(TBitmapInfoHeader(BITMAPINFO).biHeight)
@Bits,TBitmapInfo(BITMAPINFO),DIB_RGB_COLORS)LT;&GT; 0);
最后
如果(OldPal&所述;大于0),那么
SelectPalette(DC,OldPal,FALSE);
DeleteDC(DC);
结束;
结束;
// -------------------
// InternalGetDIBSizes
// -------------------
//计算缓冲区大小为nescessary位图的皈依到DIB
//指定的PixelFormat的。
//获取更多信息,请参见GetDIBSizes API函数。
//从graphics.pas,优化为我所用程序TAviWriter.InternalGetDIBSizes
(
位图:HBITMAP; //源位图的句柄
VAR InfoHeaderSize:整数; //缓冲区返回的大小,将接收
// DIB的TBitmapInfo结构
VAR IMAGESIZE:LONGINT; //缓冲区的大小返回将接收DIB的像素数据
的PixelFormat:TPixelFormat //目的地DIB的像素格式
);
VAR
信息:TBitmapInfoHeader;
开始
InitializeBitmapInfoHeader(位图,信息,的PixelFormat);
//检查调色板设备格式
如果(Info.biBitCount→8)然后
开始
//头,但没有调色板
InfoHeaderSize:=一下SizeOf(TBitmapInfoHeader);
如果((Info.biCom pression和BI_BITFIELDS)所述;大于0),那么
公司(InfoHeaderSize,12);
其他结束
//头和调色板
InfoHeaderSize:=一下SizeOf(TBitmapInfoHeader)+一下SizeOf(TRGBQuad)*(1 SHL Info.biBitCount);
IMAGESIZE:= Info.biSizeImage;
结束;// --------------------------
// InitializeBitmapInfoHeader
// --------------------------
//当转换为一个填充用位图的值的TBitmapInfoHeader
//指定的PixelFormat的DIB。
//从graphics.pas,优化为我所用程序TAviWriter.InitializeBitmapInfoHeader
(
位图:HBITMAP; //源位图的句柄
VAR信息:TBitmapInfoHeader; //该TBitmapInfoHeader缓冲区,将接收到的值
的PixelFormat:TPixelFormat //目的地DIB的像素格式
);
VAR
DIB:TDIBSection;
字节:整数;
功能AlignBit(位,BitsPerPixel,阵营:红衣主教):红衣主教;
开始
DEC(校准);
结果:=((位* BitsPerPixel)+对齐),而不是对准;
结果:=结果SHR 3;
结束;
开始
DIB.dsbmih.biSize:= 0;
字节:= GetObject的(位图,一下SizeOf(DIB),@DIB);
如果(字节= 0),那么
提高Exception.Create('无效的位图');
//错误(sInvalidBitmap); 如果(字节&GT; =(sizeof的(DIB.dsbm)+ sizeof的(DIB.dsbmih)))和
(DIB.dsbmih.biSize&GT; = sizeof的(DIB.dsbmih)),然后
信息:= DIB.dsbmih
其他
开始
FillChar(信息,sizeof的(信息),0);
与信息,DIB.dsbm做
开始
biSize:=一下SizeOf(信息);
biWidth:= bmWidth;
biHeight:= bmHeight;
结束;
结束;
时的PixelFormat
pf1bit:Info.biBitCount:= 1;
pf4bit:Info.biBitCount:= 4;
pf8bit:Info.biBitCount:= 8;
pf24bit:Info.biBitCount:= 24;
其他
//错误(sInvalidPixelFormat);
提高Exception.Create('无效的像素格式');
// Info.biBitCount:= DIB.dsbm.bmBitsPixel * DIB.dsbm.bmPlanes;
结束;
Info.biPlanes:= 1;
Info.biCom pression:= BI_RGB; //始终在RGB格式返回数据
Info.biSizeImage:= AlignBit(Info.biWidth,Info.biBitCount,32)*红衣主教(ABS(Info.biHeight));
结束;程序TAviWriter.SetWavFileName(价值:字符串);
开始
如果小写(fWavFileName)LT;&GT;小写字母(值)
那么如果小写(ExtractFileExt(值))&LT;&GT; .WAV
然后抬起Exception.Create('WavFileName必须命名一个文件
+'与.WAV扩展名)
否则fWavFileName:=值;
结束;程序注册;
开始
RegisterComponents('样品',[TAviWriter]);
结束;结束。
更改的 AVISaveV
功能,它的统一code版本。当在Windows API的参考函数的说明的Uni code和ANSI名字
对您来说意味着,在Delphi中,你要选择无论是从统一code版的功能,或从ANSI之一取决于你会使用什么样的编译器。
您正在试图调用 AVISaveV
,它实际并不存在。这里只有 AVISaveVA
和 AVISaveVW
在 avifil32.dll
和既然你要这个code转换为统一code,尝试改变函数导入是这样的:
功能AVISaveV;外部avifil32.dll'名'AVISaveVW';
这仅仅是第一思想,code的定义,就像是甚至不能在Delphi中的非统一code版本的工作,因为它称为不存在的功能。
My application creates images from fractals and I love the feeling of 'flying' around a fractal. I once saved about 2000 bitmaps to file and created an AVI from it using Premiere. That experience is rather frustrating though I succeeded in creating a movie. That was spectacular. Of course I want to create a video from my application. I actually don't care about the niftyness of the codec, compression or whatever. I just want to have a video that I can replay on most systems.
In the past I have tried this but never succeeded. I was triggered by a question recently but alas could not get FFMpeg running.
Update
I decided to adapt the question slightly and put a bounty for it. I have seen several solutions but the most attractive (because it's simple) seems to me TAviWrite. I tried TAviWriter but did not succeed. In procedure TAviWriter.Write; the function call around line 370
AVIERR := AVISaveV(s,
// pchar(FileName),
nil, // File handler
nil, // Callback
nStreams, // Number of streams
Streams,
CompOptions); // Compress options for VideoStream
does not return AVIERR_OK.
Update 2
The reason for above mentioned error is a wrong declaration of AVISaveV, it should be declared as AVISaveVW as TLama pointed out. The correct code for creating AVI filoes form BMP files is posted below. The original code below was downloaded from efg with an example unit.
Using Delphi XE on Windows 7.
unit AviWriter;
/////////////////////////////////////////////////////////////////////////////
// //
// AviWriter -- a component to create rudimentary AVI files //
// by Elliott Shevin, with large pieces of code //
// stolen from Anders Melander //
// version 1.0. Please send comments, suggestions, and advice //
// to shevine@aol.com. //
/////////////////////////////////////////////////////////////////////////////
interface
uses
Windows,Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ole2;
////////////////////////////////////////////////////////////////////////////////
// //
// Video for Windows //
// //
////////////////////////////////////////////////////////////////////////////////
// //
// Adapted from Thomas Schimming's VFW.PAS //
// (c) 1996 Thomas Schimming, schimmin@iee1.et.tu-dresden.de //
// (c) 1998,99 Anders Melander //
// //
////////////////////////////////////////////////////////////////////////////////
// //
// Ripped all COM/ActiveX stuff and added some AVI stream functions. //
// //
////////////////////////////////////////////////////////////////////////////////
// Unicode version created by Arnold and TLama (2012) //
////////////////////////////////////////////////////////////////////////////////
type
LONG = Longint;
PVOID = Pointer;
const
// TAVIFileInfo dwFlag values
AVIF_HASINDEX = $00000010;
AVIF_MUSTUSEINDEX = $00000020;
AVIF_ISINTERLEAVED = $00000100;
AVIF_WASCAPTUREFILE = $00010000;
AVIF_COPYRIGHTED = $00020000;
AVIF_KNOWN_FLAGS = $00030130;
AVIERR_UNSUPPORTED = $80044065; // MAKE_AVIERR(101)
AVIERR_BADFORMAT = $80044066; // MAKE_AVIERR(102)
AVIERR_MEMORY = $80044067; // MAKE_AVIERR(103)
AVIERR_INTERNAL = $80044068; // MAKE_AVIERR(104)
AVIERR_BADFLAGS = $80044069; // MAKE_AVIERR(105)
AVIERR_BADPARAM = $8004406A; // MAKE_AVIERR(106)
AVIERR_BADSIZE = $8004406B; // MAKE_AVIERR(107)
AVIERR_BADHANDLE = $8004406C; // MAKE_AVIERR(108)
AVIERR_FILEREAD = $8004406D; // MAKE_AVIERR(109)
AVIERR_FILEWRITE = $8004406E; // MAKE_AVIERR(110)
AVIERR_FILEOPEN = $8004406F; // MAKE_AVIERR(111)
AVIERR_COMPRESSOR = $80044070; // MAKE_AVIERR(112)
AVIERR_NOCOMPRESSOR = $80044071; // MAKE_AVIERR(113)
AVIERR_READONLY = $80044072; // MAKE_AVIERR(114)
AVIERR_NODATA = $80044073; // MAKE_AVIERR(115)
AVIERR_BUFFERTOOSMALL = $80044074; // MAKE_AVIERR(116)
AVIERR_CANTCOMPRESS = $80044075; // MAKE_AVIERR(117)
AVIERR_USERABORT = $800440C6; // MAKE_AVIERR(198)
AVIERR_ERROR = $800440C7; // MAKE_AVIERR(199)
// TAVIStreamInfo dwFlag values
AVISF_DISABLED = $00000001;
AVISF_VIDEO_PALCHANGES = $00010000;
AVISF_KNOWN_FLAGS = $00010001;
type
TAVIFileInfoW = record
dwMaxBytesPerSec,// max. transfer rate
dwFlags, // the ever-present flags
dwCaps,
dwStreams,
dwSuggestedBufferSize,
dwWidth,
dwHeight,
dwScale,
dwRate, // dwRate / dwScale == samples/second
dwLength,
dwEditCount: DWORD;
szFileType: array[0..63] of WideChar; // descriptive string for file type?
end;
PAVIFileInfoW = ^TAVIFileInfoW;
TAVIStreamInfoW = record
fccType,
fccHandler,
dwFlags, // Contains AVITF_* flags
dwCaps: DWORD;
wPriority,
wLanguage: WORD;
dwScale,
dwRate, // dwRate / dwScale == samples/second
dwStart,
dwLength, // In units above...
dwInitialFrames,
dwSuggestedBufferSize,
dwQuality,
dwSampleSize: DWORD;
rcFrame: TRect;
dwEditCount,
dwFormatChangeCount: DWORD;
szName: array[0..63] of WideChar;
end;
TAVIStreamInfo = TAVIStreamInfoW;
PAVIStreamInfo = ^TAVIStreamInfo;
PAVIStream = pointer;
PAVIFile = pointer;
TAVIStreamList = array[0..0] of PAVIStream;
PAVIStreamList = ^TAVIStreamList;
TAVISaveCallback = function (nPercent: integer): LONG; stdcall;
TAVICompressOptions = packed record
fccType : DWORD;
fccHandler : DWORD;
dwKeyFrameEvery : DWORD;
dwQuality : DWORD;
dwBytesPerSecond : DWORD;
dwFlags : DWORD;
lpFormat : pointer;
cbFormat : DWORD;
lpParms : pointer;
cbParms : DWORD;
dwInterleaveEvery : DWORD;
end;
PAVICompressOptions = ^TAVICompressOptions;
// Palette change data record
const
RIFF_PaletteChange: DWORD = 1668293411;
type
TAVIPalChange = packed record
bFirstEntry : byte;
bNumEntries : byte;
wFlags : WORD;
peNew : array[byte] of TPaletteEntry;
end;
PAVIPalChange = ^TAVIPalChange;
APAVISTREAM = array[0..1] of PAVISTREAM;
APAVICompressOptions = array[0..1] of PAVICompressOptions;
procedure AVIFileInit; stdcall;
procedure AVIFileExit; stdcall;
function AVIFileOpen(var ppfile: PAVIFile; szFile: PChar; uMode: UINT; lpHandler: pointer): HResult; stdcall;
function AVIFileCreateStream(pfile: PAVIFile; var ppavi: PAVISTREAM; var psi: TAVIStreamInfo): HResult; stdcall;
function AVIStreamSetFormat(pavi: PAVIStream; lPos: LONG; lpFormat: pointer; cbFormat: LONG): HResult; stdcall;
function AVIStreamReadFormat(pavi: PAVIStream; lPos: LONG; lpFormat: pointer; var cbFormat: LONG): HResult; stdcall;
function AVIStreamWrite(pavi: PAVIStream; lStart, lSamples: LONG; lpBuffer: pointer; cbBuffer: LONG; dwFlags: DWORD; var plSampWritten: LONG; var plBytesWritten: LONG): HResult; stdcall;
function AVIStreamRelease(pavi: PAVISTREAM): ULONG; stdcall;
function AVIFileRelease(pfile: PAVIFile): ULONG; stdcall;
function AVIFileGetStream(pfile: PAVIFile; var ppavi: PAVISTREAM; fccType: DWORD; lParam: LONG): HResult; stdcall;
function CreateEditableStream(var ppsEditable: PAVISTREAM; psSource: PAVISTREAM): HResult; stdcall;
function AVISaveV(szFile: PChar; pclsidHandler: PCLSID; lpfnCallback: TAVISaveCallback;
nStreams: integer; pavi: APAVISTREAM; lpOptions: APAVICompressOptions): HResult; stdcall;
const
AVIERR_OK = 0;
AVIIF_LIST = $01;
AVIIF_TWOCC = $02;
AVIIF_KEYFRAME = $10;
streamtypeVIDEO = $73646976; // DWORD( 'v', 'i', 'd', 's' )
streamtypeAUDIO = $73647561; // DWORD( 'a', 'u', 'd', 's' )
type
TPixelFormat = (pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit, pf32bit, pfCustom);
type
TAviWriter = class (TComponent)
private
TempFileName : string;
pFile : PAVIFile;
fHeight : integer;
fWidth : integer;
fStretch : boolean;
fFrameTime : integer;
fFileName : string;
fWavFileName : string;
VideoStream : PAVISTREAM;
AudioStream : PAVISTREAM;
procedure AddVideo;
procedure AddAudio;
procedure InternalGetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: Integer;
var ImageSize: longInt; PixelFormat: TPixelFormat);
function InternalGetDIB(Bitmap: HBITMAP; Palette: HPALETTE;
var BitmapInfo; var Bits; PixelFormat: TPixelFormat): Boolean;
procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var Info: TBitmapInfoHeader;
PixelFormat: TPixelFormat);
procedure SetWavFileName(value : string);
public
Bitmaps : TList;
constructor Create(AOwner : TComponent); override;
destructor Destroy; override;
procedure Write;
published
property Height : integer read fHeight write fHeight;
property Width : integer read fWidth write fWidth;
property FrameTime: integer read fFrameTime write fFrameTime;
property Stretch : boolean read fStretch write fStretch;
property FileName : string read fFileName write fFileName;
property WavFileName : string read fWavFileName write SetWavFileName;
end;
procedure Register;
implementation
procedure AVIFileInit; stdcall; external 'avifil32.dll' name 'AVIFileInit';
procedure AVIFileExit; stdcall; external 'avifil32.dll' name 'AVIFileExit';
function AVIFileOpen; external 'avifil32.dll' name 'AVIFileOpenW';
function AVIFileCreateStream; external 'avifil32.dll' name 'AVIFileCreateStreamW';
function AVIStreamSetFormat; external 'avifil32.dll' name 'AVIStreamSetFormat';
function AVIStreamReadFormat; external 'avifil32.dll' name 'AVIStreamReadFormat';
function AVIStreamWrite; external 'avifil32.dll' name 'AVIStreamWrite';
function AVIStreamRelease; external 'avifil32.dll' name 'AVIStreamRelease';
function AVIFileRelease; external 'avifil32.dll' name 'AVIFileRelease';
function AVIFileGetStream; external 'avifil32.dll' name 'AVIFileGetStream';
function CreateEditableStream; external 'avifil32.dll' name 'CreateEditableStream';
function AVISaveV; external 'avifil32.dll' name 'AVISaveVW';
constructor TAviWriter.Create(AOwner : TComponent);
begin
inherited Create(AOwner);
fHeight := screen.height div 10;
fWidth := screen.width div 10;
fFrameTime := 1000;
fStretch := true;
fFileName := '';
Bitmaps := TList.create;
AVIFileInit;
TempFileName := {tempdir +} 'temp.avi';
end;
destructor TAviWriter.Destroy;
begin
Bitmaps.free;
AviFileExit;
inherited;
end;
procedure TAviWriter.Write;
var
ExtBitmap : TBitmap;
nstreams : integer;
i : integer;
Streams : APAVISTREAM;
CompOptions : APAVICompressOptions;
AVIERR : integer;
refcount : integer;
begin
AudioStream := nil;
VideoStream := nil;
// If no bitmaps are on the list, raise an error.
if Bitmaps.count < 1
then raise Exception.Create('No bitmaps on the Bitmaps list');
// If anything on the Bitmaps TList is not a bitmap, raise
// an error.
for i := 0 to Bitmaps.count - 1 do
begin
ExtBitmap := Bitmaps[i];
if not(ExtBitmap is TBitmap)
then raise Exception.Create('Bitmaps[' + inttostr(i)
+ '] is not a TBitmap');
end; // for
try
AddVideo;
if WavFileName <> ''
then AddAudio;
// Create the output file.
if WavFileName <> ''
then nstreams := 2
else nstreams := 1;
Streams[0] := VideoStream;
Streams[1] := AudioStream;
CompOptions[0] := nil;
CompOptions[1] := nil;
AVIERR := AVISaveV(
pchar(FileName),
nil, // File handler
nil, // Callback
nStreams, // Number of streams
Streams,
CompOptions); // Compress options for VideoStream
if AVIERR <> AVIERR_OK then
raise Exception.Create('Unable to write output file');
finally
if assigned(VideoStream)
then AviStreamRelease(VideoStream);
if assigned(AudioStream)
then AviStreamRelease(AudioStream);
try
repeat
refcount := AviFileRelease(pFile);
until refcount <= 0;
except
// ignore exception
end; // try..except
DeleteFile(TempFileName);
end; // try..finally
end;
procedure TAviWriter.AddVideo;
var
Pstream: PAVISTREAM;
StreamInfo: TAVIStreamInfo;
BitmapInfo: PBitmapInfoHeader;
BitmapInfoSize: Integer;
BitmapSize: longInt;
BitmapBits: pointer;
Bitmap: TBitmap;
ExtBitmap: TBitmap;
Samples_Written: LONG;
Bytes_Written: LONG;
AVIERR: integer;
i: integer;
ok: Int64;
mode: uInt32;
fn: pChar;
err: string;
begin
// Open AVI file for write
pfile := nil;
mode := OF_CREATE or OF_WRITE or OF_SHARE_EXCLUSIVE;
fn := pchar (TempFileName);
ok := AVIFileOpen (pFile, fn, mode, nil);
if ok = AVIERR_BADFORMAT then err := 'The file could not be read, indicating a corrupt file or an unrecognized format.';
if ok = AVIERR_MEMORY then err := 'The file could not be opened because of insufficient memory.';
if ok = AVIERR_FILEREAD then err := 'A disk error occurred while reading the file.';
if ok = AVIERR_FILEOPEN then err := 'A disk error occurred while opening the file.';
if ok = REGDB_E_CLASSNOTREG then err := 'According to the registry, the type of file specified in AVIFileOpen does not have a handler to process it.';
if err <> '' then raise Exception.Create (err);
// Allocate the bitmap to which the bitmaps on the Bitmaps Tlist
// will be copied.
Bitmap := TBitmap.create;
Bitmap.Height := self.Height;
Bitmap.Width := self.Width;
// Write the stream header.
try
FillChar (StreamInfo, sizeof (StreamInfo), 0);
// Set frame rate and scale
StreamInfo.dwRate := 1000;
StreamInfo.dwScale := fFrameTime;
StreamInfo.fccType := streamtypeVIDEO;
StreamInfo.fccHandler := 0;
StreamInfo.dwFlags := 0;
StreamInfo.dwSuggestedBufferSize := 0;
StreamInfo.rcFrame.Right := self.width;
StreamInfo.rcFrame.Bottom := self.height;
// Open AVI data stream
if (AVIFileCreateStream(pFile, pStream, StreamInfo) <> AVIERR_OK) then
raise Exception.Create('Failed to create AVI video stream');
try
// Write the bitmaps to the stream.
for i := 0 to Bitmaps.count - 1 do
begin
BitmapInfo := nil;
BitmapBits := nil;
try
// Copy the bitmap from the list to the AVI bitmap,
// stretching if desired. If the caller elects not to
// stretch, use the first pixel in the bitmap as a
// background color in case either the height or
// width of the source is smaller than the output.
// If Draw fails, do a StretchDraw.
ExtBitmap := Bitmaps[i];
if fStretch
then Bitmap.Canvas.StretchDraw
(Rect(0,0,self.width,self.height),ExtBitmap)
else try
with Bitmap.Canvas do begin
Brush.Color := ExtBitmap.Canvas.Pixels[0,0];
Brush.Style := bsSolid;
FillRect(Rect(0,0,Bitmap.Width,Bitmap.Height));
Draw(0,0,ExtBitmap);
end;
except
Bitmap.Canvas.StretchDraw
(Rect(0,0,self.width,self.height),ExtBitmap);
end;
// Determine size of DIB
InternalGetDIBSizes(Bitmap.Handle, BitmapInfoSize, BitmapSize, pf8bit);
if (BitmapInfoSize = 0) then
raise Exception.Create('Failed to retrieve bitmap info');
// Get DIB header and pixel buffers
GetMem(BitmapInfo, BitmapInfoSize);
GetMem(BitmapBits, BitmapSize);
InternalGetDIB
(Bitmap.Handle, 0, BitmapInfo^, BitmapBits^, pf8bit);
// On the first time through, set the stream format.
if i = 0 then
if (AVIStreamSetFormat(pStream, 0, BitmapInfo, BitmapInfoSize) <> AVIERR_OK) then
raise Exception.Create('Failed to set AVI stream format');
// Write frame to the video stream
AVIERR :=
AVIStreamWrite(pStream, i, 1, BitmapBits, BitmapSize, AVIIF_KEYFRAME,
Samples_Written, Bytes_Written);
if AVIERR <> AVIERR_OK then
raise Exception.Create
('Failed to add frame to AVI. Err='
+ inttohex(AVIERR,8));
finally
if (BitmapInfo <> nil) then
FreeMem(BitmapInfo);
if (BitmapBits <> nil) then
FreeMem(BitmapBits);
end;
end;
// Create the editable VideoStream from pStream.
if CreateEditableStream(VideoStream,pStream) <> AVIERR_OK then
raise Exception.Create
('Could not create Video Stream');
finally
AviStreamRelease(pStream);
end;
finally
Bitmap.free;
end;
end;
procedure TAviWriter.AddAudio;
var
InputFile : PAVIFILE;
InputStream : PAVIStream;
err: string;
ok: Int64;
begin
// Open the audio file.
ok := AVIFileOpen(InputFile, pchar(WavFileName),OF_READ, nil);
if ok = AVIERR_BADFORMAT then err := 'The file could not be read, indicating a corrupt file or an unrecognized format.';
if ok = AVIERR_MEMORY then err := 'The file could not be opened because of insufficient memory.';
if ok = AVIERR_FILEREAD then err := 'A disk error occurred while reading the file.';
if ok = AVIERR_FILEOPEN then err := 'A disk error occurred while opening the file.';
if ok = REGDB_E_CLASSNOTREG then err := 'According to the registry, the type of file specified in AVIFileOpen does not have a handler to process it.';
if err <> '' then raise Exception.Create (err);
// Open the audio stream.
try
if (AVIFileGetStream(InputFile, InputStream, 0, 0) <> AVIERR_OK) then
raise Exception.Create('Unable to get audio stream');
try
// Create AudioStream as a copy of InputStream
if (CreateEditableStream(AudioStream,InputStream) <> AVIERR_OK) then
raise Exception.Create('Failed to create editable AVI audio stream');
finally
AviStreamRelease(InputStream);
end;
finally
AviFileRelease(InputFile);
end;
end;
// --------------
// InternalGetDIB
// --------------
// Converts a bitmap to a DIB of a specified PixelFormat.
//
// Note: The InternalGetDIBSizes function can be used to calculate the
// nescessary sizes of the BitmapInfo and Bits buffers.
//
// From graphics.pas, "optimized" for our use
function TAviWriter.InternalGetDIB
(
Bitmap: HBITMAP; // The handle of the source bitmap
Palette: HPALETTE; // The handle of the source palette
var BitmapInfo; // The buffer that will receive the DIB's TBitmapInfo structure.
// A buffer of sufficient size must have been allocated prior to
// calling this function
var Bits; // The buffer that will receive the DIB's pixel data
PixelFormat: TPixelFormat // The pixel format of the destination DIB
): Boolean; // True on success, False on failure
var
OldPal : HPALETTE;
DC : HDC;
begin
InitializeBitmapInfoHeader(Bitmap, TBitmapInfoHeader(BitmapInfo), PixelFormat);
OldPal := 0;
DC := CreateCompatibleDC(0);
try
if (Palette <> 0) then
begin
OldPal := SelectPalette(DC, Palette, False);
RealizePalette(DC);
end;
Result := (GetDIBits(DC, Bitmap, 0, abs(TBitmapInfoHeader(BitmapInfo).biHeight),
@Bits, TBitmapInfo(BitmapInfo), DIB_RGB_COLORS) <> 0);
finally
if (OldPal <> 0) then
SelectPalette(DC, OldPal, False);
DeleteDC(DC);
end;
end;
// -------------------
// InternalGetDIBSizes
// -------------------
// Calculates the buffer sizes nescessary for convertion of a bitmap to a DIB
// of a specified PixelFormat.
// See the GetDIBSizes API function for more info.
// From graphics.pas, "optimized" for our use
procedure TAviWriter.InternalGetDIBSizes
(
Bitmap: HBITMAP; // The handle of the source bitmap
var InfoHeaderSize: Integer; // The returned size of a buffer that will receive
// the DIB's TBitmapInfo structure
var ImageSize: longInt; // The returned size of a buffer that will receive the DIB's pixel data
PixelFormat: TPixelFormat // The pixel format of the destination DIB
);
var
Info: TBitmapInfoHeader;
begin
InitializeBitmapInfoHeader(Bitmap, Info, PixelFormat);
// Check for palette device format
if (Info.biBitCount > 8) then
begin
// Header but no palette
InfoHeaderSize := SizeOf(TBitmapInfoHeader);
if ((Info.biCompression and BI_BITFIELDS) <> 0) then
Inc(InfoHeaderSize, 12);
end else
// Header and palette
InfoHeaderSize := SizeOf(TBitmapInfoHeader) + SizeOf(TRGBQuad) * (1 shl Info.biBitCount);
ImageSize := Info.biSizeImage;
end;
// --------------------------
// InitializeBitmapInfoHeader
// --------------------------
// Fills a TBitmapInfoHeader with the values of a bitmap when converted to a
// DIB of a specified PixelFormat.
// From graphics.pas, "optimized" for our use
procedure TAviWriter.InitializeBitmapInfoHeader
(
Bitmap: HBITMAP; // The handle of the source bitmap
var Info: TBitmapInfoHeader; // The TBitmapInfoHeader buffer that will receive the values
PixelFormat: TPixelFormat // The pixel format of the destination DIB
);
var
DIB : TDIBSection;
Bytes : Integer;
function AlignBit(Bits, BitsPerPixel, Alignment: Cardinal): Cardinal;
begin
Dec(Alignment);
Result := ((Bits * BitsPerPixel) + Alignment) and not Alignment;
Result := Result SHR 3;
end;
begin
DIB.dsbmih.biSize := 0;
Bytes := GetObject(Bitmap, SizeOf(DIB), @DIB);
if (Bytes = 0) then
raise Exception.Create('Invalid bitmap');
// Error(sInvalidBitmap);
if (Bytes >= (sizeof(DIB.dsbm) + sizeof(DIB.dsbmih))) and
(DIB.dsbmih.biSize >= sizeof(DIB.dsbmih)) then
Info := DIB.dsbmih
else
begin
FillChar(Info, sizeof(Info), 0);
with Info, DIB.dsbm do
begin
biSize := SizeOf(Info);
biWidth := bmWidth;
biHeight := bmHeight;
end;
end;
case PixelFormat of
pf1bit: Info.biBitCount := 1;
pf4bit: Info.biBitCount := 4;
pf8bit: Info.biBitCount := 8;
pf24bit: Info.biBitCount := 24;
else
// Error(sInvalidPixelFormat);
raise Exception.Create('Invalid pixel format');
// Info.biBitCount := DIB.dsbm.bmBitsPixel * DIB.dsbm.bmPlanes;
end;
Info.biPlanes := 1;
Info.biCompression := BI_RGB; // Always return data in RGB format
Info.biSizeImage := AlignBit(Info.biWidth, Info.biBitCount, 32) * Cardinal(abs(Info.biHeight));
end;
procedure TAviWriter.SetWavFileName(value : string);
begin
if lowercase(fWavFileName) <> lowercase(value)
then if lowercase(ExtractFileExt(value)) <> '.wav'
then raise Exception.Create('WavFileName must name a file '
+ 'with the .wav extension')
else fWavFileName := value;
end;
procedure Register;
begin
RegisterComponents('Samples', [TAviWriter]);
end;
end.
Change the import part of the AVISaveV
function to the Unicode version of it. When the function in the Windows API reference has the note Unicode and ANSI names
it means for you, in Delphi, you have to choose either from the Unicode version of the function or from the ANSI one depending on what compiler will you use.
You're trying to call the AVISaveV
, which physically doesn't exists. There's only AVISaveVA
and the AVISaveVW
in avifil32.dll
and since you want to convert this code to Unicode, try to change the function import this way:
function AVISaveV; external 'avifil32.dll' name 'AVISaveVW';
This is just a first thought, the code with the definition like was cannot work even in non Unicode versions of Delphi, because it called the not existing function.
这篇关于如何转换位图视频?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!