Share via


How do i use attached webcams to take still image in my application

Question

Tuesday, December 17, 2013 2:26 PM

Hi all,

Please i'm developing a biometric enrollment app with VS2010 VB.NET and I need to use detachable webcams and finger print scanner to take still images and scan finger prints into be saved in my sql server.

Now my problem is that I've not been able to connect to the attached webcam to take the photos. The code samples I've tried have not been able to detect the attached webcam, its only my laptop webcam it detects and works. I'm currently using a Logitech C210 webcam. Please help.

It may seem that my question might have an answer among similar threads, however I've searched through a lot of threads an haven't gotten a solution to my problem.

Kayman

All replies (20)

Monday, December 23, 2013 12:50 PM ✅Answered | 4 votes

Hi,

 I have made a class that you can add to any project and use it to capture images from a webcam using DirectShow. The first thing you need to do is download the latest DirectShow library from SourceForge.net and unzip it somewhere handy. Then you can start a new Form Project and add a class by going to the VB menu and clicking (Project) and then (Add Class...) and name it (DSCamCapture.vb). Now copy the DSCamCapture class code from below. After that you will need to add a reference to the DirectShow.dll file in the folder you downloaded from SourceForge. You can do that by going to the VB menu and clicking (Project) and then (Add Reference...). When the window opens click the (Browse) tab and browse to the (DirectShow.dll) file or the latest is named (DirectShowLib-2005.dll) and select it. That takes care of adding the class and references that are needed.

Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Diagnostics

Imports DirectShowLib 'You must add a reference to the newest DirectShowLib.dll file if this line has an error

Public Class DSCamCapture
    Implements ISampleGrabberCB
    Implements IDisposable

    Private WithEvents TmrCaptured As New Timer With {.Interval = 10}
    Private WithEvents TmrSaved As New Timer With {.Interval = 10}
    Public Event FrameCaptured(ByVal capImage As Bitmap)
    Public Event FrameSaved(ByVal capImage As Bitmap, ByVal imgPath As String)

    Private m_graphBuilder As IFilterGraph4 = Nothing
    Private m_mediaCtrl As IMediaControl = Nothing
    Private sampGrabber As ISampleGrabber = Nothing

    Private mediaEventEx As IMediaEventEx = Nothing
    Private videoWindow As IVideoWindow = Nothing
    Private Const WM_APP As Integer = &H8000
    Private Const WM_GRAPHNOTIFY As Integer = (WM_APP + 1)

    Private capturedPic As Bitmap = Nothing
    Private parentHandle As IntPtr = IntPtr.Zero
    Private saveImage As Boolean = False
    Private getImage As Boolean = False
    Private ImagePathName As String = ""
    Private ImgFormat As Imaging.ImageFormat = Nothing

    Private unsupportedVideo As Boolean
    Private m_videoWidth As Integer
    Private m_videoHeight As Integer
    Private m_stride As Integer

    Private Running As Boolean = False
    Private Connected As Boolean = False

#If DEBUG Then
    Private m_rot As DsROTEntry = Nothing
#End If

    ''' <summary>
    ''' Indicates if this instance is currently connected to a device.
    ''' </summary>
    Public ReadOnly Property IsConnected() As Boolean
        Get
            Return Connected
        End Get
    End Property

    ''' <summary>
    ''' Indicates if the capture graph is running or paused/stoped.
    ''' </summary>
    Public ReadOnly Property IsRunning() As Boolean
        Get
            Return Running
        End Get
    End Property

    ''' <summary>
    ''' Enum of common video frame sizes. Used to set the (frameSize) parameter of the (ConnectToDevice) function.
    ''' </summary>
    Public Enum FrameSizes As Integer
        s160x120 = 0
        s176x144 = 1
        s320x240 = 2
        s352x288 = 3
        s640x480 = 4
    End Enum

    ''' <summary>
    ''' Connects this instance of the Capture class to the specified capture device index.
    ''' </summary>
    ''' <param name="deviceIndex">The Zero Based Index Of Capture Device To Connect To.</param>
    ''' <param name="frameRate">The Capture Rate. Equivilant to FPS.</param>
    ''' <param name="windowSize">The size of the visible video window.</param>
    ''' <param name="frameSize">The size used for the video frames. This will also be the size images are saved as.</param>
    ''' <param name="hParent">A Handle To The Parent Window.</param>
    Public Function ConnectToDevice(ByVal deviceIndex As Integer, ByVal frameRate As Integer, ByVal windowSize As Size, ByVal frameSize As FrameSizes, ByVal hParent As IntPtr) As Boolean
        parentHandle = hParent

        ' Get the collection of video devices
        Dim capDevices As DsDevice() = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)

        If (deviceIndex + 1 > capDevices.Length) Then Throw New Exception("No video capture devices found at that index!")

        Dim dev As DsDevice = capDevices(deviceIndex)

        Dim iSize As New Size(CInt(frameSize.ToString.Substring(1, 3)), CInt(frameSize.ToString.Substring(5, 3)))

        Try
            SetupGraph(dev, frameRate, windowSize, iSize)
        Catch
            Dispose()
            If unsupportedVideo Then
                MessageBox.Show("The (imageSize) resolution isn't supported by the camera.")
            Else
                MessageBox.Show("An unknown error happened when connecting to the camera.")
            End If
            Return False
        End Try

        Connected = True
        Return True
    End Function

    ''' <summary>
    ''' Used to resize and/or change the location of the visible video window.
    ''' </summary>
    ''' <param name="xLoc">The new X location.</param>
    ''' <param name="yLoc">The new Y location.</param>
    ''' <param name="sWidth">The new Width of the window.</param>
    ''' <param name="sHeight">The new Height of the window.</param>
    ''' <remarks></remarks>
    Public Sub ResizeWindow(ByVal xLoc As Integer, ByVal yLoc As Integer, ByVal sWidth As Integer, ByVal sHeight As Integer)
        If Not parentHandle.Equals(IntPtr.Zero) Then
            Dim hr As Integer
            hr = videoWindow.SetWindowPosition(xLoc, yLoc, sWidth, sHeight)
            DsError.ThrowExceptionForHR(hr)
        End If
    End Sub

    ''' <summary>
    ''' Returns a string array containing all video capture device names in the device index order that are currently available.
    ''' </summary>
    Public Function GetCaptureDevices() As String()
        Dim capDevices As DsDevice() = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
        Dim dvcList As New List(Of String)
        For Each cd As DsDevice In capDevices
            dvcList.Add(cd.Name)
        Next
        Return dvcList.ToArray
    End Function

    ' <summary> 
    ' Disconnects from any devices and clears all resources.
    ' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        CloseInterfaces()
    End Sub

    Protected Overloads Overrides Sub finalize()
        CloseInterfaces()
    End Sub

    ''' <summary>
    ''' Starts the capture graph.
    ''' </summary>
    Public Sub Start()
        If Not Running And Connected Then
            Dim hr As Integer = m_mediaCtrl.Run()
            DsError.ThrowExceptionForHR(hr)
            Running = True
        End If
    End Sub

    ''' <summary>
    ''' Pauses the capture graph. Running the graph takes up a lot of resources. (Pause) it when it isn't needed at the time and (Start) it when needed again.
    ''' </summary>
    Public Sub Pause()
        If Running And Connected Then
            Dim hr As Integer = m_mediaCtrl.Pause()
            DsError.ThrowExceptionForHR(hr)
            Running = False
        End If
    End Sub

    ''' <summary>
    ''' Saves an image file of the current video frame and passes the captured image to the (capImage) parameter in the (FrameSaved) event.
    ''' </summary>
    ''' <param name="strFileName">The full path, name, and extension to save the image as.</param>
    ''' <param name="iFormat">The image format for saving the file. Make sure the file extension matches.</param>
    Public Sub SaveCurrentFrame(ByVal strFileName As String, ByVal iFormat As Imaging.ImageFormat)
        ImagePathName = strFileName
        ImgFormat = iFormat
        saveImage = True
        TmrSaved.Start()
    End Sub

    'Used to save the image and trigger the FrameSaved event to notify the owner application the image was saved.
    Private Sub Tmr2_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TmrSaved.Tick
        If Not saveImage Then
            TmrSaved.Stop()
            capturedPic.Save(ImagePathName, ImgFormat)
            RaiseEvent FrameSaved(capturedPic, ImagePathName)
        End If
    End Sub

    ''' <summary>
    ''' Gets the current video frame and passes the captured image as the (capImage) parameter in the (FrameCaptured) event.
    ''' </summary>
    Public Sub GetCurrentFrame()
        getImage = True
        TmrCaptured.Start()
    End Sub

    'Used to raise the (FrameCaptured) event to notify the owner application the image is ready and pass the image.
    Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TmrCaptured.Tick
        If Not getImage Then
            TmrCaptured.Stop()
            RaiseEvent FrameCaptured(capturedPic)
        End If
    End Sub

    Private Sub SetupGraph(ByVal dev As DsDevice, ByVal iFrameRate As Integer, ByVal winSize As Size, ByVal imgSize As Size)
        Dim hr As Integer
        Dim baseGrabFlt As IBaseFilter = Nothing
        Dim capFilter As IBaseFilter = Nothing
        Dim capGraph As ICaptureGraphBuilder2 = Nothing

        m_graphBuilder = DirectCast(New FilterGraph(), IFilterGraph4)
        m_mediaCtrl = DirectCast(m_graphBuilder, IMediaControl)
        mediaEventEx = DirectCast(m_graphBuilder, IMediaEventEx)
        videoWindow = DirectCast(m_graphBuilder, IVideoWindow)

#If DEBUG Then
        m_rot = New DsROTEntry(m_graphBuilder)
#End If

        Try
            capGraph = DirectCast(New CaptureGraphBuilder2(), ICaptureGraphBuilder2)
            sampGrabber = DirectCast(New SampleGrabber(), ISampleGrabber)

            hr = capGraph.SetFiltergraph(DirectCast(m_graphBuilder, IGraphBuilder))
            DsError.ThrowExceptionForHR(hr)

            hr = m_graphBuilder.AddSourceFilterForMoniker(dev.Mon, Nothing, dev.Name, capFilter)
            DsError.ThrowExceptionForHR(hr)

            baseGrabFlt = DirectCast(sampGrabber, IBaseFilter)
            ConfigureSampleGrabber(sampGrabber)

            hr = m_graphBuilder.AddFilter(baseGrabFlt, "DShow Capture")
            DsError.ThrowExceptionForHR(hr)

            SetConfigParms(capGraph, capFilter, iFrameRate, imgSize.Width, imgSize.Height)

            hr = capGraph.RenderStream(PinCategory.Capture, MediaType.Video, capFilter, baseGrabFlt, Nothing)
            DsError.ThrowExceptionForHR(hr)

            hr = mediaEventEx.SetNotifyWindow(parentHandle, WM_GRAPHNOTIFY, IntPtr.Zero)
            DsError.ThrowExceptionForHR(hr)

            hr = videoWindow.put_Owner(parentHandle)
            DsError.ThrowExceptionForHR(hr)

            hr = videoWindow.SetWindowPosition(0, 0, winSize.Width, winSize.Height)
            DsError.ThrowExceptionForHR(hr)

            hr = videoWindow.put_WindowStyle(WindowStyle.Child)
            DsError.ThrowExceptionForHR(hr)

            SaveSizeInfo(sampGrabber)

        Finally

            If (Not capFilter Is Nothing) Then
                Marshal.ReleaseComObject(capFilter)
                capFilter = Nothing
            End If
            If (Not sampGrabber Is Nothing) Then
                Marshal.ReleaseComObject(sampGrabber)
                sampGrabber = Nothing
            End If
        End Try
    End Sub

    Private Sub SaveSizeInfo(ByVal sampGrabber As ISampleGrabber)
        Dim hr As Integer
        Dim media As AMMediaType = New AMMediaType()
        hr = sampGrabber.GetConnectedMediaType(media)
        DsError.ThrowExceptionForHR(hr)

        If (Not (media.formatType.Equals(FormatType.VideoInfo)) AndAlso Not (media.formatPtr.Equals(IntPtr.Zero))) Then
            Throw New NotSupportedException("Unknown Media Format")
        End If

        Dim vInfoHeader As VideoInfoHeader = New VideoInfoHeader()
        Marshal.PtrToStructure(media.formatPtr, vInfoHeader)
        m_videoWidth = vInfoHeader.BmiHeader.Width
        m_videoHeight = vInfoHeader.BmiHeader.Height
        m_stride = CInt(m_videoWidth * (vInfoHeader.BmiHeader.BitCount / 8))

        DsUtils.FreeAMMediaType(media)
        media = Nothing
    End Sub

    Private Sub ConfigureSampleGrabber(ByVal sampGrabber As ISampleGrabber)
        Dim hr As Integer
        Dim media As AMMediaType = New AMMediaType()

        media.majorType = MediaType.Video
        media.subType = MediaSubType.RGB24
        media.formatType = FormatType.VideoInfo

        hr = sampGrabber.SetMediaType(media)
        DsError.ThrowExceptionForHR(hr)

        DsUtils.FreeAMMediaType(media)
        media = Nothing

        hr = sampGrabber.SetOneShot(False)
        DsError.ThrowExceptionForHR(hr)

        hr = sampGrabber.SetCallback(Me, 0)
        DsError.ThrowExceptionForHR(hr)

        sampGrabber.SetBufferSamples(False)
    End Sub

    Private Sub SetConfigParms(ByVal capGraph As ICaptureGraphBuilder2, ByVal capFilter As IBaseFilter, ByVal iFrameRate As Integer, ByVal iWidth As Integer, ByVal iHeight As Integer)
        Dim hr As Integer
        Dim obj As Object = Nothing
        Dim media As AMMediaType = Nothing
        Dim videoStreamConfig As IAMStreamConfig
        Dim videoControl As IAMVideoControl = DirectCast(capFilter, IAMVideoControl)

        hr = capGraph.FindInterface(PinCategory.Capture, MediaType.Video, capFilter, GetType(IAMStreamConfig).GUID, obj)

        videoStreamConfig = DirectCast(obj, IAMStreamConfig)

        Try
            If (videoStreamConfig Is Nothing) Then Throw New Exception("Failed to get IAMStreamConfig")

            hr = videoStreamConfig.GetFormat(media)
            DsError.ThrowExceptionForHR(hr)

            Dim vih As VideoInfoHeader = New VideoInfoHeader()
            Marshal.PtrToStructure(media.formatPtr, vih)

            vih.AvgTimePerFrame = CLng(10000000 / iFrameRate)
            vih.BmiHeader.Width = iWidth
            vih.BmiHeader.Height = iHeight

            Marshal.StructureToPtr(vih, media.formatPtr, False)

            hr = videoStreamConfig.SetFormat(media)
            If hr <> 0 Then unsupportedVideo = True Else unsupportedVideo = False
            DsError.ThrowExceptionForHR(hr)

            DsUtils.FreeAMMediaType(media)
            media = Nothing
        Finally
            Marshal.ReleaseComObject(videoStreamConfig)
        End Try
    End Sub

    Private Sub CloseInterfaces()
        Dim hr As Integer
        Try
            If m_mediaCtrl IsNot Nothing Then

                hr = m_mediaCtrl.Stop()
                m_mediaCtrl = Nothing
                Running = False

                hr = videoWindow.put_Visible(OABool.False)
                DsError.ThrowExceptionForHR(hr)

                hr = videoWindow.put_Owner(IntPtr.Zero)
                DsError.ThrowExceptionForHR(hr)

                If mediaEventEx IsNot Nothing Then
                    hr = mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero)
                    DsError.ThrowExceptionForHR(hr)
                End If

            End If
        Catch ex As Exception
            Debug.WriteLine(ex)
        End Try

#If DEBUG Then
        If m_rot IsNot Nothing Then
            m_rot.Dispose()
            m_rot = Nothing
        End If
#End If

        If m_graphBuilder IsNot Nothing Then
            Marshal.ReleaseComObject(m_graphBuilder)
            m_graphBuilder = Nothing
        End If

        Connected = False
        parentHandle = IntPtr.Zero
        saveImage = False
        getImage = False
        ImagePathName = ""
        ImgFormat = Nothing

        GC.Collect()
    End Sub

    Private Function SampleCB(ByVal SampleTime As Double, ByVal pSample As IMediaSample) As Integer Implements ISampleGrabberCB.SampleCB
        If IsDBNull(pSample) = True Then Return -1
        Dim dataLen As Integer = pSample.GetActualDataLength()
        Dim buffPtr As IntPtr
        If pSample.GetPointer(buffPtr) = 0 And dataLen > 0 Then
            Dim buf As Byte() = New Byte(dataLen) {}
            Marshal.Copy(buffPtr, buf, 0, dataLen)

            If saveImage Or getImage Then
                Dim bmp As New Bitmap(m_videoWidth, m_videoHeight, Imaging.PixelFormat.Format24bppRgb)
                Dim bounds As Rectangle = New Rectangle(0, 0, m_videoWidth, m_videoHeight)

                Dim bmpData As BitmapData = bmp.LockBits(bounds, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format24bppRgb)

                Marshal.Copy(buf, 0, bmpData.Scan0, dataLen)
                capturedPic = bmp

                bmp.UnlockBits(bmpData)

                bmpData = Nothing
                bmp = Nothing
                buf = Nothing

                capturedPic.RotateFlip(RotateFlipType.RotateNoneFlipY)

                getImage = False
                saveImage = False
            End If
        End If
        Marshal.ReleaseComObject(pSample)
        Return 0
    End Function

    Private Function BufferCB(ByVal SampleTime As Double, ByVal pBuffer As IntPtr, ByVal BufferLen As Integer) As Integer Implements ISampleGrabberCB.BufferCB
        SyncLock Me
            'Empty....
        End SyncLock
        Return 0
    End Function

End Class

 Now we can program the Forms code. Here is an example that will list all the Video Capture devices in a ComboBox and lets you select the cam and the Frame Size that you wish to have the images saved as and then click the (Connect) button. After it is connected you can use the (SaveCurrentFrame) method to capture the current frame and save it directly to the hard drive. You could also use the (GetCurrentFrame) which is basically the same except it does not save it to the hard drive. There are a few other functions and properties i added to make it a little easier to use.

Public Class Form1
    Private WithEvents cam As New DSCamCapture
    Dim MyPicturesFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        cam.Dispose()
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ComboBox_Devices.Items.AddRange(cam.GetCaptureDevices)
        If ComboBox_Devices.Items.Count > 0 Then ComboBox_Devices.SelectedIndex = 0

        For Each sz As String In [Enum].GetNames(GetType(DSCamCapture.FrameSizes))
            ComboBox_FrameSize.Items.Add(sz.Replace("s", ""))
        Next
        If ComboBox_FrameSize.Items.Count > 2 Then ComboBox_FrameSize.SelectedIndex = 2

        Button_Connect.Enabled = (ComboBox_Devices.Items.Count > 0)
        Button_Save.Enabled = False
    End Sub

    Private Sub ComboBox_Devices_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox_Devices.DropDown
        ComboBox_Devices.Items.Clear()
        ComboBox_Devices.Items.AddRange(cam.GetCaptureDevices)
        Button_Connect.Enabled = (ComboBox_Devices.Items.Count > 0)
        If ComboBox_Devices.SelectedIndex = -1 And ComboBox_Devices.Items.Count > 0 Then ComboBox_Devices.SelectedIndex = 0
    End Sub

    Private Sub Button_Connect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Connect.Click
        If Not cam.IsConnected Then
            Dim si As Integer = ComboBox_FrameSize.SelectedIndex
            Dim SelectedSize As DSCamCapture.FrameSizes = CType(si, DSCamCapture.FrameSizes)
            If cam.ConnectToDevice(ComboBox_Devices.SelectedIndex, 15, PictureBox1.ClientSize, SelectedSize, PictureBox1.Handle) Then
                cam.Start()
                Button_Connect.Text = "Disconnect"
            End If
        Else
            cam.Dispose()
            Button_Connect.Text = "Connect"
        End If
        Button_Save.Enabled = cam.IsConnected
        ComboBox_Devices.Enabled = Not cam.IsConnected
        ComboBox_FrameSize.Enabled = Not cam.IsConnected
    End Sub

    Private Sub Button_Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Save.Click
        If Not IO.Directory.Exists(MyPicturesFolder) Then IO.Directory.CreateDirectory(MyPicturesFolder)
        Dim fName As String = Now.ToString.Replace("/", "-").Replace(":", "-").Replace(" ", "_") & ".jpg"
        Dim SaveAs As String = IO.Path.Combine(MyPicturesFolder, fName)
        cam.SaveCurrentFrame(SaveAs, Imaging.ImageFormat.Jpeg)
    End Sub

    Private Sub PictureBox1_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.SizeChanged
        cam.ResizeWindow(0, 0, PictureBox1.ClientSize.Width, PictureBox1.ClientSize.Height)
    End Sub

    Private Sub cam_FrameSaved(ByVal capImage As System.Drawing.Bitmap, ByVal imgPath As String) Handles cam.FrameSaved
        PictureBox2.Image = New Bitmap(capImage)
        Label2.Text = "Saved As - " & IO.Path.GetFileName(imgPath)
        Label3.Text = "Image Size - " & PictureBox2.Image.Size.ToString
    End Sub
End Class

Try it out if you want to and if you have problems or questions i will try to help.   :)

Here is what my Form looks like just to give an idea of the controls i used. I named them so it shouldn`t be to hard to figure out which one is which.


Tuesday, December 17, 2013 2:59 PM | 1 vote

Hi,

 You can try the code i posted at This Link. However, some webcams will not display the streaming video in the picturebox and you will see nothing but black in the picturebox but, it will still capture the image. If you have this problem and you really need to see the streaming video then you will need to use DirectShow to capture the webcam. That is a bit more complex than the version i have in that link. I have not experimented enough with the DirectShow method to figure out how to save images from the video stream so maybe someone here that has more knowledge of using DirectShow can help with that if the code in the link does not work.   :)


Wednesday, December 18, 2013 1:39 PM

Hi,

Thanks for your post.

I've tried the link and the code, but i'm still not getting the result I want.

The thing is, with you codes and other codes I got so far, I still cant detect and connect to my Logitech C210 webcam when connected to my laptop. I have two experiences here. The first is with the earlier code I have if I don't connect this webcam to the laptop the code worked fine with the fix manufacturer's webcam that come with the laptop, however when I connected the webcam the codes couldn't detect the connected webcam, it still shows the fix one in the listbox.

The second experience is with your code where it didn't detect both of the webcams on my laptop, but when I tried it on a another system without fix webcam, it was detected and worked.

I thought it might be driver issue on my laptop, but I've reinstalled severally, and when I ran the HP webcam app it detect both and worked just fine, but in my app.

Please any further suggestions.

Kayman


Thursday, December 19, 2013 12:07 AM

Hi,

 Below is the same code from the link i gave you but, i added one more button to the form and named it (Button_Source). After opening the app you can click the Source button and it should show you a dialog window that lets you select which WebCam you want to use. The dialog window will also let you set other options that are related to each WebCam. Unfortunately using the APIs like this are kind of limited in choosing the WebCam so if you want to automatically connect with a specific cam when the form loads then DirectShow is what you want to use.

Imports System.Runtime.InteropServices

Public Class Form1
    Dim cWnd As IntPtr = IntPtr.Zero
    Dim devId As Integer = 0
    Dim picnumber As Integer = 0
    Dim tmppic As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Temp.dib")

    Private Const WS_CHILD As Integer = &H40000000
    Private Const WS_VISIBLE As Integer = &H10000000
    Private Const WM_USER As Integer = &H400
    Private Const WM_CAP_DRIVER_CONNECT As Integer = WM_USER + 10
    Private Const WM_CAP_DRIVER_DISCONNECT As Integer = WM_USER + 11
    Private Const WM_CAP_SET_PREVIEW As Integer = WM_USER + 50
    Private Const WM_CAP_SET_PREVIEWRATE As Integer = WM_USER + 52
    Private Const WM_CAP_SET_SCALE As Integer = WM_USER + 53
    Private Const WM_CAP_SAVEDIB As Integer = WM_USER + 25
    Private Const WM_CAP_DLG_VIDEOFORMAT As Integer = WM_USER + 41
    Private Const WM_CAP_DLG_VIDEOSOURCE As Integer = WM_USER + 42

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Ansi)> Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As String) As IntPtr
    End Function

    <DllImport("avicap32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> Private Shared Function capCreateCaptureWindowA(ByVal lpszWindowName As String, ByVal dwStyle As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hWndParent As IntPtr, ByVal nID As Integer) As IntPtr
    End Function

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> Private Shared Function DestroyWindow(ByVal hwnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If Not cWnd.Equals(IntPtr.Zero) Then
            SendMessage(cWnd, WM_CAP_DRIVER_DISCONNECT, devId, Nothing)
            DestroyWindow(cWnd)
        End If
        If System.IO.File.Exists(tmppic) Then System.IO.File.Delete(tmppic)
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        cWnd = capCreateCaptureWindowA(devId.ToString, WS_VISIBLE Or WS_CHILD, 0, 0, PictureBox1.Width, PictureBox1.Height, PictureBox1.Handle, 0)
        If Not SendMessage(cWnd, WM_CAP_DRIVER_CONNECT, devId, Nothing) = IntPtr.Zero Then
            SendMessage(cWnd, WM_CAP_SET_SCALE, 1, Nothing)
            SendMessage(cWnd, WM_CAP_SET_PREVIEWRATE, 66, Nothing)
            SendMessage(cWnd, WM_CAP_SET_PREVIEW, 1, Nothing)
        Else
            MessageBox.Show("Error connecting to capture device. Make sure your WebCam is connected and try again.")
            cWnd = IntPtr.Zero
            Me.Close()
        End If
    End Sub

    Private Sub Button_SavePicture_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_SavePicture.Click
        SendMessage(cWnd, WM_CAP_SAVEDIB, 0, tmppic)
        Dim bmp As New Bitmap(tmppic)
        Dim saveas As String = "C:\TestFolder\MyPic_" & picnumber.ToString & ".jpg"
        picnumber += 1
        bmp.Save(saveas, Imaging.ImageFormat.Jpeg)
        bmp.Dispose()
    End Sub

    Private Sub Button_SetSizeColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_SetSizeColor.Click
        SendMessage(cWnd, WM_CAP_DLG_VIDEOFORMAT, 0, Nothing)
    End Sub

    Private Sub Button_Source_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Source.Click
        SendMessage(cWnd, WM_CAP_DLG_VIDEOSOURCE, 0, Nothing)
    End Sub
End Class

Thursday, December 19, 2013 3:53 AM

Ok I'll try this and get back.

Kayman


Thursday, December 19, 2013 10:08 AM

Hi,

Still same issue. The webcam is not detected. I would prefer to  use the video source dialog box to select which camera to use among the connected cameras.

I'll assume the webcam I'm using has problem, i'll get another to try you codes with.

Thanks for your response.

However you may inform me if there are other solutions you know of.

Kayman


Monday, December 23, 2013 2:26 PM

I'll try this. Thanks.

Kayman


Monday, December 30, 2013 10:52 AM | 1 vote

Hi,

Since we haven't heard from you for a long time, I temporarily close this case. I mark useful reply as answer. If you have any concerns, please free feel to reopen it or submit a new question.

Thanks for your understanding. Happy New Year:)

Best regards,
Franklin

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Tuesday, January 7, 2014 5:51 AM

Hi Kayman,

Try the 'webcam capture' demo application from the page and see how it works for you. It uses a 3rd party SDK - Dynamic .NET TWAIN, which is a .NET component to capture images from UVC/WIA webcams & TWAIN scanners.


Wednesday, October 1, 2014 7:51 AM

Could you have Visual C++ version as the same function like this.

or another web teach this 


Wednesday, October 1, 2014 10:41 AM

Could you have Visual C++ version as the same function like this.

or another web teach this 

 I imagine you could but, you would need a good knowledge of VC++ programming so you could convert it all to VC++. Do a search in the VC++ forum and you may find some examples and info on doing this.   8)

VC++ Msdn Forum Link

 

If you say it can`t be done then i`ll try it


Monday, September 28, 2015 12:47 PM

I know this is an old thread but just wanted to say 'thanks' to IronRazerz for posting this.

After several days of trying other solutions I've finally got my webcam working thanks to you.


Monday, September 28, 2015 9:08 PM

I know this is an old thread but just wanted to say 'thanks' to IronRazerz for posting this.

After several days of trying other solutions I've finally got my webcam working thanks to you.

 You`re Welcome,  i am glad it helped.  8)

If you say it can`t be done then i`ll try it


Monday, February 15, 2016 7:44 PM | 1 vote

Hi,

 I have made a class that you can add to any project and use it to capture images from a webcam using DirectShow. The first thing you need to do is download the latest DirectShow library from SourceForge.net and unzip it somewhere handy. Then you can start a new Form Project and add a class by going to the VB menu and clicking (Project) and then (Add Class...) and name it (DSCamCapture.vb). Now copy the DSCamCapture class code from below. After that you will need to add a reference to the DirectShow.dll file in the folder you downloaded from SourceForge. You can do that by going to the VB menu and clicking (Project) and then (Add Reference...). When the window opens click the (Browse) tab and browse to the (DirectShow.dll) file or the latest is named (DirectShowLib-2005.dll) and select it. That takes care of adding the class and references that are needed.

Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Runtime.InteropServices
Imports System.Diagnostics

Imports DirectShowLib 'You must add a reference to the newest DirectShowLib.dll file if this line has an error

Public Class DSCamCapture
    Implements ISampleGrabberCB
    Implements IDisposable

    Private WithEvents TmrCaptured As New Timer With {.Interval = 10}
    Private WithEvents TmrSaved As New Timer With {.Interval = 10}
    Public Event FrameCaptured(ByVal capImage As Bitmap)
    Public Event FrameSaved(ByVal capImage As Bitmap, ByVal imgPath As String)

    Private m_graphBuilder As IFilterGraph4 = Nothing
    Private m_mediaCtrl As IMediaControl = Nothing
    Private sampGrabber As ISampleGrabber = Nothing

    Private mediaEventEx As IMediaEventEx = Nothing
    Private videoWindow As IVideoWindow = Nothing
    Private Const WM_APP As Integer = &H8000
    Private Const WM_GRAPHNOTIFY As Integer = (WM_APP + 1)

    Private capturedPic As Bitmap = Nothing
    Private parentHandle As IntPtr = IntPtr.Zero
    Private saveImage As Boolean = False
    Private getImage As Boolean = False
    Private ImagePathName As String = ""
    Private ImgFormat As Imaging.ImageFormat = Nothing

    Private unsupportedVideo As Boolean
    Private m_videoWidth As Integer
    Private m_videoHeight As Integer
    Private m_stride As Integer

    Private Running As Boolean = False
    Private Connected As Boolean = False

#If DEBUG Then
    Private m_rot As DsROTEntry = Nothing
#End If

    ''' <summary>
    ''' Indicates if this instance is currently connected to a device.
    ''' </summary>
    Public ReadOnly Property IsConnected() As Boolean
        Get
            Return Connected
        End Get
    End Property

    ''' <summary>
    ''' Indicates if the capture graph is running or paused/stoped.
    ''' </summary>
    Public ReadOnly Property IsRunning() As Boolean
        Get
            Return Running
        End Get
    End Property

    ''' <summary>
    ''' Enum of common video frame sizes. Used to set the (frameSize) parameter of the (ConnectToDevice) function.
    ''' </summary>
    Public Enum FrameSizes As Integer
        s160x120 = 0
        s176x144 = 1
        s320x240 = 2
        s352x288 = 3
        s640x480 = 4
    End Enum

    ''' <summary>
    ''' Connects this instance of the Capture class to the specified capture device index.
    ''' </summary>
    ''' <param name="deviceIndex">The Zero Based Index Of Capture Device To Connect To.</param>
    ''' <param name="frameRate">The Capture Rate. Equivilant to FPS.</param>
    ''' <param name="windowSize">The size of the visible video window.</param>
    ''' <param name="frameSize">The size used for the video frames. This will also be the size images are saved as.</param>
    ''' <param name="hParent">A Handle To The Parent Window.</param>
    Public Function ConnectToDevice(ByVal deviceIndex As Integer, ByVal frameRate As Integer, ByVal windowSize As Size, ByVal frameSize As FrameSizes, ByVal hParent As IntPtr) As Boolean
        parentHandle = hParent

        ' Get the collection of video devices
        Dim capDevices As DsDevice() = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)

        If (deviceIndex + 1 > capDevices.Length) Then Throw New Exception("No video capture devices found at that index!")

        Dim dev As DsDevice = capDevices(deviceIndex)

        Dim iSize As New Size(CInt(frameSize.ToString.Substring(1, 3)), CInt(frameSize.ToString.Substring(5, 3)))

        Try
            SetupGraph(dev, frameRate, windowSize, iSize)
        Catch
            Dispose()
            If unsupportedVideo Then
                MessageBox.Show("The (imageSize) resolution isn't supported by the camera.")
            Else
                MessageBox.Show("An unknown error happened when connecting to the camera.")
            End If
            Return False
        End Try

        Connected = True
        Return True
    End Function

    ''' <summary>
    ''' Used to resize and/or change the location of the visible video window.
    ''' </summary>
    ''' <param name="xLoc">The new X location.</param>
    ''' <param name="yLoc">The new Y location.</param>
    ''' <param name="sWidth">The new Width of the window.</param>
    ''' <param name="sHeight">The new Height of the window.</param>
    ''' <remarks></remarks>
    Public Sub ResizeWindow(ByVal xLoc As Integer, ByVal yLoc As Integer, ByVal sWidth As Integer, ByVal sHeight As Integer)
        If Not parentHandle.Equals(IntPtr.Zero) Then
            Dim hr As Integer
            hr = videoWindow.SetWindowPosition(xLoc, yLoc, sWidth, sHeight)
            DsError.ThrowExceptionForHR(hr)
        End If
    End Sub

    ''' <summary>
    ''' Returns a string array containing all video capture device names in the device index order that are currently available.
    ''' </summary>
    Public Function GetCaptureDevices() As String()
        Dim capDevices As DsDevice() = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice)
        Dim dvcList As New List(Of String)
        For Each cd As DsDevice In capDevices
            dvcList.Add(cd.Name)
        Next
        Return dvcList.ToArray
    End Function

    ' <summary> 
    ' Disconnects from any devices and clears all resources.
    ' </summary>
    Public Sub Dispose() Implements IDisposable.Dispose
        CloseInterfaces()
    End Sub

    Protected Overloads Overrides Sub finalize()
        CloseInterfaces()
    End Sub

    ''' <summary>
    ''' Starts the capture graph.
    ''' </summary>
    Public Sub Start()
        If Not Running And Connected Then
            Dim hr As Integer = m_mediaCtrl.Run()
            DsError.ThrowExceptionForHR(hr)
            Running = True
        End If
    End Sub

    ''' <summary>
    ''' Pauses the capture graph. Running the graph takes up a lot of resources. (Pause) it when it isn't needed at the time and (Start) it when needed again.
    ''' </summary>
    Public Sub Pause()
        If Running And Connected Then
            Dim hr As Integer = m_mediaCtrl.Pause()
            DsError.ThrowExceptionForHR(hr)
            Running = False
        End If
    End Sub

    ''' <summary>
    ''' Saves an image file of the current video frame and passes the captured image to the (capImage) parameter in the (FrameSaved) event.
    ''' </summary>
    ''' <param name="strFileName">The full path, name, and extension to save the image as.</param>
    ''' <param name="iFormat">The image format for saving the file. Make sure the file extension matches.</param>
    Public Sub SaveCurrentFrame(ByVal strFileName As String, ByVal iFormat As Imaging.ImageFormat)
        ImagePathName = strFileName
        ImgFormat = iFormat
        saveImage = True
        TmrSaved.Start()
    End Sub

    'Used to save the image and trigger the FrameSaved event to notify the owner application the image was saved.
    Private Sub Tmr2_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TmrSaved.Tick
        If Not saveImage Then
            TmrSaved.Stop()
            capturedPic.Save(ImagePathName, ImgFormat)
            RaiseEvent FrameSaved(capturedPic, ImagePathName)
        End If
    End Sub

    ''' <summary>
    ''' Gets the current video frame and passes the captured image as the (capImage) parameter in the (FrameCaptured) event.
    ''' </summary>
    Public Sub GetCurrentFrame()
        getImage = True
        TmrCaptured.Start()
    End Sub

    'Used to raise the (FrameCaptured) event to notify the owner application the image is ready and pass the image.
    Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles TmrCaptured.Tick
        If Not getImage Then
            TmrCaptured.Stop()
            RaiseEvent FrameCaptured(capturedPic)
        End If
    End Sub

    Private Sub SetupGraph(ByVal dev As DsDevice, ByVal iFrameRate As Integer, ByVal winSize As Size, ByVal imgSize As Size)
        Dim hr As Integer
        Dim baseGrabFlt As IBaseFilter = Nothing
        Dim capFilter As IBaseFilter = Nothing
        Dim capGraph As ICaptureGraphBuilder2 = Nothing

        m_graphBuilder = DirectCast(New FilterGraph(), IFilterGraph4)
        m_mediaCtrl = DirectCast(m_graphBuilder, IMediaControl)
        mediaEventEx = DirectCast(m_graphBuilder, IMediaEventEx)
        videoWindow = DirectCast(m_graphBuilder, IVideoWindow)

#If DEBUG Then
        m_rot = New DsROTEntry(m_graphBuilder)
#End If

        Try
            capGraph = DirectCast(New CaptureGraphBuilder2(), ICaptureGraphBuilder2)
            sampGrabber = DirectCast(New SampleGrabber(), ISampleGrabber)

            hr = capGraph.SetFiltergraph(DirectCast(m_graphBuilder, IGraphBuilder))
            DsError.ThrowExceptionForHR(hr)

            hr = m_graphBuilder.AddSourceFilterForMoniker(dev.Mon, Nothing, dev.Name, capFilter)
            DsError.ThrowExceptionForHR(hr)

            baseGrabFlt = DirectCast(sampGrabber, IBaseFilter)
            ConfigureSampleGrabber(sampGrabber)

            hr = m_graphBuilder.AddFilter(baseGrabFlt, "DShow Capture")
            DsError.ThrowExceptionForHR(hr)

            SetConfigParms(capGraph, capFilter, iFrameRate, imgSize.Width, imgSize.Height)

            hr = capGraph.RenderStream(PinCategory.Capture, MediaType.Video, capFilter, baseGrabFlt, Nothing)
            DsError.ThrowExceptionForHR(hr)

            hr = mediaEventEx.SetNotifyWindow(parentHandle, WM_GRAPHNOTIFY, IntPtr.Zero)
            DsError.ThrowExceptionForHR(hr)

            hr = videoWindow.put_Owner(parentHandle)
            DsError.ThrowExceptionForHR(hr)

            hr = videoWindow.SetWindowPosition(0, 0, winSize.Width, winSize.Height)
            DsError.ThrowExceptionForHR(hr)

            hr = videoWindow.put_WindowStyle(WindowStyle.Child)
            DsError.ThrowExceptionForHR(hr)

            SaveSizeInfo(sampGrabber)

        Finally

            If (Not capFilter Is Nothing) Then
                Marshal.ReleaseComObject(capFilter)
                capFilter = Nothing
            End If
            If (Not sampGrabber Is Nothing) Then
                Marshal.ReleaseComObject(sampGrabber)
                sampGrabber = Nothing
            End If
        End Try
    End Sub

    Private Sub SaveSizeInfo(ByVal sampGrabber As ISampleGrabber)
        Dim hr As Integer
        Dim media As AMMediaType = New AMMediaType()
        hr = sampGrabber.GetConnectedMediaType(media)
        DsError.ThrowExceptionForHR(hr)

        If (Not (media.formatType.Equals(FormatType.VideoInfo)) AndAlso Not (media.formatPtr.Equals(IntPtr.Zero))) Then
            Throw New NotSupportedException("Unknown Media Format")
        End If

        Dim vInfoHeader As VideoInfoHeader = New VideoInfoHeader()
        Marshal.PtrToStructure(media.formatPtr, vInfoHeader)
        m_videoWidth = vInfoHeader.BmiHeader.Width
        m_videoHeight = vInfoHeader.BmiHeader.Height
        m_stride = CInt(m_videoWidth * (vInfoHeader.BmiHeader.BitCount / 8))

        DsUtils.FreeAMMediaType(media)
        media = Nothing
    End Sub

    Private Sub ConfigureSampleGrabber(ByVal sampGrabber As ISampleGrabber)
        Dim hr As Integer
        Dim media As AMMediaType = New AMMediaType()

        media.majorType = MediaType.Video
        media.subType = MediaSubType.RGB24
        media.formatType = FormatType.VideoInfo

        hr = sampGrabber.SetMediaType(media)
        DsError.ThrowExceptionForHR(hr)

        DsUtils.FreeAMMediaType(media)
        media = Nothing

        hr = sampGrabber.SetOneShot(False)
        DsError.ThrowExceptionForHR(hr)

        hr = sampGrabber.SetCallback(Me, 0)
        DsError.ThrowExceptionForHR(hr)

        sampGrabber.SetBufferSamples(False)
    End Sub

    Private Sub SetConfigParms(ByVal capGraph As ICaptureGraphBuilder2, ByVal capFilter As IBaseFilter, ByVal iFrameRate As Integer, ByVal iWidth As Integer, ByVal iHeight As Integer)
        Dim hr As Integer
        Dim obj As Object = Nothing
        Dim media As AMMediaType = Nothing
        Dim videoStreamConfig As IAMStreamConfig
        Dim videoControl As IAMVideoControl = DirectCast(capFilter, IAMVideoControl)

        hr = capGraph.FindInterface(PinCategory.Capture, MediaType.Video, capFilter, GetType(IAMStreamConfig).GUID, obj)

        videoStreamConfig = DirectCast(obj, IAMStreamConfig)

        Try
            If (videoStreamConfig Is Nothing) Then Throw New Exception("Failed to get IAMStreamConfig")

            hr = videoStreamConfig.GetFormat(media)
            DsError.ThrowExceptionForHR(hr)

            Dim vih As VideoInfoHeader = New VideoInfoHeader()
            Marshal.PtrToStructure(media.formatPtr, vih)

            vih.AvgTimePerFrame = CLng(10000000 / iFrameRate)
            vih.BmiHeader.Width = iWidth
            vih.BmiHeader.Height = iHeight

            Marshal.StructureToPtr(vih, media.formatPtr, False)

            hr = videoStreamConfig.SetFormat(media)
            If hr <> 0 Then unsupportedVideo = True Else unsupportedVideo = False
            DsError.ThrowExceptionForHR(hr)

            DsUtils.FreeAMMediaType(media)
            media = Nothing
        Finally
            Marshal.ReleaseComObject(videoStreamConfig)
        End Try
    End Sub

    Private Sub CloseInterfaces()
        Dim hr As Integer
        Try
            If m_mediaCtrl IsNot Nothing Then

                hr = m_mediaCtrl.Stop()
                m_mediaCtrl = Nothing
                Running = False

                hr = videoWindow.put_Visible(OABool.False)
                DsError.ThrowExceptionForHR(hr)

                hr = videoWindow.put_Owner(IntPtr.Zero)
                DsError.ThrowExceptionForHR(hr)

                If mediaEventEx IsNot Nothing Then
                    hr = mediaEventEx.SetNotifyWindow(IntPtr.Zero, 0, IntPtr.Zero)
                    DsError.ThrowExceptionForHR(hr)
                End If

            End If
        Catch ex As Exception
            Debug.WriteLine(ex)
        End Try

#If DEBUG Then
        If m_rot IsNot Nothing Then
            m_rot.Dispose()
            m_rot = Nothing
        End If
#End If

        If m_graphBuilder IsNot Nothing Then
            Marshal.ReleaseComObject(m_graphBuilder)
            m_graphBuilder = Nothing
        End If

        Connected = False
        parentHandle = IntPtr.Zero
        saveImage = False
        getImage = False
        ImagePathName = ""
        ImgFormat = Nothing

        GC.Collect()
    End Sub

    Private Function SampleCB(ByVal SampleTime As Double, ByVal pSample As IMediaSample) As Integer Implements ISampleGrabberCB.SampleCB
        If IsDBNull(pSample) = True Then Return -1
        Dim dataLen As Integer = pSample.GetActualDataLength()
        Dim buffPtr As IntPtr
        If pSample.GetPointer(buffPtr) = 0 And dataLen > 0 Then
            Dim buf As Byte() = New Byte(dataLen) {}
            Marshal.Copy(buffPtr, buf, 0, dataLen)

            If saveImage Or getImage Then
                Dim bmp As New Bitmap(m_videoWidth, m_videoHeight, Imaging.PixelFormat.Format24bppRgb)
                Dim bounds As Rectangle = New Rectangle(0, 0, m_videoWidth, m_videoHeight)

                Dim bmpData As BitmapData = bmp.LockBits(bounds, Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format24bppRgb)

                Marshal.Copy(buf, 0, bmpData.Scan0, dataLen)
                capturedPic = bmp

                bmp.UnlockBits(bmpData)

                bmpData = Nothing
                bmp = Nothing
                buf = Nothing

                capturedPic.RotateFlip(RotateFlipType.RotateNoneFlipY)

                getImage = False
                saveImage = False
            End If
        End If
        Marshal.ReleaseComObject(pSample)
        Return 0
    End Function

    Private Function BufferCB(ByVal SampleTime As Double, ByVal pBuffer As IntPtr, ByVal BufferLen As Integer) As Integer Implements ISampleGrabberCB.BufferCB
        SyncLock Me
            'Empty....
        End SyncLock
        Return 0
    End Function

End Class

 Now we can program the Forms code. Here is an example that will list all the Video Capture devices in a ComboBox and lets you select the cam and the Frame Size that you wish to have the images saved as and then click the (Connect) button. After it is connected you can use the (SaveCurrentFrame) method to capture the current frame and save it directly to the hard drive. You could also use the (GetCurrentFrame) which is basically the same except it does not save it to the hard drive. There are a few other functions and properties i added to make it a little easier to use.

Public Class Form1
    Private WithEvents cam As New DSCamCapture
    Dim MyPicturesFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        cam.Dispose()
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ComboBox_Devices.Items.AddRange(cam.GetCaptureDevices)
        If ComboBox_Devices.Items.Count > 0 Then ComboBox_Devices.SelectedIndex = 0

        For Each sz As String In [Enum].GetNames(GetType(DSCamCapture.FrameSizes))
            ComboBox_FrameSize.Items.Add(sz.Replace("s", ""))
        Next
        If ComboBox_FrameSize.Items.Count > 2 Then ComboBox_FrameSize.SelectedIndex = 2

        Button_Connect.Enabled = (ComboBox_Devices.Items.Count > 0)
        Button_Save.Enabled = False
    End Sub

    Private Sub ComboBox_Devices_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles ComboBox_Devices.DropDown
        ComboBox_Devices.Items.Clear()
        ComboBox_Devices.Items.AddRange(cam.GetCaptureDevices)
        Button_Connect.Enabled = (ComboBox_Devices.Items.Count > 0)
        If ComboBox_Devices.SelectedIndex = -1 And ComboBox_Devices.Items.Count > 0 Then ComboBox_Devices.SelectedIndex = 0
    End Sub

    Private Sub Button_Connect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Connect.Click
        If Not cam.IsConnected Then
            Dim si As Integer = ComboBox_FrameSize.SelectedIndex
            Dim SelectedSize As DSCamCapture.FrameSizes = CType(si, DSCamCapture.FrameSizes)
            If cam.ConnectToDevice(ComboBox_Devices.SelectedIndex, 15, PictureBox1.ClientSize, SelectedSize, PictureBox1.Handle) Then
                cam.Start()
                Button_Connect.Text = "Disconnect"
            End If
        Else
            cam.Dispose()
            Button_Connect.Text = "Connect"
        End If
        Button_Save.Enabled = cam.IsConnected
        ComboBox_Devices.Enabled = Not cam.IsConnected
        ComboBox_FrameSize.Enabled = Not cam.IsConnected
    End Sub

    Private Sub Button_Save_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Save.Click
        If Not IO.Directory.Exists(MyPicturesFolder) Then IO.Directory.CreateDirectory(MyPicturesFolder)
        Dim fName As String = Now.ToString.Replace("/", "-").Replace(":", "-").Replace(" ", "_") & ".jpg"
        Dim SaveAs As String = IO.Path.Combine(MyPicturesFolder, fName)
        cam.SaveCurrentFrame(SaveAs, Imaging.ImageFormat.Jpeg)
    End Sub

    Private Sub PictureBox1_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.SizeChanged
        cam.ResizeWindow(0, 0, PictureBox1.ClientSize.Width, PictureBox1.ClientSize.Height)
    End Sub

    Private Sub cam_FrameSaved(ByVal capImage As System.Drawing.Bitmap, ByVal imgPath As String) Handles cam.FrameSaved
        PictureBox2.Image = New Bitmap(capImage)
        Label2.Text = "Saved As - " & IO.Path.GetFileName(imgPath)
        Label3.Text = "Image Size - " & PictureBox2.Image.Size.ToString
    End Sub
End Class

Try it out if you want to and if you have problems or questions i will try to help.   :)

Here is what my Form looks like just to give an idea of the controls i used. I named them so it shouldn`t be to hard to figure out which one is which.

Hello IronRazerz,

I have used your class for a while right now and it has been working great on my Toshiba Portege Webcam (many thanks!). I have recently bought a Microsoft Surface, but the class does not seem to be working as I keep getting "The (imageSize) resolution isn't supported by the camera." error. I have tried to change the hard coded frame sizes but keep getting the same error. My question is how do I figure out the possible frame sizes for the computer's internal cam, and is it possible to programmatically detect those instead of hard coding them. Thanks again!


Wednesday, March 9, 2016 4:56 PM

Thanks a lot, your code was very helpfould....God bless you


Tuesday, July 5, 2016 8:56 AM

can anyone help me to set the frame size into 640x480 without choosing in the combobox framesize and automatically connect to the webcam without clicking connect button?Thanks in advance


Tuesday, February 7, 2017 3:04 AM

Hi IronRazerz, 

I am using your code to take a picture using Directshow. 

May i find out something? The code is working well with my external webcam. But when it come to my surface pro built in camera. Once i click connect, the following error prompted. May i know what can i do? Is it something to do with camera resolution?? 

"The (imageSize) resolution isn't supported by the camera."


Tuesday, February 7, 2017 12:23 PM

@ limcheehang

 I really can't say why.  Back when i set this code up i did not set up the exception handling very good so,  it could be because the device does not support the selected size, or maybe the selected frame rate,  or there could be something else in the SetupGraph sub that is throwing the exception.  It could also be because there is another device that is connected to the webcam already.

 You can look at the link below for information on how you can get the supported sizes and formats.  There is also a lot of info and examples that can be found on the internet for this topic.

Exposing Capture and Compression Formats

 

If you say it can`t be done then i`ll try it


Thursday, January 10, 2019 1:02 PM

This is excellent. I followed this code and I am now able to grab image from webcam on Windows 10 PC. Thanks alot. Please keep contributing to the community.


Sunday, July 28, 2019 3:12 PM

Ciao

Sono 2 gg che giro in internet per qualcosa che funzioni davvero, ma nulla funzionava sul mio tablet.

Quasto funziona davvero.!!!!

Grazie per il tuo e il vostro lavoro (di tutti coloro che danno il loro contributo perchè qualcuni ne capisca qualcoosa).

Ciao

Andrea