一、准备工作:
1、文件定义
#region 文件定义
public static int PALETTE_SIZE = 4 * 256; //RGBQUAD * 256 colours
public static readonly int streamtypeVIDEO = mmioFOURCC('v', 'i', 'd', 's');
public static readonly int streamtypeAUDIO = mmioFOURCC('a', 'u', 'd', 's');
public static readonly int streamtypeMIDI = mmioFOURCC('m', 'i', 'd', 's');
public static readonly int streamtypeTEXT = mmioFOURCC('t', 'x', 't', 's');
public const int OF_SHARE_DENY_WRITE = 32;
public const int OF_WRITE = 1;
public const int OF_READWRITE = 2;
public const int OF_CREATE = 4096;
public const int BMP_MAGIC_COOKIE = 19778; //ascii string "BM"
public const int AVICOMPRESSF_INTERLEAVE = 0x00000001; // interleave
public const int AVICOMPRESSF_DATARATE = 0x00000002; // use a data rate
public const int AVICOMPRESSF_KEYFRAMES = 0x00000004; // use keyframes
public const int AVICOMPRESSF_VALID = 0x00000008; // has valid data
public const int AVIIF_KEYFRAME = 0x00000010;
public const UInt32 ICMF_CHOOSE_KEYFRAME = 0x0001; // show KeyFrame Every box
public const UInt32 ICMF_CHOOSE_DATARATE = 0x0002; // show DataRate box
public const UInt32 ICMF_CHOOSE_PREVIEW = 0x0004; // allow expanded preview dialog
//macro mmioFOURCC
public static Int32 mmioFOURCC(char ch0, char ch1, char ch2, char ch3)
{
return ((Int32)(byte)(ch0) | ((byte)(ch1) << 8) |
((byte)(ch2) << 16) | ((byte)(ch3) << 24));
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RECT
{
public UInt32 left;
public UInt32 top;
public UInt32 right;
public UInt32 bottom;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BITMAPINFOHEADER
{
public Int32 biSize;
public Int32 biWidth;
public Int32 biHeight;
public Int16 biPlanes;
public Int16 biBitCount;
public Int32 biCompression;
public Int32 biSizeImage;
public Int32 biXPelsPerMeter;
public Int32 biYPelsPerMeter;
public Int32 biClrUsed;
public Int32 biClrImportant;
}
[StructLayout(LayoutKind.Sequential)]
public struct PCMWAVEFORMAT
{
public short wFormatTag;
public short nChannels;
public int nSamplesPerSec;
public int nAvgBytesPerSec;
public short nBlockAlign;
public short wBitsPerSample;
public short cbSize;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AVISTREAMINFO
{
public Int32 fccType;
public Int32 fccHandler;
public Int32 dwFlags;
public Int32 dwCaps;
public Int16 wPriority;
public Int16 wLanguage;
public Int32 dwScale;
public Int32 dwRate;
public Int32 dwStart;
public Int32 dwLength;
public Int32 dwInitialFrames;
public Int32 dwSuggestedBufferSize;
public Int32 dwQuality;
public Int32 dwSampleSize;
public RECT rcFrame;
public Int32 dwEditCount;
public Int32 dwFormatChangeCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public UInt16[] szName;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BITMAPFILEHEADER
{
public Int16 bfType; //"magic cookie" - must be "BM"
public Int32 bfSize;
public Int16 bfReserved1;
public Int16 bfReserved2;
public Int32 bfOffBits;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AVIFILEINFO
{
public Int32 dwMaxBytesPerSecond;
public Int32 dwFlags;
public Int32 dwCaps;
public Int32 dwStreams;
public Int32 dwSuggestedBufferSize;
public Int32 dwWidth;
public Int32 dwHeight;
public Int32 dwScale;
public Int32 dwRate;
public Int32 dwLength;
public Int32 dwEditCount;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public char[] szFileType;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AVICOMPRESSOPTIONS
{
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery; // only used with AVICOMRPESSF_KEYFRAMES
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond; // only used with AVICOMPRESSF_DATARATE
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery;
}
/// <summary>AviSaveV needs a pointer to a pointer to an AVICOMPRESSOPTIONS structure</summary>
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class AVICOMPRESSOPTIONS_CLASS
{
public UInt32 fccType;
public UInt32 fccHandler;
public UInt32 dwKeyFrameEvery; // only used with AVICOMRPESSF_KEYFRAMES
public UInt32 dwQuality;
public UInt32 dwBytesPerSecond; // only used with AVICOMPRESSF_DATARATE
public UInt32 dwFlags;
public IntPtr lpFormat;
public UInt32 cbFormat;
public IntPtr lpParms;
public UInt32 cbParms;
public UInt32 dwInterleaveEvery;
public AVICOMPRESSOPTIONS ToStruct()
{
AVICOMPRESSOPTIONS returnVar = new AVICOMPRESSOPTIONS();
returnVar.fccType = this.fccType;
returnVar.fccHandler = this.fccHandler;
returnVar.dwKeyFrameEvery = this.dwKeyFrameEvery;
returnVar.dwQuality = this.dwQuality;
returnVar.dwBytesPerSecond = this.dwBytesPerSecond;
returnVar.dwFlags = this.dwFlags;
returnVar.lpFormat = this.lpFormat;
returnVar.cbFormat = this.cbFormat;
returnVar.lpParms = this.lpParms;
returnVar.cbParms = this.cbParms;
returnVar.dwInterleaveEvery = this.dwInterleaveEvery;
return returnVar;
}
}
#endregion
2、导入动态库函数
#region 导入动态库函数
//Initialize the AVI library
[DllImport("avifil32.dll")]
public static extern void AVIFileInit();
//Open an AVI file
[DllImport("avifil32.dll", PreserveSig = true)]
public static extern int AVIFileOpen(
ref int ppfile,
String szFile,
int uMode,
int pclsidHandler);
//Get a stream from an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileGetStream(
int pfile,
out IntPtr ppavi,
int fccType,
int lParam);
//Get the start position of a stream
[DllImport("avifil32.dll", PreserveSig = true)]
public static extern int AVIStreamStart(int pavi);
//Get the length of a stream in frames
[DllImport("avifil32.dll", PreserveSig = true)]
public static extern int AVIStreamLength(int pavi);
//Get information about an open stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamInfo(
IntPtr pAVIStream,
ref AVISTREAMINFO psi,
int lSize);
//Get a pointer to a GETFRAME object (returns 0 on error)
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrameOpen(
IntPtr pAVIStream,
ref BITMAPINFOHEADER bih);
//Get a pointer to a packed DIB (returns 0 on error)
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrame(
int pGetFrameObj,
int lPos);
//Create a new stream in an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileCreateStream(
int pfile,
out IntPtr ppavi,
ref AVISTREAMINFO ptr_streaminfo);
//Create an editable stream
[DllImport("avifil32.dll")]
public static extern int CreateEditableStream(
ref IntPtr ppsEditable,
IntPtr psSource
);
//Cut samples from an editable stream
[DllImport("avifil32.dll")]
public static extern int EditStreamCut(
IntPtr pStream,
ref Int32 plStart,
ref Int32 plLength,
ref IntPtr ppResult
);
//Copy a part of an editable stream
[DllImport("avifil32.dll")]
public static extern int EditStreamCopy(
IntPtr pStream,
ref Int32 plStart,
ref Int32 plLength,
ref IntPtr ppResult
);
//Paste an editable stream into another editable stream
[DllImport("avifil32.dll")]
public static extern int EditStreamPaste(
IntPtr pStream,
ref Int32 plPos,
ref Int32 plLength,
IntPtr pstream,
Int32 lStart,
Int32 lLength
);
//Change a stream's header values
[DllImport("avifil32.dll")]
public static extern int EditStreamSetInfo(
IntPtr pStream,
ref AVISTREAMINFO lpInfo,
Int32 cbInfo
);
[DllImport("avifil32.dll")]
public static extern int AVIMakeFileFromStreams(
ref IntPtr ppfile,
int nStreams,
ref IntPtr papStreams
);
//Set the format for a new stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamSetFormat(
IntPtr aviStream, Int32 lPos,
ref BITMAPINFOHEADER lpFormat, Int32 cbFormat);
//Set the format for a new stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamSetFormat(
IntPtr aviStream, Int32 lPos,
ref PCMWAVEFORMAT lpFormat, Int32 cbFormat);
//Read the format for a stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamReadFormat(
IntPtr aviStream, Int32 lPos,
ref BITMAPINFOHEADER lpFormat, ref Int32 cbFormat
);
//Read the size of the format for a stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamReadFormat(
IntPtr aviStream, Int32 lPos,
int empty, ref Int32 cbFormat
);
//Read the format for a stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamReadFormat(
IntPtr aviStream, Int32 lPos,
ref PCMWAVEFORMAT lpFormat, ref Int32 cbFormat
);
//Write a sample to a stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamWrite(
IntPtr aviStream, Int32 lStart, Int32 lSamples,
IntPtr lpBuffer, Int32 cbBuffer, Int32 dwFlags,
Int32 dummy1, Int32 dummy2);
//Release the GETFRAME object
[DllImport("avifil32.dll")]
public static extern int AVIStreamGetFrameClose(
int pGetFrameObj);
//Release an open AVI stream
[DllImport("avifil32.dll")]
public static extern int AVIStreamRelease(IntPtr aviStream);
//Release an open AVI file
[DllImport("avifil32.dll")]
public static extern int AVIFileRelease(int pfile);
//Close the AVI library
[DllImport("avifil32.dll")]
public static extern void AVIFileExit();
[DllImport("avifil32.dll")]
public static extern int AVIMakeCompressedStream(
out IntPtr ppsCompressed, IntPtr aviStream,
ref AVICOMPRESSOPTIONS ao, int dummy);
[DllImport("avifil32.dll")]
public static extern bool AVISaveOptions(
IntPtr hwnd,
UInt32 uiFlags,
Int32 nStreams,
ref IntPtr ppavi,
ref AVICOMPRESSOPTIONS_CLASS plpOptions
);
[DllImport("avifil32.dll")]
public static extern long AVISaveOptionsFree(
int nStreams,
ref AVICOMPRESSOPTIONS_CLASS plpOptions
);
[DllImport("avifil32.dll")]
public static extern int AVIFileInfo(
int pfile,
ref AVIFILEINFO pfi,
int lSize);
[DllImport("winmm.dll", EntryPoint = "mmioStringToFOURCCA")]
public static extern int mmioStringToFOURCC(String sz, int uFlags);
[DllImport("avifil32.dll")]
public static extern int AVIStreamRead(
IntPtr pavi,
Int32 lStart,
Int32 lSamples,
IntPtr lpBuffer,
Int32 cbBuffer,
Int32 plBytes,
Int32 plSamples
);
[DllImport("avifil32.dll")]
public static extern int AVISaveV(
String szFile,
Int16 empty,
Int16 lpfnCallback,
Int16 nStreams,
ref IntPtr ppavi,
ref AVICOMPRESSOPTIONS_CLASS plpOptions
);
#endregion
3、方法
#region 方法
private int aviFile = 0;
private IntPtr aviStream;
private uint frameRate;
private int countFrames = 0;
private uint stride;
private int width;
private int height;
private int fccType = mmioStringToFOURCC("vids", 0);
private int fccHandler = mmioStringToFOURCC("CVID", 0);
//Create an empty AVI file
private void Open(string fileName, UInt32 frameRate)
{
this.frameRate = frameRate;
AVIFileInit();
int hr = AVIFileOpen(
ref aviFile, fileName,
OF_WRITE | OF_CREATE, 0);
}
//Add a sample to the stream - for first sample: create the stream
private void AddFrame(Bitmap bmp)
{
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData bmpDat = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
//this is the first frame - get size and create a new stream
if (this.countFrames == 0)
{
this.stride = (uint)bmpDat.Stride;
this.width = bmp.Width;
this.height = bmp.Height;
CreateStream(); //a method to create a new video stream
}
//add the bitmap to the stream
int result = AVIStreamWrite(aviStream,
countFrames, 1,
bmpDat.Scan0, //pointer to the beginning of the image data
(Int32)(stride * height),
0, 0, 0);
bmp.UnlockBits(bmpDat);
this.countFrames++;
}
//Create a new video stream
private void CreateStream()
{
//describe the stream to create
AVISTREAMINFO strhdr = new AVISTREAMINFO();
strhdr.fccType = this.fccType; //mmioStringToFOURCC("vids", 0)
strhdr.fccHandler = this.fccHandler; //"Microsoft Video 1"
strhdr.dwScale = 1;
strhdr.dwRate = (int)frameRate;
strhdr.dwSuggestedBufferSize = (int)(height * stride);
//use highest quality! Compression destroys the hidden message.
strhdr.dwQuality = 10000;
strhdr.rcFrame.top = 0;
strhdr.rcFrame.bottom = (UInt32)height;
strhdr.rcFrame.right = (UInt32)width;
strhdr.szName = new UInt16[64];
//create the stream
int result = AVIFileCreateStream(aviFile, out aviStream, ref strhdr);
//define the image format
BITMAPINFOHEADER bi = new BITMAPINFOHEADER();
bi.biSize = Marshal.SizeOf(bi);
bi.biWidth = (Int32)width;
bi.biHeight = (Int32)height;
bi.biCompression = 0; // BI_RGB
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biSizeImage = 0/*(Int32)this.stride * this.height*/;
//format the stream
result = AVIStreamSetFormat(aviStream, 0, ref bi, Marshal.SizeOf(bi));
}
#endregion
二、步骤:
1、创建并打开一个空的AVI文件:
Open(strAviPathName, frameRate);
for (int i = m_nStart; i <= m_nEnd; i++)
{
Bitmap bmp = new Bitmap(m_listShowImage[i]);
AddFrame(bmp);
}
AVIStreamRelease(aviStream);
AVIFileRelease(aviFile);
AVIFileExit();
三、总结
以上代码已经过测试,并参考了网上的一些代码。