视频文件(avi)截取为Bitmap文件

1.首先要引入DirectShowLib-2005.dll库

2.将工程的「Allow unsafe code」选上。

 

/// <summary>
 /// Retrieves individual frames from a video file and returns them as bitmaps.
 /// </summary>
    public class FrameGrabber
    {
        // underlying variables for properties
        private string fileName;
        private int frameCount;
        private double frameRate;
        private int height;

        // private variables
        private IMediaDet mediaDet;
        private double mediaLength;
        private VideoInfoHeader videoInfo;
        private int width;

        /// <summary>
        /// Creates a FrameGrabber based on the specified video file.
        /// </summary>
        public FrameGrabber(string fileName)
        {
            FileName = fileName;
        }


        /// <summary>
        /// Creates a FrameGrabber with no video file set.  Set FileName before calling other methods.
        /// </summary>
        public FrameGrabber()
            : this("")
        {
            // nothing to do here
        }

        /// <summary>
        ///  Gets or sets the full path of the video file from which to grab frames.
        /// </summary>
        public string FileName
        {
            get
            {
                return fileName;
            }

            set
            {
                mediaDet = null;
                fileName = value;

                if (File.Exists(fileName))
                {
                    AMMediaType mediaType = null;

                    try
                    {
                        mediaDet = (IMediaDet)new MediaDet();
                        DsError.ThrowExceptionForHR(mediaDet.put_Filename(fileName));

                        // find the video stream in the file
                        int index = 0;
                        Guid type = Guid.Empty;
                        while (type != MediaType.Video)
                        {
                            mediaDet.put_CurrentStream(index++);
                            mediaDet.get_StreamType(out type);
                        }

                        // retrieve some measurements from the video
                        mediaDet.get_FrameRate(out frameRate);

                        mediaType = new AMMediaType();
                        mediaDet.get_StreamMediaType(mediaType);
                        videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.formatPtr, typeof(VideoInfoHeader));
                        DsUtils.FreeAMMediaType(mediaType);
                        mediaType = null;
                        width = videoInfo.BmiHeader.Width;
                        height = videoInfo.BmiHeader.Height;

                        mediaDet.get_StreamLength(out mediaLength);
                        frameCount = (int)(frameRate * mediaLength);
                    }
                    catch (Exception e)
                    {
                        if (mediaType != null)
                        {
                            DsUtils.FreeAMMediaType(mediaType);
                        }

                        fileName = "";

                        throw new ArgumentException(String.Format("unable to open the file \"{0}\", DirectShow reported the following error: {1}", value, e.Message));
                    }
                }
            }
        }

        /// <summary>
        /// Gets the total number of frames in the video file.
        /// </summary>
        public int FrameCount
        {
            get
            {
                return frameCount;
            }
        }

        /// <summary>
        /// Gets the framerate of the video file.  Some videos always report "0" regardless of their actual value.
        /// </summary>
        public double FrameRate
        {
            get
            {
                return frameRate;
            }
        }

        /// <summary>
        /// Gets the horizontal dimension of the video file in pixels.
        /// </summary>
        public int Width
        {
            get
            {
                return width;
            }
        }

        /// <summary>
        /// Gets the vertical dimension of the video file in pixels.  
        /// </summary>
        public int Height
        {
            get
            {
                return height;
            }
        }

        /// <summary>
        /// Gets the duration of the video file in seconds.
        /// </summary>
        public double MediaLength
        {
            get
            {
                return mediaLength;
            }
        }

        /// <summary>
        /// Gets the bit depth of the captured frame (always 24 bpp RGB).
        /// </summary>
        public PixelFormat PixelFormat
        {
            get
            {
                return PixelFormat.Format24bppRgb;
            }
        }

        /// <summary>
        /// Gets the image at the specified time.  Equivalent to calling "GetImageAtTime()".
        /// </summary>
        public Bitmap this[double seconds]
        {
            get
            {
                return GetImageAtTime(seconds);
            }
        }

        /// <summary>
        /// Gets the specified frame.  Equivalent to calling "GetImage()".
        /// </summary>
        public Bitmap this[int frame]
        {
            get
            {
                return GetImage(frame);
            }
        }

        /// <summary>
        /// Converts the frame number to seconds.
        /// </summary>
        public double ConvertFrameNumberToSeconds(int frameNumber)
        {
            return (frameNumber / frameRate);
        }

        /// <summary>
        /// Converts the seconds to frame number.
        /// </summary>
        public int ConvertSecondsToFrameNumber(double seconds)
        {
            return (int)Math.Floor(seconds * frameRate);
        }

        /// <summary>
        /// Gets the image of the specified frame.  Frames are indexed starting at 0 and go through (FrameCount - 1).
        /// </summary>
        public Bitmap GetImage(int frameNumber)
        {
            if (frameNumber < frameCount)
            {
                return GetImageAtTime(ConvertFrameNumberToSeconds(frameNumber));
            }
            else
            {
                throw new ArgumentException(String.Format("frameNumber must be between 0 and {0} inclusive, value was \"{1}\"", frameCount - 1, frameNumber));
            }
        }

        /// <summary>
        /// Gets the image at the specified time.  Seconds must be less than or equal to MediaLength.
        /// All other image and frame accessors call this method.
        /// </summary>
        public Bitmap GetImageAtTime(double seconds)
        {
            seconds += 1 / (frameRate * 2);
            if (seconds <= mediaLength)
            {
                if (mediaDet != null)
                {
                    IntPtr bufferPtr = IntPtr.Zero;
                    Bitmap returnValue = null;

                    try
                    {
                        // create a buffer to hold the image data from the MediaDet
                        int bufferSize;
                        mediaDet.GetBitmapBits(seconds, out bufferSize, IntPtr.Zero, width, height);
                        bufferPtr = Marshal.AllocHGlobal(bufferSize);
                        mediaDet.GetBitmapBits(seconds, out bufferSize, bufferPtr, width, height);

                        // compose a bitmap from the data in the managed buffer 
                        unsafe
                        {
                            returnValue = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                            BitmapData imageData = returnValue.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                            int* imagePtr = (int*)imageData.Scan0;

                            int bitmapHeaderSize = Marshal.SizeOf(videoInfo.BmiHeader);
                            int* sourcePtr = (int*)((byte*)bufferPtr.ToPointer() + bitmapHeaderSize);

                            for (int i = 0; i < (bufferSize - bitmapHeaderSize) / 4; i++)
                            {
                                *imagePtr = *sourcePtr;
                                imagePtr++;
                                sourcePtr++;
                            }

                            returnValue.UnlockBits(imageData);
                            returnValue.RotateFlip(RotateFlipType.Rotate180FlipX); // DirectShow stores pixels in a different order than Bitmaps do
                        }

                        Marshal.FreeHGlobal(bufferPtr);

                        return returnValue;
                    }
                    catch
                    {
                        if (bufferPtr != IntPtr.Zero)
                        {
                            Marshal.FreeHGlobal(bufferPtr);
                        }

                        if (returnValue != null)
                        {
                            returnValue.Dispose();
                        }

                        throw;
                    }
                }
                else
                {
                    throw new InvalidOperationException("cannot retrieve the frame because the FileName property has not been set yet");
                }
            }
            else
            {
                throw new ArgumentException(String.Format("seconds must be between 0 and {0} inclusive, value was \"{1}\"", mediaLength, seconds));
            }
        }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值