Ứng dụng của tôi tạo ra hình ảnh từ những khúc xương và tôi thích cảm giác 'bay' xung quanh một khúc xương. Tôi đã từng lưu khoảng 2000 bitmap để tạo và tạo một AVI từ nó bằng Premiere. Trải nghiệm đó khá thất vọng mặc dù tôi đã thành công trong việc tạo ra một bộ phim. Điều đó thật ngoạn mục. Tất nhiên tôi muốn tạo video từ ứng dụng của mình. Tôi thực sự không quan tâm đến sự tiện lợi của codec, nén hay bất cứ thứ gì. Tôi chỉ muốn có một video mà tôi có thể phát lại trên hầu hết các hệ thống.Làm cách nào để chuyển đổi bitmap thành video?
Trước đây tôi đã thử cách này nhưng chưa bao giờ thành công. Tôi đã được kích hoạt bởi một question gần đây nhưng than ôi không thể chạy FFMpeg.
Cập nhật
tôi quyết định để thích ứng với câu hỏi hơi và đặt một bounty cho nó. Tôi đã thấy một số giải pháp nhưng hấp dẫn nhất (vì nó đơn giản) dường như với tôi TAviWrite. Tôi đã thử TAviWriter nhưng không thành công. Trong thủ tục TAviWriter.Write; gọi hàm quanh dòng 370
AVIERR := AVISaveV(s,
// pchar(FileName),
nil, // File handler
nil, // Callback
nStreams, // Number of streams
Streams,
CompOptions); // Compress options for VideoStream
không trả về AVIERR_OK.
Cập nhật 2
Lý do cho lỗi nêu trên là một lời tuyên bố sai AVISaveV, cần được khai báo là AVISaveVW như TLama chỉ ra. Mã đúng cho việc tạo các tập tin AVI dạng tập tin BMP được đăng dưới đây. Mã ban đầu bên dưới là downloaded from efg với một đơn vị mẫu.
Sử dụng Delphi XE trên 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 [email protected] //
/////////////////////////////////////////////////////////////////////////////
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, [email protected] //
// (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.
Họ đến từ AviFil32, tôi đã thêm tiêu đề vào ví dụ mã. Vì mã này khá cũ nên tôi cho rằng chúng không liên quan đến unicode. Tôi có nên thay thế 'thủ tục AVIFileInit; stdcall; bên ngoài 'avifil32.dll' tên 'AVIFileInit'' bởi' thủ tục AVIFileInit; stdcall; tên 'avifil32.dll' bên ngoài 'AVIFileInitW''? – Arnold
Bạn đã làm gì và AddVideo hoạt động !. Hiện đang cố gắng hiểu những gì xảy ra trong AVIsaveV. Liệu cùng một loại lời khuyên áp dụng cho chức năng đó? – Arnold
Không, chỉ những cái kết thúc bằng 'A' char, nhưng bạn nên xác minh nó theo tham chiếu MSDN. Ví dụ: nếu bạn nhìn vào ['AVIFileOpen'] (http://msdn.microsoft.com/en-us/library/windows/desktop/dd756800%28v=vs.85%29.aspx) thì bạn có thể thấy phần dưới cùng của trang là phần 'Unicode và ANSI' và phần này chỉ có sẵn cho các chức năng có phiên bản ANSI và Unicode. – TLama