BMP合成AVI

5 篇文章 0 订阅

一、准备工作:

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();

三、总结

以上代码已经过测试,并参考了网上的一些代码。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值