vb.net webcam integration

1

One of the nice things about these older Logitech Webcams is that they don’t require a driver download and they support Windows Image Acquisition (WIA) directly. WIA is an API included in Windows that aims to unify the acquisition of images from all kinds of devices, including scanners and cameras. This is a pretty low-level API and a bit of a hassle to us. However, after Windows XP SP1 the WIA Automation Layer was released with a simpler COM API meant for VB6 and ASP developers. You can download this layer from MSDN and other places as it is free for redistribution. The meat of the layer is the wiaaut.dll that should be copied into the system32 directory and registered via the command “regsvr32 wiaaut.dll.”

Getting to WIA from .NET
The wiaaut.dll COM automation library can be added via “Add Reference” from with Visual Studio.NET 2005 and a .NET wrapper will be automatically generated. Only devices whose drivers support WIA will be available via this interface. Most name-brand cameras will work just fine, but some no-name brands won’t appear. If your device appears in the Control Panel’s “Scanners and Cameras” interface, then this technique, and this program, should be able to see it.

In our code, we can add a namespace qualifying statement like using WIA in C# or imports WIA in VB.NET to name it easier to access these newly imported classes and interfaces. To start, we’ll need to get a hold of a DeviceID. WIA thinks about things in terms of Devices, Commands, and Formats. Devices have types like Camera, Scanner or Video. Commands are things like “Take Picture” and Formats are JPEG or BMP, etc.

We’ll create an instance of a CommandDialogClass (from the newly imported WIA namespace) and ask it to show us a select dialog so that we might select from any kind of device. You can show only Video devices or only Scanners by changing the WiaDeviceType enumeration that’s passed in. We’ll only show this select dialog when the user clicks “Configure” in our application, or when the application has been started with invalid configuration data.

Visual Basic

Dim class1 As CommonDialogClass = New CommonDialogClassDim d As Device = class1.ShowSelectDevice(WiaDeviceType.UnspecifiedDeviceType, true, false)If (Not (d) Is Nothing) Then settings.DeviceID = d.DeviceID settings.SaveEnd If

This select dialog is, fortunately, supplied completely by Windows and returns a Device. Each Device has a DeviceID that we will save into our User-specific settings class. This class was generated automatically by new features in Visual Studio .NET 2005 that make managing settings fantastically easy. I right-clicked on the Project from within the Visual Studio Solution Explorer and selected “Settings.” After I indicated the names and data types of the settings I needed to save, Visual Studio 2005 generated a class that exposed strongly-typed properties such as DeviceID. Settings can also be saved more easily in .NET 2.0. The DeviceID for my Webcam happened to be “{6BDD1FC6-810F-11D0-BEC7-08002BE2092F}\0003” and is stored in my user’s Documents And Settings\Local Settings\Application Data\BlogWebcam directory.

Download vb.net code – http://download.microsoft.com/download/d/4/5/d4556729-81f9-4578-936a-111721b27e49/BlogWebcam-VB.msi

Download c sharp code – http://download.microsoft.com/download/d/4/5/d4556729-81f9-4578-936a-111721b27e49/BlogWebcam-CS.msi

Taking a Picture
Once we’ve stored away a DeviceID in the configuration file, we’ll want to connect to our device and take a picture. We’ll need to find the device via it’s ID without showing the dialog, connect to it and hold on the Device instance.

Visual C#

DeviceManager manager = new DeviceManagerClass();Device d = null;foreach (DeviceInfo info in manager.DeviceInfos){ if (info.DeviceID == settings.DeviceID) { d = info.Connect(); break; }}Visual Basic

Dim manager As DeviceManager = New DeviceManagerClassDim d As Device = NothingFor Each info As DeviceInfo In manager.DeviceInfos If (info.DeviceID = settings.DeviceID) Then d = info.Connect Exit For End IfNext Now we’re back where we were before, with a Device instance in the variable d. We’ll be connecting to the device each time our timer is started. Each device has a series of commands available to it, and these commands are well-known and identified by GUIDS both in the Registry and in the MSDN Help. We’re interested in “Take Picture” which has the GUID string value “AF933CAC-ACAD-11D2-A093-00C04F72DC3C”, but the COM interface also exposes this value in the constant CommandID.wiaCommandTakePicture. When we get a hold of our Device we can spin through its available Commands until we find this one to determine if the device supports it, or we can just call it directly via Device.ExecuteCommand.

Visual C#

Item item = device.ExecuteCommand(CommandID.wiaCommandTakePicture);Visual Basic

Dim item As Item = device.ExecuteCommand(CommandID.wiaCommandTakePicture)Once we’ve called ExecuteCommand on our device an “Item” is returned. This isn’t just any ordinary item, it’s a WIA Item. Each WIA may include any number of image Formats. These formats are also well-known and appear in the registry. I look them up in the startup of the app just in case they change, rather than hard-coding them.

We spin through the available formats looking for JPEG. I could likely have hard-coded the JPEG GUID and avoided this quick spin, but I also wanted to illustrate how you can find your way around the WIA object model. Once we’ve found JPEG, we call item.Transfer and an ImageFile is returned that we can save to disk.

Visual C#

Item item = device.ExecuteCommand(CommandID.wiaCommandTakePicture);foreach (string format in item.Formats){ if (format == jpegGuid) { WIA.ImageFile imagefile = item.Transfer(format) as WIA.ImageFile; filename = GetFreeFileName(); if (string.IsNullOrEmpty(filename) == false) { imagefile.SaveFile(filename); } this.picLastImage.Load(filename); return filename; }}Visual Basic

Item item = device.ExecuteDim item As Item = device.ExecuteCommand(CommandID.wiaCommandTakePicture)For Each format As String In item.Formats If (format = jpegGuid) Then Dim imagefile As WIA.ImageFile = CType(item.Transfer(format),WIA.ImageFile) filename = GetFreeFileName If (String.IsNullOrEmpty(filename) = false) Then imagefile.SaveFile(filename) End If Me.picLastImage.Load(filename) Return filename End IfNext Incidentally, I also load the saved image into a PictureBox on my WinForm and return it from this TakePicture() method.

Uploading the Picture to my WebLog
Now that I’ve taken a picture, what am I going to do to it? Well, why not upload it to a specific filename on my blog so folks can see me and my workspace; what could be more thrilling? In the past, FTP’ing a file would require a third-party library, but .NET 2.0 has extended the System.Net.WebRequest class with support for FTP.

Here we’ll create an FtpWebRequest by passing an ftp:// URL to the WebRequest.Create method. For convenience I’ll include the username and password in the URL like this: ftp://username:password@ftp.myurl.com/blog/webcam.jpg. Note that the URL includes the username, password, domain name and destination filename all in one string. We’ll load our local file into a byte array and write it out (upload it) to the FtpWebRequest’s underlying stream by retrieving it with GetRequestStream() and then Write().

Visual C#

FtpWebRequest request = (FtpWebRequest)WebRequest.Create(settings.FTPServerURL);request.Method = WebRequestMethods.Ftp.UploadFile;request.UseBinary = true;FileInfo fileInfo = new FileInfo(filename);byte[] fileContents = new byte[fileInfo.Length];using (FileStream fr = fileInfo.OpenRead()){ fr.Read(fileContents, 0, Convert.ToInt32(fileInfo.Length));}using (Stream writer = request.GetRequestStream()){ writer.Write(fileContents, 0, fileContents.Length);}using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()){} Visual Basic

Dim request As FtpWebRequest = Nothingrequest = CType(WebRequest.Create(settings.FTPServerURL),FtpWebRequest)request.Method = WebRequestMethods.Ftp.UploadFilerequest.UseBinary = trueDim fileInfo As FileInfo = New FileInfo(filename)Dim fileContents() As Byte = New Byte((fileInfo.Length) – 1) {}Using fr As FileStream = fileInfo.OpenRead fr.Read(fileContents, 0, Convert.ToInt32(fileInfo.Length))End Using Using writer As Stream = request.GetRequestStream writer.Write(fileContents, 0, fileContents.Length)End Using Dim response As FtpWebResponse = CType(request.GetResponse,FtpWebResponse) You may notice the use of the “using” statements in the code snippet above. Using “using” with classes that implement IDisposable will automatically cause Dispose() to be called when then using block exits. Some folks don’t like the syntax and others believe that using it even if the underlying Dispose() doesn’t do anything is syntactic sugar. Personally, I really like the syntax, and in this sample the using statement is closing the FileStream, the Request stream, and the FtpWebResponse.

Read Original Article : http://blogs.msdn.com/b/coding4fun/archive/2006/10/31/912546.aspx

For suggestions and comments please use idealprogrammer forums .