Read From Live Camera - ASP.NET MVC C#
BarCode Reader SDK sample in ASP.NET MVC C# demonstrating ‘Read From Live Camera’
!!!ReadmeFIRST.txt
This sample supports all browsers by using 2 modes:
(required mode is automatically detected by the javascript)
- HTML5 based web camera capture (supported by Google Chrome, Firefox, Safari, Safari on iOS browsers)
- Flash based web camera capture (supported by Internet Explorer 9+ and any browser with flash support)
IMPORTANT about HTML5 webcamera support (Chrome, Firefox, Safari on desktop and iOS): it is required to run your website (even test website) via SSL connection. Otherwise, web camera won't initialize at all as it requies SSL connection.
Visual Studio 2008/2010 or higher is required for this sample to run!
1) Install evaluation copy of BarCode Reader SDK from www.bytescout.com
2) in Visual Studio use File - Open - Web-Site.. and open the folder with this sample
3) Add a reference to ByteScout BarCode Reader dll using the menu: Website - Add Reference (find Bytescout Barcode Reader SDK on .NET tab, select and click OK to add a reference)
4) Right-click on "Default.aspx" file and select "Set As Start Page"
5) Run the project in debug mode
6) Visual Studio will run your project in Internet Explorer or another browser
If it run Internet Explorer then better copy the link from the IE and copy-and-paste to another browser with HTML5 web cam support like Google Chrome, Firefox or Safari
7) When browser asks for permission to access web-cam click "Allow" to allow access to web cam
8) click "START BARCODE SCAN.." button so the page will start automatically to grab frames from video and sending it to server-side code to read barcodes using Barcode Reader SDK
9) IMPORTANT: barcode should be in focus. Some webcams are not focusing on small barcodes, you may need to adjust the focus on your webcam so it will work OK with small images like barcodes
10) Click Stop to stop barcode scanning
Select barcode type to scan if need to scan a particular barcode type (by default scans for all known types)
TESTING:
- we recommend to use the Conveyor plugin to test your web app from local net or public url: https://marketplace.visualstudio.com/items?itemName=vs-publisher-1448185.ConveyorbyKeyoti
Barcode.cs
namespace BarcodeReader
{
using Bytescout.BarCodeReader;
public class Barcode
{
public static FoundBarcode[] FindBarcodes(string fileName)
{
Reader reader = new Reader();
// Limit search to 1D barcodes only (exclude 2D barcodes to speed up the search).
// Change to reader.BarcodeTypesToFind.SetAll() to scan for all supported 1D and 2D barcodes
// or select specific type, e.g. reader.BarcodeTypesToFind.PDF417 = True
reader.BarcodeTypesToFind.SetAll();
// reader.MediumTrustLevelCompatible = true; // uncomment this line to enable Medium Trust compatible mode (slows down the recognition process as direct image data access is disabled in Medium Trust mode)
reader.ReadFromFile(fileName);
return reader.FoundBarcodes;
}
public static BarcodeTypeSelector GetBarcodeTypeToFindFromCombobox(string barType)
{
string selectedItemText = barType.Trim().ToUpper();
BarcodeTypeSelector barcodeTypeToScan = new BarcodeTypeSelector();
if (selectedItemText.IndexOf("ALL BARCODES") > -1)
barcodeTypeToScan.SetAll();
else if (selectedItemText.IndexOf("ALL LINEAR BARCODES") > -1)
barcodeTypeToScan.SetAll1D();
else if (selectedItemText.IndexOf("ALL 2D BARCODES") > -1)
barcodeTypeToScan.SetAll2D();
else if (selectedItemText.IndexOf("AZTEC") > -1)
barcodeTypeToScan.Aztec = true;
else if (selectedItemText.IndexOf("CODABAR") > -1)
barcodeTypeToScan.Codabar = true;
else if (selectedItemText.IndexOf("CODE 39") > -1)
barcodeTypeToScan.Code39 = true;
else if (selectedItemText.IndexOf("CODE 128") > -1)
barcodeTypeToScan.Code128 = true;
else if (selectedItemText.IndexOf("DATAMATRIX") > -1)
barcodeTypeToScan.DataMatrix = true;
else if (selectedItemText.IndexOf("EAN 13") > -1)
barcodeTypeToScan.EAN13 = true;
else if (selectedItemText.IndexOf("GS1-128") > -1)
barcodeTypeToScan.GS1 = true;
else if (selectedItemText.IndexOf("GS1DATABAREXPANDED") > -1)
barcodeTypeToScan.GS1DataBarExpanded = true;
else if (selectedItemText.IndexOf("GS1DATABAREXPANDEDSTACKED") > -1)
barcodeTypeToScan.GS1DataBarExpandedStacked = true;
else if (selectedItemText.IndexOf("GS1DATABARLIMITED") > -1)
barcodeTypeToScan.GS1DataBarLimited = true;
else if (selectedItemText.IndexOf("GS1DATABAROMNIDIRECTIONAL") > -1)
barcodeTypeToScan.GS1DataBarOmnidirectional = true;
else if (selectedItemText.IndexOf("GS1DATABARSTACKED") > -1)
barcodeTypeToScan.GS1DataBarStacked = true;
else if (selectedItemText.IndexOf("I2OF5") > -1)
barcodeTypeToScan.Interleaved2of5 = true;
else if (selectedItemText.IndexOf("INTELLIGENT MAIL") > -1)
barcodeTypeToScan.IntelligentMail = true;
else if (selectedItemText.IndexOf("PATCH") > -1)
barcodeTypeToScan.PatchCode = true;
else if (selectedItemText.IndexOf("PDF 417") > -1)
barcodeTypeToScan.PDF417 = true;
else if (selectedItemText.IndexOf("QR CODE") > -1)
barcodeTypeToScan.QRCode = true;
else if (selectedItemText.IndexOf("UPCA") > -1)
barcodeTypeToScan.UPCA = true;
else if (selectedItemText.IndexOf("UPCE") > -1)
barcodeTypeToScan.UPCE = true;
else if (selectedItemText.IndexOf("MAXICODE") > -1)
barcodeTypeToScan.MaxiCode = true;
return barcodeTypeToScan;
}
}
}
Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
namespace BarcodeReader
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
}
BundleConfig.cs
using System.Web;
using System.Web.Optimization;
namespace BarcodeReader
{
public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
}
FilterConfig.cs
using System.Web;
using System.Web.Mvc;
namespace BarcodeReader
{
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
}
}
RouteConfig.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace BarcodeReader
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace BarcodeReader.Controllers
{
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using Bytescout.BarCodeReader;
public class HomeController : Controller
{
/*
IF YOU SEE TEMPORARY FOLDER ACCESS ERRORS:
Temporary folder access is required for web application when you use ByteScout SDK in it.
If you are getting errors related to the access to temporary folder like "Access to the path 'C:\Windows\TEMP\... is denied" then you need to add permission for this temporary folder to make ByteScout SDK working on that machine and IIS configuration because ByteScout SDK requires access to temp folder to cache some of its data for more efficient work.
SOLUTION:
If your IIS Application Pool has "Load User Profile" option enabled the IIS provides access to user's temp folder. Check user's temporary folder
If you are running Web Application under an impersonated account or IIS_IUSRS group, IIS may redirect all requests into separate temp folder like "c:\temp\".
In this case
- check the User or User Group your web application is running under
- then add permissions for this User or User Group to read and write into that temp folder (c:\temp or c:\windows\temp\ folder)
- restart your web application and try again
*/
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
if (file != null)
{
string name = file.FileName;
string path = Path.Combine(Server.MapPath("/"), Path.GetFileName(name));
file.SaveAs(path);
ViewBag.Barcodes = Barcode.FindBarcodes(path);
ViewBag.Img = name;
}
return View();
}
[HttpPost]
public ActionResult UploadHtml5(string image, string type)
{
try
{
StringBuilder send = new StringBuilder();
// Lock by send variable
lock (send)
{
// Convert base64 string from the client side into byte array
byte[] bitmapArrayOfBytes = Convert.FromBase64String(image);
// Create Bytescout.BarCodeReader.Reader object
Reader reader = new Reader();
// Get the barcode type from user's selection in the combobox
reader.BarcodeTypesToFind = Barcode.GetBarcodeTypeToFindFromCombobox(type);
// Read barcodes from image bytes
reader.ReadFromMemory(bitmapArrayOfBytes);
// Check whether the barcode is decoded
if (reader.FoundBarcodes != null)
{
// Add each decoded barcode into the string
foreach (FoundBarcode barcode in reader.FoundBarcodes)
{
// Add barcodes as text into the output string
send.AppendLine(String.Format("{0} : {1}", barcode.Type, barcode.Value));
}
}
// Return the output string as JSON
return Json(new { d = send.ToString() });
}
}
catch (Exception ex)
{
// return the exception instead
return Json(new { d = ex.Message + "\r\n" + ex.StackTrace });
}
}
[HttpPost]
public ActionResult UploadFlash(string type)
{
try
{
String send = "";
System.Drawing.Image originalimg;
// read barcode type set
MemoryStream log = new MemoryStream();
byte[] buffer = new byte[1024];
int c;
// read input buffer with image and saving into the "log" memory stream
while ((c = Request.InputStream.Read(buffer, 0, buffer.Length)) > 0)
{
log.Write(buffer, 0, c);
}
// create image object
originalimg = System.Drawing.Image.FromStream(log);
// resample image
originalimg = originalimg.GetThumbnailImage(640, 480, new System.Drawing.Image.GetThumbnailImageAbort(() => { return false; }), IntPtr.Zero);
Bitmap bp = new Bitmap(originalimg);
bp.Save("c:\\temp\\barcode.jpg", ImageFormat.Jpeg);
// create bytescout barcode reader object
Reader reader = new Reader();
// set barcode type to read
reader.BarcodeTypesToFind = Barcode.GetBarcodeTypeToFindFromCombobox(type);
// read barcodes from image
reader.ReadFrom(bp);
// if there are any result then convert them into a single stream
if (reader.FoundBarcodes != null)
{
foreach (FoundBarcode barcode in reader.FoundBarcodes)
{
// form the output string
send = send + (String.Format("{0} : {1}", barcode.Type, barcode.Value));
}
}
// close the memory stream
log.Close();
// dispose the image object
originalimg.Dispose();
// write output
return Content("<d>" + send + "</d>");
}
catch (Exception ex)
{
// write the exception if any
return Content("<d>" + ex + "</d>");
}
}
}
}
index.js
var canvas, context, timer;
var constraints = window.constraints = {
audio: false,
video: { facingMode: "environment" } // change to "user" for front camera (see https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/facingMode )
};
// (HTML5 based camera only) this portion of code will be used when browser supports navigator.getUserMedia ********* */
window.addEventListener("DOMContentLoaded", function () {
canvas = document.getElementById("canvasU"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
videoObj = { "video": true },
errBack = function (error) {
console.log("Video capture error: ", error.code);
};
// check if we can use HTML5 based camera (through mediaDevices.getUserMedia() function)
if (navigator.mediaDevices.getUserMedia) { // Standard browser
// display HTML5 camera
document.getElementById("userMedia").style.display = '';
// adding click event to take photo from webcam
document.getElementById("snap").addEventListener("click", function () {
context.drawImage(video, 0, 0, 640, 480);
});
navigator.mediaDevices
.getUserMedia(constraints)
.then(handleSuccess)
.catch(handleError);
}
// check if we can use HTML5 based camera (through .getUserMedia() function in Webkit based browser)
else if (navigator.webkitGetUserMedia) { // WebKit-prefixed for Google Chrome
// display HTML5 camera
document.getElementById("userMedia").style.display = '';
// adding click event to take photo from webcam
document.getElementById("snap").addEventListener("click", function () {
context.drawImage(video, 0, 0, 640, 480);
});
navigator.webkitGetUserMedia(videoObj, function (stream) {
video.src = window.webkitURL.createObjectURL(stream);
video.play();
}, errBack);
}
// check if we can use HTML5 based camera (through .getUserMedia() function in Firefox based browser)
else if (navigator.mozGetUserMedia) { // moz-prefixed for Firefox
// display HTML5 camera
document.getElementById("userMedia").style.display = '';
// adding click event to take photo from webcam
document.getElementById("snap").addEventListener("click", function () {
context.drawImage(video, 0, 0, 640, 480);
});
navigator.mozGetUserMedia(videoObj, function (stream) {
video.mozSrcObject = stream;
video.play();
}, errBack);
}
else
// if we can not use any of HTML5 based camera ways then we use Flash based camera
{
// display Flash camera
document.getElementById("flashDiv").style.display = '';
document.getElementById("flashOut").innerHTML = (webcam.get_html(640, 480));
}
}, false);
// (all type of camera) set the default selection of barcode type
var selection = "All barcodes (slow)";
// (all type of camera) gets the selection text of "barcode type to scan" combobox
function selectType(type) {
selection = type.options[type.selectedIndex].text;
}
function handleSuccess(stream) {
var video = document.querySelector('video');
var videoTracks = stream.getVideoTracks();
console.log('Got stream with constraints:', constraints);
console.log(`Using video device: ${videoTracks[0].label}`);
window.stream = stream; // make variable available to browser console
video.srcObject = stream;
}
function handleError(error) {
if (error.name === 'ConstraintNotSatisfiedError') {
var v = constraints.video;
errorMsg(`The resolution ${v.width.exact}x${v.height.exact} px is not supported by your device.`);
} else if (error.name === 'PermissionDeniedError') {
errorMsg('Permissions have not been granted to use your camera and ' +
'microphone, you need to allow the page access to your devices in ' +
'order for the demo to work.');
}
errorMsg(`getUserMedia error: ${error.name}`, error);
}
function errorMsg(msg, error) {
var errorElement = document.querySelector('#errorMsg');
errorElement.innerHTML += `<p>${msg}</p>`;
if (typeof error !== 'undefined') {
console.error(error);
}
}
// (HTML5 based camera only)
// uploads the image to the server
function UploadToCloud() {
document.getElementById('report').innerHTML = "scanning the current frame......";
context.drawImage(video, 0, 0, 640, 480);
$("#upload").attr('disabled', 'disabled');
$("#upload").attr("value", "Uploading...");
var img = canvas.toDataURL('image/jpeg', 0.9).split(',')[1];
// send AJAX request to the server with image data
$.ajax({
url: "/Home/UploadHtml5",
type: "POST",
data: "{ 'image': '" + img + "' , 'type': '" + selection + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
// on success output the result returned by the server side (See HTML5Camera.aspx)
success: function (data, status) {
$("#upload").removeAttr('disabled');
$("#upload").attr("value", "Upload");
if (data.d.length != 0) {
var htmlSelect = document.getElementById('OutListBoxHTML5');
//var selectBoxOption = document.createElement("option");
//selectBoxOption.text = data.d;
//selectBoxOption.id = "child";
//htmlSelect.insertBefore(selectBoxOption, htmlSelect.childNodes[0]);
htmlSelect.value = data.d + "\r\n" + htmlSelect.value;
}
},
// on error just show the message that no barcodes were found
error: function (data) {
document.getElementById('report').innerHTML = "no barcode found, scanning.....";
$("#upload").removeAttr('disabled');
$("#upload").attr("value", "Upload");
},
async: false
});
timer = setTimeout(UploadToCloud, 3000); // will capture new image to detect barcode after 3000 mili second
}
// (flash based camera only) stop the capturing
function stopCall() {
document.getElementById('report').innerHTML = "STOPPED Scanning."
clearTimeout(timer);
}
// (flash based camera only) sets the handler for callback completition to output the result
Webcam.on('onComplete', 'my_completion_handler');
// (flash based camera only) this function will start flash to capture image and send the image to the server for further processing (for IE)
function take_snapshot() {
// set api to be called by flash camera
webcam.set_api_url('/home/UploadFlash?type=' + selection);
webcam.set_quality(100);
// enable the shutter sound
webcam.set_shutter_sound(true);
document.getElementById('upload_results').innerHTML = '<h4>Scanning...</h4>';
// capture image from the webcam
webcam.snap();
// set timout to capter new image (interval between captures)
timer = setTimeout(take_snapshot, 3000);
}
// (flash based camera only) this one will work after recieving barcode from server
// this function writes the output result back to the front page (from server side)
function my_completion_handler(msg) {
var str = msg;
// encode into html compatible string
var result = str.match(/<d>(.*?)<\/d>/g).map(function (val) {
return val.replace(/<\/?d>/g, '');
});
// add new result into the listbox
var htmlSelect = document.getElementById('OutListBoxFlash');
//var selectBoxOption = document.createElement("option");
//selectBoxOption.text = result;
//selectBoxOption.id = "child";
//htmlSelect.insertBefore(selectBoxOption, htmlSelect.childNodes[0]);
htmlSelect.value = result + "\r\n" + htmlSelect.value;
// reset webcam and flash to capture new image. this reset process flickers a little
webcam.reset();
}
// (flash based camera only) stop the scan and set the message on the page
function stopScanning() {
document.getElementById('upload_results').innerHTML = "STOPPED Scanning."
clearTimeout(timer);
}
jquery-1.4.2.js
��/ *
* j Q u e r y J a v a S c r i p t L i b r a r y v 1 . 4 . 2
* C o p y r i g h t 2 0 1 0 , J o h n R e s i g , h t t p : / / j q u e r y . c o m /
* D i s t r i b u t e d i n w h o l e u n d e r t h e t e r m s o f t h e M I T l i c e n s e
* h t t p : / / w w w . o p e n s o u r c e . o r g / l i c e n s e s / m i t - l i c e n s e . p h p
*
* I n c l u d e s S i z z l e . j s
* h t t p : / / s i z z l e j s . c o m /
* C o p y r i g h t 2 0 1 0 , T h e D o j o F o u n d a t i o n
* R e l e a s e d u n d e r t h e M I T , B S D , a n d G P L L i c e n s e s .
* /
( f u n c t i o n ( w i n d o w , u n d e f i n e d ) {
/ / D e f i n e a l o c a l c o p y o f j Q u e r y
v a r j Q u e r y = f u n c t i o n ( s e l e c t o r , c o n t e x t ) {
/ / T h e j Q u e r y o b j e c t i s a c t u a l l y j u s t t h e i n i t c o n s t r u c t o r ' e n h a n c e d '
r e t u r n n e w j Q u e r y . f n . i n i t ( s e l e c t o r , c o n t e x t ) ;
} ,
/ / M a p o v e r j Q u e r y i n c a s e o f o v e r w r i t e
_ j Q u e r y = w i n d o w . j Q u e r y ,
/ / M a p o v e r t h e $ i n c a s e o f o v e r w r i t e
_ $ = w i n d o w . $ ,
/ / U s e t h e c o r r e c t d o c u m e n t a c c o r d i n g l y w i t h w i n d o w a r g u m e n t ( s a n d b o x )
d o c u m e n t = w i n d o w . d o c u m e n t ,
/ / A c e n t r a l r e f e r e n c e t o t h e r o o t j Q u e r y ( d o c u m e n t )
r o o t j Q u e r y ,
/ / A s i m p l e w a y t o c h e c k f o r H T M L s t r i n g s o r I D s t r i n g s
/ / ( b o t h o f w h i c h w e o p t i m i z e f o r )
q u i c k E x p r = / ^ [ ^ <