Webcam Barcode Scanner with HTML5 and Web Browser

As Internet connection speed getting faster, more and more people tend to embrace cloud service. Any desktop applications could be transformed to cloud applications with better maintainability, security, and stability. End-users can use web browsers to get connected with social friends, store tons of personal data, watch live video, edit documents, publish blog posts and even write code. As a programmer, if you are still developing desktop applications, it is time to think about how to turn your apps into web services. In this article, we will take a glimpse of how to make webcam barcode scanner with Dynamic Barcode Reader SDK work and web technologies.

This article has been posted on CodeProject.

webcam barcode scanner

Implementation of Webcam Barcode Scanner

  1. Open Visual Studio to create a new web project.
  2. Click References to import Dynamsoft.BarcodeReader.dll.
  3. Create a C# class BarrecodeReaderRepo to handle barcode detection on the server-side:
    using System;
    using System.Drawing;
    using System.IO;
    using Dynamsoft.Barcode;
    
    namespace BarcodeDLL
    {
        public class BarrecodeReaderRepo
        {
            private static readonly char CSep = Path.DirectorySeparatorChar;
            private static readonly string StrPath = AppDomain.CurrentDomain.BaseDirectory + "Images";
            private static readonly string CollectFolder = StrPath + CSep + "Collect";
    
            public static string Barcode(string strImgBase64, Int64 iformat, int iMaxNumbers, ref string strResult)
            {
                if (string.IsNullOrEmpty(strImgBase64.Trim())) throw new Exception("No barcode exist.");
    
                return DoBarcode(strImgBase64, iformat, iMaxNumbers, ref strResult);
            }
    
            private static string DoBarcode(string strImgBase64, Int64 format, int iMaxNumbers, ref string strResult)
            {
                strResult = "";
                var strResturn = "[";
    
                var listResult = GetBarcode(strImgBase64, format, iMaxNumbers);
    
                if (listResult == null || listResult.Length == 0)
                {
                    strResult = "No barcode found. ";
                    return "[]";
                }
                strResult = "Total barcode(s) found: " + listResult.Length + "<br/>";
                var i = 1;
                foreach (var item in listResult)
                {
                    strResult = strResult + "&nbsp&nbspBarcode " + i + ":<br/>";
                    strResult = strResult + "&nbsp&nbsp&nbsp&nbspType: " + item.BarcodeFormat + "<br/>";
                    strResult = strResult + "&nbsp&nbsp&nbsp&nbspValue: " + item.BarcodeText + "<br/>";
                    strResult = strResult + "&nbsp&nbsp&nbsp&nbspRegion: {Left: " + item.ResultPoints[0].X
                                + ", Top: " + item.ResultPoints[0].Y
                                + ", Width: " + item.BoundingRect.Width
                                + ", Height: " + item.BoundingRect.Height + "}<br/>";
                    i++;
                }
                strResturn = strResturn.Substring(0, strResturn.Length - 1);
                strResturn += "]";
                return strResturn;
            }
    
            public static BarcodeResult[] GetBarcode(string strImgBase64, Int64 format, int iMaxNumbers)
            {
                var reader = new Dynamsoft.Barcode.BarcodeReader();
                var options = new ReaderOptions
                {
                    MaxBarcodesToReadPerPage = iMaxNumbers,
                    BarcodeFormats = (BarcodeFormat) format
                };
    
                reader.ReaderOptions = options;
                reader.LicenseKeys = "693C401F1CC972A511F060EA05D537CD";
                return reader.DecodeBase64String(strImgBase64);
            }
        }
    }
    
  4. Create a Generic Handler WebcamBarcodeReader.ashx to process the HTTP request. Parse stream to get the base64 string, and then pass it to BarrecodeReaderRepo:
    public class WebcamBarcodeReader : IHttpHandler
        {
            public void ProcessRequest(HttpContext context)
            {
                try
                {
                    // 1. Get Base64 Stream
                    context.Request.InputStream.Position = 0;
                    string jsonString;
                    using (var inputStream = new StreamReader(context.Request.InputStream))
                    {
                        jsonString = inputStream.ReadToEnd();
                    }
                    var postData = JsonConvert.DeserializeObject<PostData>(@jsonString);
                    
                    if (postData == null) return;
                    
                    // 2. reader barcode and output result
                    var strResult = "";
                    BarrecodeReaderRepo.Barcode(postData.Base64Data, postData.BarcodeType, 10, ref strResult);
                    if (strResult.IndexOf("No barcode found", StringComparison.Ordinal) == -1)
                    {
                        strResult = "|" + strResult; 
                    }
    
                    strResult += DateTime.Now;
                    context.Response.Write(strResult);
                }
                catch (Exception exp)
                {
                    context.Response.Write("Error: " + exp.Message);
                }
            }
    
            public bool IsReusable
            {
                get
                {
                    return true;
                }
            }
    
            public class PostData
            {
                public string Base64Data { get; set; }
                public int BarcodeType { get; set; }
            }
        }
  5. Create an element <video></video>. Open a webcam in a web page with the HTML5 API getUserMedia:
    function toggleCamera() {
        var videoSource = videoSelect.value;
        var constraints = {
            video: {
                optional: [{
                    sourceId: videoSource
                }]
            }
        };
    
        startCamera(constraints);
    }
    
    // Start camera preview on <video></video>
    function successCallback(stream) {
        window.stream = stream;
        videoElement.src = window.URL.createObjectURL(stream);
        videoElement.play();
    }
    
    function errorCallback(error) {
        console.log("Error: " + error);
    }
    
    function startCamera(constraints) {
        if (navigator.getUserMedia) {
            navigator.getUserMedia(constraints, successCallback, errorCallback);
        } else {
            console.log("getUserMedia not supported");
        }
    }
  6. How to send preview images to the remote server? Keep drawing frames on a hidden canvas. Convert the canvas data to base64 string and send it in Ajax. If there is nothing detected, use the method setTimeout to send the preview data for detection again:
    context.drawImage(videoElement, 0, 0, width, height);
    // convert canvas to base64
    var base64 = dbrCanvas.toDataURL('image/png', 1.0);
    var data = base64.replace(/^data:image\/(png|jpeg|jpg);base64,/, "");
    var imgData = JSON.stringify({
        Base64Data: data,
        BarcodeType: getBarcodeFormat()
    });
    $.ajax({
        url: 'WebcamBarcodeReader.ashx',
        dataType: 'json',
        data: imgData,
        type: 'POST',
        complete: function (result) {
            console.log(result);
            if (isPaused) {
                return;
            }
            var barcode_result = document.getElementById('dbr');
            var aryResult;
            aryResult = result.responseText.split('|');
    
            // display barcode result
            if (result.responseText.indexOf("No barcode") == -1) {
                resetButtonGo();
                barcode_result.innerHTML = result.responseText.substring(aryResult[0].length + 1);
            }
            else {
                barcode_result.innerHTML = result.responseText;
                setTimeout(scanBarcode, 200);
            }
        }
    });

Online Demo

Try it now!

Sample Code

Download