Dailycode.info

Short solution for short problems

DirectShow, how to adjust properties of a Webcam

I chose to use the DirectShow library of 2005 to handle a wabcam programatically. This was not so difficult. In a previous post I explained how to take a picture from a webcam using directshow. This worked fine for me, untill there was the need to adjust brightness, contrast etc... I spent 1 day looking for the solution, but couldn't find it. I decided to ask God for a solution, and when He took control over my fingers, the desired google result came up! At the bottom of this page you will find the help I needed.

For now I can post some code on how to change the properties of the webcam programatically, I will do some more work on this and I will keep this post updated on the progress. 

 

        public void SetupProperties(int iDeviceNum, int brightness, int contrast, 
          int backlightcompensation, int sharpness)
        {
            DsDevice[] capDevices;
            // Get the collection of video devices
            capDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
            DsDevice dev = capDevices[iDeviceNum];
            // Set up the capture graph
            SetupProperties(dev, brightness, contrast, backlightcompensation, sharpness);
        }
 
        private void SetupProperties(DsDevice dev, int brightness, int contrast, 
          int backlightcompensation, int sharpness)
        {
            object o;
            Guid IID_IBaseFilter = new Guid("56a86895-0ad4-11ce-b03a-0020af0ba770");
            dev.Mon.BindToObject(null, null, ref IID_IBaseFilter, out o);
            IAMVideoProcAmp vpa = (IAMVideoProcAmp)o;
 
            int pMin, pMax, pSteppingDelta, pDefault;
            int pMin2, pMax2, pSteppingDelta2, pDefault2;
            int pMin3, pMax3, pSteppingDelta3, pDefault3;
            int pMin4, pMax4, pSteppingDelta4, pDefault4;
            VideoProcAmpFlags pFlags, pFlags2, pFlags3, pFlags4;
 
            vpa.GetRange(
            VideoProcAmpProperty.Brightness,
            out pMin,
            out pMax,
            out pSteppingDelta,
            out pDefault,
            out pFlags);
 
            vpa.GetRange(
            VideoProcAmpProperty.Sharpness,
            out pMin2,
            out pMax2,
            out pSteppingDelta2,
            out pDefault2,
            out pFlags2);
 
            vpa.GetRange(
            VideoProcAmpProperty.BacklightCompensation,
            out pMin3,
            out pMax3,
            out pSteppingDelta3,
            out pDefault3,
            out pFlags3);
 
            vpa.GetRange(
            VideoProcAmpProperty.Contrast,
            out pMin4,
            out pMax4,
            out pSteppingDelta4,
            out pDefault4,
            out pFlags4);
 
            if (brightness >= pMin && brightness <= pMax)
            {
                vpa.Set(VideoProcAmpProperty.Brightness, brightness, pFlags);
            }
            if (sharpness >= pMin2 && sharpness <= pMax2)
            {
                vpa.Set(VideoProcAmpProperty.Sharpness, sharpness, pFlags2);
            }
            if (backlightcompensation >= pMin3 && backlightcompensation <= pMax3)
            {
                vpa.Set(VideoProcAmpProperty.BacklightCompensation, backlightcompensation, pFlags3);
            }
            if (contrast >= pMin4 && contrast <= pMin4)
            {
                vpa.Set(VideoProcAmpProperty.Contrast, contrast, pFlags4);
            }
            //dev.Dispose();
        } 

You will be able to adjust all the properties of the video input device that you are capable to adjust manually as in following image:

Here again the list off all the properties:

VideoProcAmpProperty.BacklightCompensation;
VideoProcAmpProperty.Brightness;
VideoProcAmpProperty.ColorEnable;
VideoProcAmpProperty.Contrast;
VideoProcAmpProperty.Gain;
VideoProcAmpProperty.Gamma;
VideoProcAmpProperty.Hue;
VideoProcAmpProperty.Saturation;
VideoProcAmpProperty.Sharpness;
VideoProcAmpProperty.WhiteBalance;

 

When you perform this operation:

vpa.GetRange(
VideoProcAmpProperty.BacklightCompensation,
out pMin,
out pMax,
out pSteppingDelta,
out pDefault,
out pFlags3);
 

you can find out the min and max value you can assing to this property, the default value and the steps. This is usefull to prevent you from entering values who are out of range. 

The function SetupProperties I added to the class Caputer.cs. This class also has a method for taking a picture from the webcam. Here's the function:

/// <summary>
        /// Get the image from the Still pin.  The returned image can turned into a bitmap with
        /// Bitmap b = new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);
        /// If the image is upside down, you can fix it with
        /// b.RotateFlip(RotateFlipType.RotateNoneFlipY);
        /// </summary>
        /// <returns>Returned pointer to be freed by caller with Marshal.FreeCoTaskMem</returns>
        public IntPtr Click()
        {
            int hr;
 
            // get ready to wait for new image
            m_PictureReady.Reset();
            m_ipBuffer = Marshal.AllocCoTaskMem(Math.Abs(m_stride) * m_videoHeight);
 
            try
            {
                m_WantOne = true;
 
                // If we are using a still pin, ask for a picture
                if (m_VidControl != null)
                {
                    // Tell the camera to send an image
                    hr = m_VidControl.SetMode(m_pinStill, VideoControlFlags.Trigger);
                    DsError.ThrowExceptionForHR(hr);
                }
 
                // Start waiting
                if (!m_PictureReady.WaitOne(9000, false))
                {
                    throw new Exception("Timeout waiting to get picture");
                }
            }
            catch
            {
                Marshal.FreeCoTaskMem(m_ipBuffer);
                m_ipBuffer = IntPtr.Zero;
                throw;
            }
 
            // Got one
            return m_ipBuffer;
        }
 
        public int Width
        {
            get
            {
                return m_videoWidth;
            }
        }
        public int Height
        {
            get
            {
                return m_videoHeight;
            }
        }
        public int Stride
        {
            get
            {
                return m_stride;
            }
        }
 

This funtion return a Bitmap. very easy implementation. Feel free to ask for the source, I can provide the Capture class and all non work related source. If I complete the project and I have some spare time, I will create a demo project.

The project download is not available anymore.