protected static void StartCamera(
            int image_width,
            int image_height,
            ref WebcamVisionDirectShowCapture[] cam,
            int[] directshow_filter_index,
            int[] camera_filter_index,
            ref PictureBox[] preview,
            int index,
            float exposure,
            int min_exposure,
            int max_exposure,
            bool auto_exposure,
            bool use_pause)
        {
            cam[index] = new WebcamVisionDirectShowCapture(directshow_filter_index[camera_filter_index[index]], image_width, image_height, preview[index], true);
            if (cam[index] != null)
            {
                if (!cam[index].Active)
                {
                    // if still image capture mode fails
                    // use regular video capture

                    // trash the previous object
                    cam[index].Dispose();

                    // then try again
                    cam[index] = new WebcamVisionDirectShowCapture(directshow_filter_index[camera_filter_index[index]], image_width, image_height, preview[index], false);
                }

                if (cam[index] != null)
                {
                    // set the initial exposure value
                    if (auto_exposure)
                    {
                        cam[index].SetExposureAuto();
                    }
                    else
                    {
                        cam[index].SetExposure(min_exposure + (int)(exposure * (max_exposure - min_exposure) / 100));
                    }

                    if (use_pause)
                    {
                        cam[index].Pause();
                    }
                    else
                    {
                        cam[index].Stop();
                    }
                }
            }
        }
        protected static int[] GetFilterIndexes()
        {
            List <int> filter_indexes = new List <int>();

            string[] filter_names = WebcamVisionDirectShowCapture.GetDeviceNames();
            if (filter_names != null)
            {
                int n = 0;
                for (int i = 0; i < filter_names.Length; i++)
                {
                    if (!filter_names[i].ToLower().Contains("vfw"))
                    {
                        Console.WriteLine(n.ToString() + ". " + filter_names[i]);
                        filter_indexes.Add(i);
                        n++;
                    }
                }
                if (filter_indexes.Count > 0)
                {
                    int[] filter_indexes2 = new int[filter_indexes.Count];
                    for (int i = 0; i < filter_indexes.Count; i++)
                    {
                        filter_indexes2[i] = filter_indexes[i];
                    }
                    return(filter_indexes2);
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// grabs a frame from the camera
        /// </summary>
        protected static void CaptureFrame(
            WebcamVisionDirectShowCapture cam,
            int initial_frames,
            string output_filename,
            string output_format,
            ref IntPtr m_ip,
            int exposure,
            bool use_pause)
        {
            if (cam != null)
            {
                // start rolling the cameras
                if (cam.lastFrame != null)
                {
                    cam.lastFrame.Dispose();
                }

                if (m_ip != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(m_ip);
                    m_ip = IntPtr.Zero;
                }

                cam.Resume();

                // grab frames
                for (int i = 0; i < initial_frames; i++)
                {
                    cam.Grab(ref m_ip, false);

                    if (m_ip != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(m_ip);
                        m_ip = IntPtr.Zero;
                    }
                }
                cam.SetExposure(exposure);
                Bitmap grabbed_image = cam.Grab(ref m_ip, true);
                if (grabbed_image != null)
                {
                    System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Jpeg;
                    output_format = output_format.ToLower();
                    if (output_format == "bmp")
                    {
                        format = System.Drawing.Imaging.ImageFormat.Bmp;
                    }
                    if (output_format == "png")
                    {
                        format = System.Drawing.Imaging.ImageFormat.Png;
                    }
                    if (output_format == "gif")
                    {
                        format = System.Drawing.Imaging.ImageFormat.Gif;
                    }
                    grabbed_image.Save(output_filename + "." + output_format, format);
                }

                // stop the camera
                if (use_pause)
                {
                    cam.Pause();
                }
                else
                {
                    cam.Stop();
                }
            }
        }
        /// <summary>
        /// grabs frames from two cameras
        /// </summary>
        protected static void CaptureFrames(
            int start_camera_index,
            WebcamVisionDirectShowCapture[] cam,
            int initial_frames,
            string output_filename,
            string output_format,
            IntPtr[] m_ip,
            bool save_images,
            int exposure,
            bool use_pause,
            ref string left_image_filename,
            ref string right_image_filename,
            ref Bitmap left_image_bitmap,
            ref Bitmap right_image_bitmap,
            ref DateTime left_image_capture,
            ref DateTime right_image_capture)
        {
            const int step_size = 5; // when checking if frames are blank

            if (left_image_bitmap != null)
            {
                left_image_bitmap.Dispose();
            }
            if (right_image_bitmap != null)
            {
                right_image_bitmap.Dispose();
            }

            if ((cam[start_camera_index] != null) && (cam[start_camera_index + 1] != null))
            {
                /*
                 * if (m_ip[start_camera_index] != IntPtr.Zero)
                 * {
                 *  Marshal.FreeCoTaskMem(m_ip[start_camera_index]);
                 *  m_ip[start_camera_index] = IntPtr.Zero;
                 * }
                 *
                 * if (m_ip[start_camera_index+1] != IntPtr.Zero)
                 * {
                 *  Marshal.FreeCoTaskMem(m_ip[start_camera_index+1]);
                 *  m_ip[start_camera_index+1] = IntPtr.Zero;
                 * }
                 */

                for (int i = 0; i < 2; i++)
                {
                    WebcamVisionDirectShowCapture c = cam[start_camera_index];
                    if (i > 0)
                    {
                        c = cam[start_camera_index + 1];
                    }

                    // start rolling the cameras
                    if (c.lastFrame != null)
                    {
                        c.lastFrame.Dispose();
                    }

                    c.Resume();
                }

                // grab frames
                Bitmap   grabbed_image0  = null;
                Bitmap   grabbed_image1  = null;
                bool     is_blank0       = true;
                bool     is_blank1       = true;
                DateTime left_image_cap  = DateTime.Now;
                DateTime right_image_cap = DateTime.Now;

                //for (int j = 0; j < 2; j++)
                Parallel.For(0, 2, delegate(int j)
                {
                    for (int i = 0; i < initial_frames + 1; i++)
                    {
                        if (j == 0)
                        {
                            left_image_cap = DateTime.Now;
                            cam[start_camera_index].SetExposure(exposure);
                            grabbed_image0 = cam[start_camera_index].Grab(ref m_ip[start_camera_index], true);
                            is_blank0      = IsBlankFrame(grabbed_image0, step_size);
                            if ((!is_blank0) && (i > 1))
                            {
                                break;
                            }
                        }
                        else
                        {
                            right_image_cap = DateTime.Now;
                            cam[start_camera_index + 1].SetExposure(exposure);
                            grabbed_image1 = cam[start_camera_index + 1].Grab(ref m_ip[start_camera_index + 1], true);
                            is_blank1      = IsBlankFrame(grabbed_image1, step_size);
                            if ((!is_blank0) && (i > 1))
                            {
                                break;
                            }
                        }
                    }
                });

                left_image_capture  = left_image_cap;
                right_image_capture = right_image_cap;

                if ((grabbed_image0 != null) &&
                    (grabbed_image1 != null))
                {
                    System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Jpeg;
                    output_format = output_format.ToLower();
                    if (output_format == "bmp")
                    {
                        format = System.Drawing.Imaging.ImageFormat.Bmp;
                    }
                    if (output_format == "png")
                    {
                        format = System.Drawing.Imaging.ImageFormat.Png;
                    }
                    if (output_format == "gif")
                    {
                        format = System.Drawing.Imaging.ImageFormat.Gif;
                    }
                    left_image_bitmap    = grabbed_image0;
                    right_image_bitmap   = grabbed_image1;
                    left_image_filename  = output_filename + "0." + output_format;
                    right_image_filename = output_filename + "1." + output_format;
                    try
                    {
                        if (save_images)
                        {
                            grabbed_image0.Save(left_image_filename, format);
                            grabbed_image1.Save(right_image_filename, format);
                        }
                    }
                    catch
                    {
                        left_image_filename  = "";
                        right_image_filename = "";
                    }
                }

                for (int i = 0; i < 2; i++)
                {
                    WebcamVisionDirectShowCapture c = cam[start_camera_index];
                    if (i > 0)
                    {
                        c = cam[start_camera_index + 1];
                    }

                    // stop the camera
                    if (use_pause)
                    {
                        c.Pause();
                    }
                    else
                    {
                        c.Stop();
                    }
                }
            }
        }
        protected static void StartCamera(
            int image_width,
            int image_height,
            ref WebcamVisionDirectShowCapture[] cam,
            int[] directshow_filter_index,
            int[] camera_filter_index,
            ref PictureBox[] preview,
            int index,
            float exposure,
            int min_exposure,
            int max_exposure,
            bool auto_exposure,
            bool use_pause)
        {
            cam[index] = new WebcamVisionDirectShowCapture(directshow_filter_index[camera_filter_index[index]], image_width, image_height, preview[index], true);
            if (cam[index] != null)
            {
                if (!cam[index].Active)
                {
                    // if still image capture mode fails
                    // use regular video capture

                    // trash the previous object
                    cam[index].Dispose();

                    // then try again
                    cam[index] = new WebcamVisionDirectShowCapture(directshow_filter_index[camera_filter_index[index]], image_width, image_height, preview[index], false);
                }

                if (cam[index] != null)
                {
                    // set the initial exposure value
                    if (auto_exposure)
                        cam[index].SetExposureAuto();
                    else
                        cam[index].SetExposure(min_exposure + (int)(exposure*(max_exposure - min_exposure)/100));

                    if (use_pause)
                        cam[index].Pause();
                    else
                        cam[index].Stop();
                }
            }
        }
        /// <summary>
        /// grabs a frame from the camera
        /// </summary>
        protected static void CaptureFrame(
            WebcamVisionDirectShowCapture cam,
            int initial_frames,
            string output_filename,
            string output_format,
            ref IntPtr m_ip,
            int exposure,
            bool use_pause)
        {
            if (cam != null)
            {
                // start rolling the cameras
                if (cam.lastFrame != null)
                    cam.lastFrame.Dispose();

                if (m_ip != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(m_ip);
                    m_ip = IntPtr.Zero;
                }

                cam.Resume();

                // grab frames                
                for (int i = 0; i < initial_frames; i++)
                {
                    cam.Grab(ref m_ip, false);

                    if (m_ip != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(m_ip);
                        m_ip = IntPtr.Zero;
                    }
                }
                cam.SetExposure(exposure);
                Bitmap grabbed_image = cam.Grab(ref m_ip, true);
                if (grabbed_image != null)
                {
                    System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Jpeg;
                    output_format = output_format.ToLower();
                    if (output_format == "bmp") format = System.Drawing.Imaging.ImageFormat.Bmp;
                    if (output_format == "png") format = System.Drawing.Imaging.ImageFormat.Png;
                    if (output_format == "gif") format = System.Drawing.Imaging.ImageFormat.Gif;
                    grabbed_image.Save(output_filename + "." + output_format, format);
                }

                // stop the camera
                if (use_pause)
                    cam.Pause();
                else
                    cam.Stop();
            }
        }
        /// <summary>
        /// grabs frames from two cameras
        /// </summary>
        protected static void CaptureFrames(
            int start_camera_index,
            WebcamVisionDirectShowCapture[] cam,
            int initial_frames,
            string output_filename,
            string output_format,
            IntPtr[] m_ip,
            bool save_images,
            int exposure,
            bool use_pause,
            ref string left_image_filename,
            ref string right_image_filename,
            ref Bitmap left_image_bitmap,
            ref Bitmap right_image_bitmap,
            ref DateTime left_image_capture,
            ref DateTime right_image_capture)
        {
            const int step_size = 5; // when checking if frames are blank
            if (left_image_bitmap != null) left_image_bitmap.Dispose();
            if (right_image_bitmap != null) right_image_bitmap.Dispose();

            if ((cam[start_camera_index] != null) && (cam[start_camera_index+1] != null))
            {
                /*
                if (m_ip[start_camera_index] != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(m_ip[start_camera_index]);
                    m_ip[start_camera_index] = IntPtr.Zero;
                }

                if (m_ip[start_camera_index+1] != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(m_ip[start_camera_index+1]);
                    m_ip[start_camera_index+1] = IntPtr.Zero;
                }
                */

                for (int i = 0; i < 2; i++)
                {
                    WebcamVisionDirectShowCapture c = cam[start_camera_index];
                    if (i > 0) c = cam[start_camera_index+1];

                    // start rolling the cameras
                    if (c.lastFrame != null)
                        c.lastFrame.Dispose();

                    c.Resume();
                }
                
                // grab frames       
                Bitmap grabbed_image0 = null;
                Bitmap grabbed_image1 = null;
                bool is_blank0 = true;
                bool is_blank1 = true;
                DateTime left_image_cap = DateTime.Now;
                DateTime right_image_cap = DateTime.Now;

                //for (int j = 0; j < 2; j++)                
                Parallel.For(0, 2, delegate(int j)
                {
                    
                    for (int i = 0; i < initial_frames + 1; i++)
                    {

                        if (j == 0)
                        {
                            left_image_cap = DateTime.Now;
                            cam[start_camera_index].SetExposure(exposure);
                            grabbed_image0 = cam[start_camera_index].Grab(ref m_ip[start_camera_index], true);
                            is_blank0 = IsBlankFrame(grabbed_image0, step_size);
                            if ((!is_blank0) && (i > 1)) break;
                        }
                        else
                        {
                            right_image_cap = DateTime.Now;
                            cam[start_camera_index+1].SetExposure(exposure);
                            grabbed_image1 = cam[start_camera_index+1].Grab(ref m_ip[start_camera_index+1], true);
                            is_blank1 = IsBlankFrame(grabbed_image1, step_size);
                            if ((!is_blank0) && (i > 1)) break;
                        }
                    }
                    
                } );                

                left_image_capture = left_image_cap;
                right_image_capture = right_image_cap;
                
                if ((grabbed_image0 != null) &&
                    (grabbed_image1 != null))
                {
                    System.Drawing.Imaging.ImageFormat format = System.Drawing.Imaging.ImageFormat.Jpeg;
                    output_format = output_format.ToLower();
                    if (output_format == "bmp") format = System.Drawing.Imaging.ImageFormat.Bmp;
                    if (output_format == "png") format = System.Drawing.Imaging.ImageFormat.Png;
                    if (output_format == "gif") format = System.Drawing.Imaging.ImageFormat.Gif;
                    left_image_bitmap = grabbed_image0;
                    right_image_bitmap = grabbed_image1; 
                    left_image_filename = output_filename + "0." + output_format;
                    right_image_filename = output_filename + "1." + output_format;
                    try
                    {
                        if (save_images)
                        {
                            grabbed_image0.Save(left_image_filename, format);
                            grabbed_image1.Save(right_image_filename, format);
                        }
                    }
                    catch
                    {
                        left_image_filename = "";
                        right_image_filename = "";
                    }
                }                

                for (int i = 0; i < 2; i++)
                {
                    WebcamVisionDirectShowCapture c = cam[start_camera_index];
                    if (i > 0) c = cam[start_camera_index + 1];

                    // stop the camera
                    if (use_pause)
                        c.Pause();
                    else
                        c.Stop();
                }
            }
        }