程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> .NET實例教程 >> C#將圖像文件壓縮為AVI文件播放

C#將圖像文件壓縮為AVI文件播放

編輯:.NET實例教程

這是接上午那篇來說的,記錄了如何將圖像文件壓縮為一個avi文件的基礎方法。



using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;

namespace org.loon.util
...{
    /**//// <summary>
    /// chenpeng
    /// email:[email protected]
    /// AVIWriter 的摘要說明。
    /// </summary>
    public class AVIWriter
    ...{
        const string AVIFILE32 = "AVIFIL32";
        private int _pfile = 0;
        private IntPtr _ps = new IntPtr(0);
        private IntPtr _psCompressed = new IntPtr(0);
        private UInt32 _frameRate = 0;
        private int _count = 0;
        private UInt32 _width = 0;
        private UInt32 _stride = 0;
        private UInt32 _height = 0;
        //avi標識
        private UInt32 _fccType = 1935960438; // vids
        private UInt32 _fccHandler = 808810089;// IV50
    
        private Bitmap _bmp;

        [DllImport(AVIFILE32)]
        private static extern void AVIFileInit();

        [DllImport(AVIFILE32)]
        private static extern int AVIFileOpenW(ref int ptr_pfile, [MarshalAs(UnmanagedType.LPWStr)]string fileName, int flags, int dummy);

        [DllImport(AVIFILE32)]
        private static extern int AVIFileCreateStream(int ptr_pfile, out IntPtr ptr_ptr_avi, ref AVISTREAMINFOW ptr_streaminfo);
        [DllImport(AVIFILE32)]
        private static extern int AVIMakeCompressedStream(out IntPtr PPSCompressed, IntPtr aviStream, ref AVICOMPRESSOPTIONS ao, int dummy);

        [DllImport(AVIFILE32)]
        private static extern int AVIStreamSetFormat(IntPtr aviStream, Int32 lPos, ref BITMAPINFOHEADER lpFormat, Int32 cbFormat);

        [DllImport(AVIFILE32)]
        unsafe private static extern int AVISaveOptions(int hwnd, UInt32 flags,int nStreams, IntPtr* ptr_ptr_avi, AVICOMPRESSOPTIONS** ao);

        [DllImport(AVIFILE32)]
        private static extern int AVIStreamWrite(IntPtr aviStream, Int32 lStart,Int32 lSamples, IntPtr lpBuffer, Int32 cbBuffer, Int32 dwFlags, Int32 dummy1, Int32 dummy2);

        [DllImport(AVIFILE32)]
        private static extern int AVIStreamRelease(IntPtr aviStream);

        [DllImport(AVIFILE32)]
        private static extern int AVIFileRelease(int pfile);

        [DllImport(AVIFILE32)]
        private static extern void AVIFileExit();

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
            private struct AVISTREAMINFOW
        ...{
            public UInt32 fccType;
            public UInt32 fccHandler;
            public UInt32 dwFlags;
            public UInt32 dwCaps;
            public UInt16 wPriority;
            public UInt16 wLanguage;
            public UInt32 dwScale;
            public UInt32 dwRate;
            public UInt32 dwStart;
            public UInt32 dwLength;
            public UInt32 dwInitialFrames;
            public UInt32 dwSuggestedBufferSize;
            public UInt32 dwQuality;
            public UInt32 dwSampleSize;
            public UInt32 rect_left;
            public UInt32 rect_top;
            public UInt32 rect_right;
            public UInt32 rect_bottom;
            public UInt32 dwEditCount;
            public UInt32 dwFormatChangeCount;
            public UInt16 szName0;
            public UInt16 szName1;
            public UInt16 szName2;
            public UInt16 szName3;
            public UInt16 szName4;
            public UInt16 szName5;
            public UInt16 szName6;
            public UInt16 szName7;
            public UInt16 szName8;
            public UInt16 szName9;
            public UInt16 szName10;
            public UInt16 szName11;
            public UInt16 szName12;
            public UInt16 szName13;
            public UInt16 szName14;
            public UInt16 szName15;
            public UInt16 szName16;
            public UInt16 szName17;
            public UInt16 szName18;
            public UInt16 szName19;
            public UInt16 szName20;
            public UInt16 szName21;
            public UInt16 szName22;
            public UInt16 szName23;
            public UInt16 szName24;
            public UInt16 szName25;
            public UInt16 szName26;
            public UInt16 szName27;
            public UInt16 szName28;
            public UInt16 szName29;
            public UInt16 szName30;
            public UInt16 szName31;
            public UInt16 szName32;
            public UInt16 szName33;
            public UInt16 szName34;
            public UInt16 szName35;
            public UInt16 szName36;
            public UInt16 szName37;
            public UInt16 szName38;
            public UInt16 szName39;
            public UInt16 szName40;
            public UInt16 szName41;
            public UInt16 szName42;
            public UInt16 szName43;
            public UInt16 szName44;
            public UInt16 szName45;
            public UInt16 szName46;
            public UInt16 szName47;
            public UInt16 szName48;
            public UInt16 szName49;
            public UInt16 szName50;
            public UInt16 szName51;
            public UInt16 szName52;
            public UInt16 szName53;
            public UInt16 szName54;
            public UInt16 szName55;
      &    public UInt16 szName56;
            public UInt16 szName57;
            public UInt16 szName58;
            public UInt16 szName59;
            public UInt16 szName60;
            public UInt16 szName61;
            public UInt16 szName62;
            public UInt16 szName63;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
            private struct AVICOMPRESSOPTIONS
        ...{
            public UInt32 fccType;
            public UInt32 fccHandler;
            public UInt32 dwKeyFrameEvery;
    
            public UInt32 dwQuality;
            public UInt32 dwBytesPerSecond;
        
            public UInt32 dwFlags;
            public IntPtr lpFormat;
            public UInt32 cbFormat;
            public IntPtr lpParms;
            public UInt32 cbParms;
            public UInt32 dwInterleaveEvery;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct BITMAPINFOHEADER
        ...{
            public UInt32 biSize;
            public Int32 biWidth;
            public Int32 biHeight;
            public Int16 biPlanes;
            public Int16 biBitCount;
            public UInt32 biCompression;
            public UInt32 biSizeImage;
            public Int32 biXPelsPerMeter;
            public Int32 biYPelsPerMeter;
            public UInt32 biClrUsed;
            public UInt32 biClrImportant;
        }

        public class AvIException : ApplicationException
        ...{
            public AvIException(string s) : base(s) ...{ }
 &n         public AvIException(string s, Int32 hr)
                : base(s)
            ...{

                if (hr == AVIERR_BADPARAM)
                ...{
                    err_msg = "AVIERR_BADPARAM";
                }
                else
                ...{
                    err_msg = "unknown";
                }
            }

            public string ErrMsg()
            ...{
                return err_msg;
            }
            private const Int32 AVIERR_BADPARAM = -2147205018;
            private string err_msg;
        }

        public Bitmap Create(string fileName, UInt32 frameRate, int width, int
            height)
        ...{
            _frameRate = frameRate;
            _width = (UInt32)width;
            _height = (UInt32)height;
            _bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            //鎖定為24位位圖
            BitmapData bmpDat = _bmp.LockBits(new Rectangle(0, 0, width,
                height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            _stride = (UInt32)bmpDat.Stride;
            _bmp.UnlockBits(bmpDat);
            AVIFileInit();
            int hr = AVIFileOpenW(ref _pfile, fileName, 4097, 0);
            if (hr != 0)
            ...{
                throw new AvIException("Create錯誤!");
            }

            CreateStream();
            SetOptions();

            return _bmp;
        }

        public void AddFrame()
        ...{

            BitmapData bmpDat = _bmp.LockBits(
                new Rectangle(0, 0, (int)_width, (int)_height),
                ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);

            int hr = AVIStreamWrite(_psCompressed, _count, 1,
                bmpDat.Scan0, 
                (Int32)(_stride * _height),
                0, 
                0,
                0);

            if (hr != 0)
            ...{
                throw new AvIException("AVIStreamWrite");
            }

            _bmp.UnlockBits(bmpDat);

            _count++;
        }

        public void LoadFrame(Bitmap nextframe)
        ...{

            _bmp = new Bitmap(nextframe);
        }

        public void Close()
        ...{
            AVIStreamRelease(_ps);
            AVIStreamRelease(_psCompressed);

            AVIFileRelease(_pfile);
            AVIFileExit();
        }

        /**//// <summary>
        /// 創建流文件
        /// </summary>
        private void CreateStream()
        ...{
            AVISTREAMINFOW strhdr = new AVISTREAMINFOW();
            strhdr.fccType = _fccType;
            strhdr.fccHandler = _fccHandler;
            strhdr.dwFlags = 0;
            strhdr.dwCaps = 0;
            strhdr.wPriority = 0;
            strhdr.wLanguage = 0;
            strhdr.dwScale = 1;
            strhdr.dwRate = _frameRate; 
            strhdr.dwStart = 0;
            strhdr.dwLength = 0;
            strhdr.dwInitialFrames = 0;
            strhdr.dwSuggestedBufferSize = _height * _stride;
            strhdr.dwQuality = 0xffffffff; 
            strhdr.dwSampleSize = 0;
            strhdr.rect_top = 0;
            strhdr.rect_left = 0;
            strhdr.rect_bottom = _height;
            strhdr.rect_right = _width;
            strhdr.dwEditCount = 0;
            strhdr.dwFormatChangeCount = 0;
      strhdr.szName0 = 0;
            strhdr.szName1 = 0;

            int hr = AVIFileCreateStream(_pfile, out _ps, ref strhdr);

            if (hr != 0)
            ...{
                throw new AvIException("AVIFileCreateStream");
            }
        }

        /**//// <summary>
        /// 設置參數
        /// </summary>
        unsafe private void SetOptions()
        ...{
            AVICOMPRESSOPTIONS opts = new AVICOMPRESSOPTIONS();
            opts.fccType = _fccType;
            opts.fccHandler = 0;
            opts.dwKeyFrameEvery = 0;
            opts.dwQuality = 0; 
            opts.dwFlags = 0; 
            opts.dwBytesPerSecond = 0;
            opts.lpFormat = new IntPtr(0);
            opts.cbFormat = 0;
            opts.lpParms = new IntPtr(0);
            opts.cbParms = 0;
            opts.dwInterleaveEvery = 0;

            AVICOMPRESSOPTIONS* p = &opts;
            AVICOMPRESSOPTIONS** pp = &p;

            IntPtr x = _ps;
            IntPtr* ptr_ps = &x;

            AVISaveOptions(0, 0, 1, ptr_ps, pp);

            int hr = AVIMakeCompressedStream(out _psCompressed, _ps, ref
                opts, 0);
            if (hr != 0)
            ...{
                throw new AvIException("AVIMakeCompressedStream");
            }

            BITMAPINFOHEADER bi = new BITMAPINFOHEADER();
            bi.biSize = 40;
            bi.biWidth = (Int32)_width;
            bi.biHeight = (Int32)_height;
            bi.biPlanes = 1;
            bi.biBitCount = 24;
            bi.biCompression = 0; 
            bi.biSizeImage = _stride * _height;
            bi.biXPelsPerMeter = 0;
            bi.biYPelsPerMeter = 0;
            bi.biClrUsed = 0;
            bi.biClrImportant = 0;

            hr = AVIStreamSetFormat(_psCompressed, 0, ref bi, 40);
            if (hr != 0)
            ...{
                throw new AvIException("AVIStreamSetFormat", hr);
            }
        }
    

    
    };

}

大家可以看到,這個類基本是利用Win32 API得以實現的,下面我來演示一下如何運行此類。

手邊沒有什麼合適的圖,所以用前陣子寫的小軟件漫畫采集助手下了部《羅德斯島戰記》|||……



org.loon.util.FileUtil file=new org.loon.util.FileUtil();
            org.loon.util.AVIWriter aviWriter = new org.loon.util.AVIWriter();
            //ps:avi中所有圖像皆不能小於width及height
            Bitmap avi_frame = aviWriter.Create("d:\mytest.avi",1, 700, 700);
            //獲得指定目錄下文件列表的list
            IList list=file.ListFile("D:\羅德島戰記\羅德島戰記1\");
            foreach(string s in list)
            ...{
                //獲得圖像
                Bitmap cache=new Bitmap("D:\羅德島戰記\羅德島戰記1\"+s);
                //由於轉化為avi後呈現相反,所以翻轉
                cache.RotateFlip(RotateFlipType.Rotate180FlipX);
                //載入圖像
                aviWriter.LoadFrame(cache);
                aviWriter.AddFrame();
            }
            //釋放資源
            aviWriter.Close();
            avi_frame.Dispose();
生成的文件屬性如下,與我們設定的參數相符:



播放畫面如下:




是不是很簡單?實際上,借助於avifile32 api,我們甚至可以改變文件壓縮格式,加入背景音樂,乃至植入病毒(咳,通常我們結合桌面截圖及avi生成還有模擬鍵盤,就可以遠程操作或者監控、記錄電腦操作……)總之,在Windows下操作avi文件是一件再簡單沒有的事情了。

有興趣的話可以這兩篇博文為基礎,將其修改為自己的字幕組工具、屏幕錄像工具、乃至遠程監控工具等。有疑問的話,可以發email到:[email protected]

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved