在Windows系統(tǒng)中,借助于API之利,我們能夠輕易的實(shí)現(xiàn)AVI文件的分解與重組。下面,我給出一個(gè)C#版本的AVI分解示例。 AVI英文全稱為Audio Video Interleaved,即音頻視頻交錯(cuò)格式。它是一種將語音和影像同步組合在一起的文件格式。AVI支持256色和RLE壓縮,主要應(yīng)用在多媒體光盤上,主要用來保存電視、電影等各種影像信息。 using System; using System.Drawing; using System.Runtime.InteropServices; using System.IO; namespace org.loon.util ...{ /**//// <summary> /// org.loon.util.AVIUtil 用于AVI文件處理 /// </summary> public class AVIUtil...{ [StructLayout(LayoutKind.Sequential, Pack = 1)] struct BITMAPFILEHEADER ...{ public ushort bfType; public uint bfSize; public ushort bfReserved1; public ushort bfReserved2; public uint bfOffBits; }
[StructLayout(LayoutKind.Sequential, Pack = 1)] struct BITMAPINFOHEADER ...{ public uint biSize; public int biWidth; public int biHeight; public ushort biPlanes; public ushort biBitCount; public uint biCompression; public uint biSizeImage; public int biXPelsPerMeter; public int biYPelsPerMeter; public uint biClrUsed; public uint biClrImportant; public const int BI_RGB = 0; }
const uint DIB_RGB_COLORS = 0;
const uint DIB_PAL_COLORS = 1;
/**//// <summary> /// 對(duì)象轉(zhuǎn)換 /// </summary> /// <param name="pBITMAPINFOHEADER"></param> /// <returns></returns> public static Bitmap ToBitmap(IntPtr pBITMAPINFOHEADER) ...{ unsafe ...{ BITMAPINFOHEADER* pbmi = (BITMAPINFOHEADER*)pBITMAPINFOHEADER; BITMAPFILEHEADER pbmfi; pbmfi.bfType = (int)’M’ << 8 | (int)’B’; pbmfi.bfOffBits = (uint)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); pbmfi.bfSize = pbmfi.bfOffBits + pbmi->biSizeImage;
MemoryStream stream = new MemoryStream(); BinaryWriter bw = new BinaryWriter(stream); byte[] data = new byte[sizeof(BITMAPFILEHEADER)]; Marshal.Copy((IntPtr)(&pbmfi), data, 0, data.Length); bw.Write(data);
data = new byte[sizeof(BITMAPINFOHEADER)]; Marshal.Copy(pBITMAPINFOHEADER, data, 0, data.Length); bw.Write(data);
data = new byte[pbmi->biSizeImage]; ++pbmi; Marshal.Copy((IntPtr)pbmi, data, 0, data.Length); bw.Write(data); bw.Flush(); bw.BaseStream.Position = 0;
return new Bitmap(bw.BaseStream); } } }
/**//// <summary> /// AviFile,用于AVI文件處理 /// </summary> public class AviFile : IDisposable ...{ const string AVIFILE32 = "AVIFIL32"; const int AVIGETFRAMEF_BESTDISPLAYFMT = 1;
internal enum OpenFileFlags : uint ...{ OF_READ = 0x00000000, OF_WRITE = 0x00000001, OF_READWRITE = 0x00000002, OF_SHARE_COMPAT = 0x00000000, OF_SHARE_EXCLUSIVE = 0x00000010, OF_SHARE_DENY_WRITE = 0x00000020, OF_SHARE_DENY_READ = 0x00000030, OF_SHARE_DENY_NONE = 0x00000040, OF_PARSE = 0x00000100, OF_DELETE = 0x00000200, OF_VERIFY = 0x00000400, OF_CANCEL = 0x00000800, OF_CREATE = 0x00001000, OF_PROMPT = 0x00002000, OF_EXIST = 0x00004000, OF_REOPEN = 0x00008000, }
[DllImport(AVIFILE32)] extern internal static void AVIFileInit();
[DllImport(AVIFILE32)] extern internal static void AVIFileExit();
[DllImport(AVIFILE32)] extern internal static uint AVIFileOpen(out IntPtr ppfile, string szFile, OpenFileFlags mode, IntPtr pclsidHandler);
[DllImport(AVIFILE32)] extern internal static int AVIFileRelease(IntPtr pfile);
[DllImport(AVIFILE32)] extern internal static uint AVIFileGetStream(IntPtr pfile, out IntPtr ppavi, uint fccType, int lParam);
[DllImport(AVIFILE32)] extern internal static int AVIStreamRelease(IntPtr pavi);
[DllImport(AVIFILE32)] extern internal static IntPtr AVIStreamGetFrameOpen(IntPtr pavi, int lpbiWanted);
[DllImport(AVIFILE32)] extern internal static IntPtr AVIStreamGetFrame(IntPtr pgf, int lPos);
[DllImport(AVIFILE32)] extern internal static int AVIStreamLength(IntPtr pavi); [DllImport(AVIFILE32)] extern internal static uint AVIStreamGetFrameClose(IntPtr pget); = static uint mmioFOURCC(char c0, char c1, char c2, char c3) ...{ return (uint)c3 << 24 | (uint)c2 << 16 | (uint)c1 << 8 | (uint)c0; }
static readonly uint streamtypeVIDEO = mmioFOURCC(’v’, ’i’, ’d’, ’s’); static readonly uint streamtypeAUDIO = mmioFOURCC(’a’, ’u’, ’d’, ’s’); static readonly uint streamtypeMIDI = mmioFOURCC(’m’, ’i’, ’d’, ’s’); static readonly uint streamtypeTEXT = mmioFOURCC(’t’, ’x’, ’t’, ’s’);
IntPtr aviFile = IntPtr.Zero; IntPtr aviStream = IntPtr.Zero; bool disposed = false;
public static void Initialize() ...{ AVIFileInit(); }
public static void Terminate() ...{ AVIFileExit(); }
public AviFile(string filename) ...{ uint result; result = AVIFileOpen(out aviFile, filename, OpenFileFlags.OF_READ, IntPtr.Zero); if (result != 0) ...{ Release(); throw new Exception("AVIFileOpen failure."); }
result = AVIFileGetStream(aviFile, out aviStream, streamtypeVIDEO, 0); if (result != 0) ...{ Release(); throw new Exception("AVIFileGetStream failure."); } }
~AviFile() ...{ Dispose(false); }
void Release() ...{ if (aviStream != IntPtr.Zero) ...{ AVIStreamRelease(aviStream); aviStream = IntPtr.Zero; }
if (aviFile != IntPtr.Zero) ...{ AVIFileRelease(aviFile); aviFile = IntPtr.Zero; } }
public int GetMaxFrameCount() ...{ if (aviStream == IntPtr.Zero) throw new InvalidOperationException(); return AVIStreamLength(aviStream); }
public Bitmap GetFrame(int no) ...{ if (aviStream == IntPtr.Zero) throw new InvalidOperationException();
IntPtr frame = IntPtr.Zero; try ...{ frame = AVIStreamGetFrameOpen(aviStream, AVIGETFRAMEF_BESTDISPLAYFMT); IntPtr pbmi = AVIStreamGetFrame(frame, no); return org.loon.util.AVIUtil.ToBitmap(pbmi);
} finally ...{ if (frame != IntPtr.Zero) AVIStreamGetFrameClose(frame); } }
protected void Dispose(bool disposing) ...{ if (disposed) return; disposed = true; Release(); }
public void Dispose() ...{ //不讓垃圾回收器終止指定對(duì)象(即不將指定對(duì)象調(diào)入終止序列中) GC.SuppressFinalize(this); Dispose(true); }
} } 分解AVI: string filename = "d:\test.avi"; //初始化 org.loon.util.AviFile.Initialize();
using (org.loon.util.AviFile avi = new org.loon.util.AviFile(filename)) ...{ int max = avi.GetMaxFrameCount(); for (int i = 0; i < max; ++i) ...{ Bitmap bmp = avi.GetFrame(i); bmp.Save("d:\test\"+i + ".bmp"); bmp.Dispose(); } } //完成 org.loon.util.AviFile.Terminate();
|