Silverlight 4.0 Tutorial (9 of N): Using the WebCam as a Barcode Scanner
You can find a list of the previous tutorial posts here
Continuing our RegistrationBooth Application, we want to allow registered users to evaluate sessions, we don’t have a credentials store in our application so to identify the registered attendees we will use a simpler approach, in part2 we allowed printing a name tag for registered attendees, this name tag contains a barcode of the attendee id, in this post we will see how can we use the new Silverlight 4.0 WebCam functionality to be able to scan/read barcodes and extract the attendee id to identify the corresponding attendee.
During PDC09 Keynote, Scott Guthrie demonstrated a Silverlight Application that scans a book ISBN barcode and passes this ISBN to Amazon web service to retrieve the book information, we will reuse the code from this sample which can be downloaded from here.
This sample actually uses a code from a CodeProject Article (by Berend Engelbrecht) that detects barcodes inside an image. the code is located in the file BarcodeImaging.cs, so we will copy this file to our project.
The sample also has another class BarcodeCapture that derives from VideoSink, according to MSDN “To obtain video information from a video input device in Silverlight, you derive a custom video sink from VideoSink” , the important method to override in this class is OnSample which is called when the video device captures a complete video sample. the code in this method calls the BarcodeImaging method that scans the current sample bitmap for a barcode, if a barcode is found the BarcodeCapture class fires a custom event BarcodeDetected that propagates the detected barcode. so we will need to copy the BarcodeCapture.cs file to our project.
On the UI we will have two components, the first one is a rectangle that we will display the webcam stream inside it.
<StackPanel>
<TextBlock TextAlignment="Center" FontSize="14.667" FontWeight="Bold" Foreground="White" >Place your name tag infront of the camera</TextBlock>
<Rectangle x:Name="barcodeScanner" Fill="White" Width="400" Height="300" />
</StackPanel>
</Border>
The second UI component is another rectangle that will be shown when a barcode is detected, the rectangle will display a simple welcome message to the user, we will add more functionality later.
<StackPanel Orientation="Horizontal">
<TextBlock TextAlignment="Center" FontSize="14.667" VerticalAlignment="Center" FontWeight="Bold" Foreground="White" >Welcome </TextBlock>
<TextBlock x:Name="userName" TextAlignment="Center" FontSize="14.667" VerticalAlignment="Center" FontWeight="Bold" Foreground="White" ></TextBlock>
</StackPanel>
</Border>
We will add two new visual states, the first one is “ScanningNameTag” in this state we display the barcode scanning area and the attendee list, here’s how the UI looks like in this state
The button “Back” moves the UI back to the Default state by using a MoveToStateAction behavior
The second state is “WelcomeAttendee”, in this state we show the welcome area and the attendee list, here’s how the UI looks like in this state
As you can see we added a Good Bye Button (btnLogout), we will add a MoveToStateAction behavior to this button so that when we click it we move to the Default state
when we click the “Login” button, we will start the cam and move to the “ScanningNameTag” state
{
if (ActivateCamera())
{
if (m_Capture == null)
{
m_Capture = new BarcodeCapture();
m_Capture.BarcodeDetected += new EventHandler<BarcodeEventArgs>(OnBarcodeDetected);
m_Capture.CaptureSource = m_CaptureSource;
}
VisualStateManager.GoToState(this, "ScanningNameTag", true);
}
}
The code first activates the camera to start capturing by calling the ActivateCamera function shown below
{
if (m_CaptureSource == null)
{
m_CaptureSource = new CaptureSource();
m_CaptureSource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
VideoBrush previewBrush = new VideoBrush();
previewBrush.Stretch = Stretch.Uniform;
previewBrush.SetSource(m_CaptureSource);
barcodeScanner.Fill = previewBrush;
Size diff = new Size(double.MaxValue, double.MaxValue);
Size wantedSize = new Size(640, 480);
VideoFormat bestFormat = null;
foreach (VideoFormat format in m_CaptureSource.VideoCaptureDevice.SupportedFormats)
{
double x = Math.Abs(format.PixelWidth - wantedSize.Width);
double y = Math.Abs(format.PixelHeight - wantedSize.Height);
if (x < diff.Width && y < diff.Height)
{
bestFormat = format;
diff.Width = x;
diff.Height = y;
}
}
if (bestFormat != null)
{
m_CaptureSource.VideoCaptureDevice.DesiredFormat = bestFormat;
}
if (CaptureDeviceConfiguration.RequestDeviceAccess() || CaptureDeviceConfiguration.AllowedDeviceAccess)
{
m_CaptureSource.Start();
return true;
}
else
return false;
}
else
return true;
}
after starting the camera we create an instance of our VideoSink (BarcodeCapture) and link the capture source with our video sink, we must also register to the event BarcodeDetected to be notified when the BarcodeCapture video sink detects a barcode in the image.
Here is the event handler for the BarcodeDetected event
{
if (e.Barcode.Length < 8)//barcode formate is ATTXXXXX
return;
int attendeeID=0;
if (!Int32.TryParse(e.Barcode.Substring(3, 5), out attendeeID))
return;
Dispatcher.BeginInvoke(delegate()
{
RegistrationDomainContext context = this.Resources["registrationDomainContext"] as RegistrationDomainContext;
context.Load(context.GetAttendeeQuery(attendeeID),
delegate(LoadOperation<Attendee> loadOperation)
{
m_CaptureSource.Stop();
m_Capture.Clear();
foreach (var attendee in loadOperation.Entities)
{
lblUserName.Text = string.Format(" {0} {1}", attendee.FirstName ,attendee.LastName);
break;
}
VisualStateManager.GoToState(this, "WelcomeAttendee", true);
},
null);
});
}
First We validate the barcode format, then we call a new domain service method that retrieves the attendee based on the id, note that we are using Dispatcher.BeginInvoke method so that our code runs on the main UI thread.
Let’s run the application, click on the Login button, the webcam will start, hold the name tag in front of the webcam, you may need to move the name tag closer/way from the webcam till it picks the barcode
Once the barcode is detected, the application will move to the WelcomeAttendee state
Note: i used the Silverlight Barcode Library to generate the barcode, cause the previous method we used (the font 3 of 9) was not recognized by Berend library
You can download the source code from here.
See you in the next post.
Comments
I have downloaded RegistrationBooth code and built it but its throw error on machine.
Could you please provide complete SharePoint Solution package for this feature.
Thanks in advance.
Regards,
Tushar Parikh
http://www.barcodemart.co.id/web/pubcategory/scanning-barcode-1-3-01.html here you can find
everything about scaning, printing pos software and many other things visit us you wont be sorry.