Quantcast
Channel: Barcode – Dynamsoft Developers
Viewing all 145 articles
Browse latest View live

How to Read Barcode in WPF with VB.NET

$
0
0

We’re proud to reveal that Dynamsoft’s Dynamic .NET TWAIN 5.0 is on its way to release soon. In addition to WinForms support, the new version will include a WPF control. You can use it in your WPF app to capture images from TWAIN scanners and UVC/WIA webcams, to edit and save images to local disks, to a server or a database. Today, I’d like to cover how, using VB.NET, you can use the Dynamic .NET TWAIN 5.0 SDK to implement barcode reading in a WPF application.

The relevant source code can be downloaded here.

Barcode Demo

1.        Create a New WPF Project

First, start Visual Studio .NET, and create a new WPF project. Select Visual Basic as the type and choose WPF Application as the template.

Create WPF Project

2.        Add a Reference

Right-click on the project root, and select Add Reference… from the menu. Click Browse to locate DynamicDotNetTWAIN.dll and add it.

WPF Reference

3.      Add Dynamic .NET TWAIN Component

If there is no Dynamic .NET TWAIN component available, you might need to open the toolbox. To do so, right-click on the panel and select Choose Items… Switch to the tab WPF Components and click Browse… to load DynamicDotNetTWAIN.Wpf.dll

 WPF Component

4.         Add Buttons and Textbox

Next, you’ll want to drag two buttons and one textbox from the toolbox to design a form. The buttons are used to load an image and make the detection of a barcode. And, the textbox is used to display the information decoded from barcode.

WPF Button

5.         Code for Loading Image

Now, what you need to do is to acquire an image using the Windows standard API. Then you’ll need to load it using the Dynamic .NET TWAIN component method. Just a couple of lines of code are needed for loading an image. It’s pretty simple.

       Dim filedlg As OpenFileDialog
        filedlg = New OpenFileDialog()
        filedlg.Multiselect = True
       Dim strFilename As String
        If (filedlg.ShowDialog() = DialogResult.OK) Then
            For Each strFilename In filedlg.FileNames
                DynamicDotNetTwain1.LoadImage(strFilename)
            Next
        End If

6.         Code for Barcode Recognition

To decode a barcode, the path for the barcode library needs to be first be specified. Then, with one additional line of code, you’ll get results.

Set the path of barcode library

        Dim strDllFolder As String
        strDllFolder = Application.ExecutablePath
        Dim pos As Integer
        pos = strDllFolder.LastIndexOf("\Samples\")
        If (pos <> -1) Then
            strDllFolder = strDllFolder.Substring(0, strDllFolder.IndexOf("\", pos)) + "\Bin\BarcodeResources\"
        End If
        Me.DynamicDotNetTwain1.BarcodeDllPath = strDllFolder

Get the results and display them on screen

        Me.TextBox1.Text = ""
        Dim aryResult() As Result
        aryResult = Me.DynamicDotNetTwain1.ReadBarcode(Me.DynamicDotNetTwain1.CurrentImageIndexInBuffer, BarcodeFormat.All)
        Dim strText As StringBuilder
        strText = New StringBuilder()
        If aryResult.Length = 1 Then
            strText.AppendFormat(aryResult.Length & " total barcode" & ("") & " found." & Constants.vbCrLf)
        Else
            strText.AppendFormat(aryResult.Length & " total barcode" & ("s") & " found." & Constants.vbCrLf)
        End If
        For i As Integer = 0 To aryResult.Length - 1
            Dim objResult As Result
            objResult = aryResult(i)
            strText.AppendFormat("      Result " & (i + 1) & Constants.vbCrLf)
            strText.AppendFormat("      BarcodeFormat: " & objResult.BarcodeFormat.ToString() & Constants.vbCrLf)
            strText.AppendFormat("      Text read: " & objResult.Text & Constants.vbCrLf)
        Next i
        Me.TextBox1.Text = strText.ToString()

I hope this brief tutorial is helpful to anyone who is looking for a .NET barcode reader SDK in VB.NET.

For further inquiries, please feel free to send me an email at kgao[at]dynamsoft.com.

Dynamic .NET TWAIN 5.0 is scheduled to be released late next month. To stay informed about all our product announcements, blog posts and more, be sure to follow us on Twitter, like us on Facebook or add us on Google+. Also, if you’d like to be amongst the first to try out the new version first, please contact support[at]dynamsoft.com.


Have Fun with the WPF Demo of .NET TWAIN 5.0

$
0
0

Dynamic .NET TWAIN 5.0 has been released for a while. To help users to quickly grasp APIs, a brand-new API demo, written in WPF with C# & VB.NET, is included. In this tutorial, we would like to show the anatomy of this application. Let’s glance at the screenshot as a warm up. As you can see, the functionalities of the demo include scanner control, image loading, barcode recognition, OCR, image manipulation and processing.

WPF UI

How to install Dynamic .NET TWAIN 5.0?

Visit Dynamic .NET TWAIN page and get the installation package by clicking Download button. Follow the InstallShield Wizard step by step.

Where is the API demo?

The demo source code is located at “…\Dynamsoft\Dynamic .NET TWAIN 5.0 Trial\Samples\C# Samples\VS 12” and “…\Dynamsoft\Dynamic .NET TWAIN 5.0 Trial\Samples\VB .NET Samples\VS 12\WpfControlsDemo”. You can choose your preferred programming language, C# or VB.NET.

What does the project look like in Visual Studio?

WPF project

The reference DynamicDotNetTWAIN.Wpf.dll is located at “…\Dynamsoft\Dynamic .NET TWAIN 5.0 Trial\Samples\Bin”. It will be copied to your project folder when you run the Visual Studio solution file “WpfControlsDemo.sln”. If you want to create your own project, don’t forget to add it. In this project, we have created three windows. The main window is “Window1.xaml”.

How to use the relevant APIs to implement following functions?

All implementation logics are same no matter which language you choose. Let’s illustrate with C#.

Initialize

Set the paths of barcode library, OCR library and OCR language package.

dynamicDotNetTwainThum.BarcodeDllPath = dynamicDotNetTwainDirectory + @"Redistributable\BarcodeResources\"; // barcode library
dynamicDotNetTwainThum.OCRDllPath = dynamicDotNetTwainDirectory + @"Redistributable\OCRResources\"; // OCR library
dynamicDotNetTwainThum.OCRTessDataPath = dynamicDotNetTwainDirectory + @"Redistributable\"; // OCR language package

Scan

The “ScanWindow.xaml” is used for scan window.

scan window

To run this window from the main window:

ScanWindow scanWnd = new ScanWindow();
scanWnd.Owner = this;
scanWnd.TWAIN = dynamicDotNetTwainThum;
scanWnd.ShowDialog();

scan UI

To acquire the TWAIN sources, and scan the image:

for (int i = 0; i < twain.SourceCount; i ++)
{
   cbxSources.Items.Add(twain.SourceNameItems((short)i)); // get & add source names
}
twain.ScanInNewThread = true;
twain.SelectSourceByIndex(cbxSources.SelectedIndex);
twain.OpenSource(); // open selected source
twain.IfShowUI = ckbShowUI.IsChecked.Value;
twain.IfFeederEnabled = ckbADF.IsChecked.Value;
twain.IfDuplexEnabled = ckbDuplex.IsChecked.Value;
if (rbBW.IsChecked.Value)
{
    twain.PixelType = Dynamsoft.DotNet.TWAIN.Enums.TWICapPixelType.TWPT_BW;
                    twain.BitDepth = 1;
}
else if (rbGrey.IsChecked.Value)
{
   twain.PixelType = Dynamsoft.DotNet.TWAIN.Enums.TWICapPixelType.TWPT_GRAY;
                    twain.BitDepth = 8;
}
else if (rbColorful.IsChecked.Value)
{
   twain.PixelType = Dynamsoft.DotNet.TWAIN.Enums.TWICapPixelType.TWPT_RGB;
                    twain.BitDepth = 24;
}
twain.AcquireImage(); // acquire image from scanner

Load

load image

When loading an image from the disk, we can get the thumbnail from the original image.

To get the thumbnail:

dynamicDotNetTwainThum.LoadImage(strFileName);

To display the large image:

Clipboard.Clear();
dynamicDotNetTwainThum.CopyToClipboard(dynamicDotNetTwainThum.CurrentImageIndexInBuffer);
dynamicDotNetTwainView.RemoveAllImages();
dynamicDotNetTwainView.LoadDibFromClipboard(); // load the large image
Clipboard.Clear();

OCR

Let’s load an image file with text, and try OCR.

dynamicDotNetTwainThum.IfShowCancelDialogWhenBarcodeOrOCR = true;
dynamicDotNetTwainThum.OCRResultFormat = Dynamsoft.DotNet.TWAIN.OCR.ResultFormat.Text;
dynamicDotNetTwainThum.OCRLanguage = "eng";
byte[] bytes = dynamicDotNetTwainThum.OCR(dynamicDotNetTwainThum.CurrentSelectedImageIndicesInBuffer); // recognize the buffered image
if (bytes != null)
{
   SaveFileDialog dlg = new SaveFileDialog();
   dlg.Filter = "Text File(*.txt)|*.txt";
   if (dlg.ShowDialog().Value)
   {
      System.IO.File.WriteAllBytes(dlg.FileName, bytes); // write recognized text to text file
   }
}

OCR

OCR result

Barcode

We choose QR code for testing.

dynamicDotNetTwainThum.IfShowCancelDialogWhenBarcodeOrOCR = true;
Result[] results = dynamicDotNetTwainThum.ReadBarcode(dynamicDotNetTwainThum.CurrentImageIndexInBuffer, Dynamsoft.DotNet.TWAIN.Enums.Barcode.BarcodeFormat.All);
string strResult = results.Length + " total barcode found." + "\r\n";
for (int i = 0; i < results.Length; i++)
{
    strResult += "Result " + (i + 1) + "\r\n  " + "Barcode Format: " + results[i].BarcodeFormat + "    Barcode Text: " + results[i].Text + "\r\n";
}

load image

barcode result

To experience more interesting functions, just download the Dynamic .NET TWAIN 5.0 and have fun. Hopefully everyone can enjoy it. Please follow our Twitter, Facebook and Google+ if you have something to share with us.

How to Deploy JavaScript QR Code Generator to Google App Engine

$
0
0

Recently, I found an excellent jQuery plugin jquery.qrcode.js, which is written by Jerome Etienne. In this article, I would like to share how to use the QR code plugin to implement a free online app with Google App Engine. You can try my demo http://dynamsoft-test.appspot.com/.

qr code

How to Implement QR Code Generator

<script src="js/jquery.min.js"></script>
<script src="js/jquery.qrcode.min.js"></script>
<script src="js/utf-8.js"></script>
  • Create a text input, a button, and an area for QR code display.
<input type="text" id="text" placeholder="www.dynamsoft.com">
<button onclick="generate()">Try it</button>
<div id="output"></div>
  • Add JS code for button event.
function generate()
{
	jQuery(function(){
		var canvas = document.querySelector("canvas");
		if (canvas != null && canvas.parentNode) {
			canvas.parentNode.removeChild(canvas);
		}
		var text = document.getElementById("text");
		jQuery('#output').qrcode(Utf8.encode(text.value));
		text.value = "";
	})
}
  • You can run it now.

How to Deploy the App to Google App Engine

  • There are four programming languages supported. I would like to pick PHP.

application

  • Change the qrcode.html to qrcode.php.
  • Create a configuration file named app.yaml with the following contents:
application: dynamsoft-test
version: 1
runtime: php
api_version: 1

handlers:
- url: /stylesheets
  static_dir: stylesheets

- url: /js
  static_dir: js

- url: /.*
  script: qrcode.php
  • Modify the source code for loading css and scripts:
<link type="text/css" rel="stylesheet" href="/stylesheets/main.css" />
<script src="/js/jquery.min.js"></script>
<script src="/js/jquery.qrcode.min.js"></script>
<script src="/js/utf-8.js"></script>
  • In the command line tool, type in python google_appengine/dev_appserver.py qrcode/
  • Visit http://localhost:8080/ to check your app.
  • If there is no error, you can upload the project to Google App Engine by the command appcfg.py update qrcode/

Now, you can visit the app domain to have fun. If you have any questions, please feel free to contact {desmond at Dynamsoft dot com}.

 

Barcode Generator with HTML5 WebSocket

$
0
0

Last week, I shared how to transmit an image between a WebSocket server and a Web client. Based on that, we can make a little bit of improvement. Today, I would like to share how to generate barcode on .Net server side and display it on web browser.

websocket barcode

Prerequisites

Remote Barcode Generator

  • In your WinForms project, add DynamicBarcode.dll and set its property Copy to Output Directory as Copy always. As so, the Dynamic .NET TWAIN component is able to automatically load the barcode library.

barcode library

  • Encode the received message, and draw generated barcode onto a background image:
            float scale = 3;
            short sImageIndex = 0;
            dynamicDotNetTwain.MaxImagesInBuffer = 1;
            bool isLoaded = dynamicDotNetTwain.LoadImage("test.png");
            dynamicDotNetTwain.AddBarcode(sImageIndex, Dynamsoft.DotNet.TWAIN.Enums.Barcode.BarcodeFormat.QR_CODE, message, "", 0, 0, scale);
  • Send image width, height and data to web client:
            Image img = dynamicDotNetTwain.GetImage(sImageIndex);

            ImageData imageData = load_image(img);
            session.Send(imageData.Width + "," + imageData.Height);
            session.Send(imageData.Data, 0, imageData.Data.Length);
            imageData = null;
  • Display the barcode image on JavaScript web client:
               ws.onmessage = function (evt) {
                    var data = evt.data;
                    if (!data)
                        return;

                    if (data instanceof ArrayBuffer) {
                        drawImage(evt.data);
                    }
                    else {
                        var len = data.length;
                        var index = data.indexOf(",");
                        var w = data.substring(0, index);
                        var h = data.substring(index + 1, len);
                        imageWidth = parseInt(w);
                        imageHeight = parseInt(h);
                    }
                };

Now, you can have fun with the remote barcode generator via all browsers (Chrome, Firefox, IE etc.) which support HTML5 WebSocket.

Source Code

WebSocketBarcodeGenerator

 

How to Build a Web App to Read PDF417 Barcode with DWT

$
0
0

If you have upgraded to the latest HTML5 version of DWT (Dynamic Web TWAIN), probably you have noticed that it only supports 1D barcode reading. Although the 2D barcode SDK has not been officially released yet, it is coming soon. Today, I’d like to demo how to build a Web application to read PDF417 barcode with DWT in advance.

read pdf417 barcode

Barcode Reading Steps

  1. Scan or load an image of a driver’s license.
  2. Get barcode results from DWT native server.
  3. Display results in corresponding fields on Web client side.

Coding with DWT SDK

Put Barcode.zip and Barcodex64.zip in Resources.

Create index.html with the following code:

<!DOCTYPE html>
<html>
<head>
    <title>Use Dynamic Web TWAIN to Read Barcode</title>
	<style> 
		#mainWindow {
			width:600px;
			margin:0px auto;
			padding:15px;
			background-color:#eee;
		}
	</style>
    <script type="text/javascript" src="Resources/dynamsoft.webtwain.initiate.js"> </script>
    <script type="text/javascript" src="Resources/dynamsoft.webtwain.config.js"> </script>
</head>

<body>
	<div id="mainWindow">
	<H1> Dynamic Web TWAIN - Driver's Licenses</H1>
    <input type="button" value="Scan" onclick="AcquireImage();" />
    <input type="button" value="Load" onclick="LoadImage();" />
    <input type="button" value="Read Driver License" onclick="ReadBarcode();" /> <br/>

    First Name: <input type="text" id="FirstName" />
    Last Name: <input type="text" id="LastName"/> <br />
    City: <input type="text" id="City" />
    Address: <input type="text" id="Address" />
    License Number: <input type="text" id="LicenseNumber" /> <br />
    State: <input type="text" id="State" />
    Zip: <input type="text" id="Zip" />

    <!-- dwtcontrolContainer is the default div id for Dynamic Web TWAIN control.
         If you need to rename the id, you should also change the id in the dynamsoft.webtwain.config.js accordingly. -->
    <div id="dwtcontrolContainer"></div>

    <script type="text/javascript">
        Dynamsoft.WebTwainEnv.RegisterEvent('OnWebTwainReady', Dynamsoft_OnReady); // Register OnWebTwainReady event. This event fires as soon as Dynamic Web TWAIN is initialized and ready to be used

        var DWObject;
        var text;

        function Dynamsoft_OnReady() {
            DWObject = Dynamsoft.WebTwainEnv.GetWebTwain('dwtcontrolContainer'); // Get the Dynamic Web TWAIN object that is embeded in the div with id 'dwtcontrolContainer'

        }

        function AcquireImage() {
            if (DWObject) {
                DWObject.SelectSource();
                DWObject.OpenSource();
                DWObject.IfDisableSourceAfterAcquire = true;	// Scanner source will be disabled/closed automatically after the scan.
                DWObject.AcquireImage();
            }
        }

        //Callback functions for async APIs
        function OnSuccess() {
            console.log('successful');
        }

        function OnFailure(errorCode, errorString) {
            alert(errorString);
        }

        function LoadImage() {
            if (DWObject) {
                DWObject.IfShowFileDialog = true; // Open the system's file dialog to load image
                DWObject.LoadImageEx("", EnumDWT_ImageType.IT_ALL, OnSuccess, OnFailure); // Load images in all supported formats (.bmp, .jpg, .tif, .png, .pdf). OnSuccess or OnFailure will be called after the operation
            }
        }

        function GetField(keyword) {

            var k = text.search(keyword);
            var n = text.indexOf(":", k);
            var m = text.indexOf("\n", n);
            var subtext = text.substring(n+1, m);
            return subtext;
        }

        function GetBarcodeInfo(sImageIndex, result) {//This is the function called when barcode is read successfully
            //Retrieve barcode details
            var count = result.GetCount();
            if (count == 0) {
                alert("The barcode for the selected format is not found.");
                return;
            } else {
                for (i = 0; i < count; i++) {
                    text = result.GetContent(i);
                    var x = result.GetX1(i);
                    var y = result.GetY1(i);
                    var format = result.GetFormat(i);
                    var barcodeText = ("barcode[" + (i + 1) + "]: " + "\n" + text + "\n");
                    //barcodeText += ("format: PDF 417" + "\n");
                    //barcodeText += ("x: " + x + " y:" + y + "\n");
                    //var strBarcodeString = text + "\r\n" + (format == 4 ? "Code 39" : "Code 128");
                    //DWObject.AddText(DWObject.CurrentImageIndexInBuffer, x, y, strBarcodeString, -1, 94700, 0, 1);
                    // alert(barcodeText);   // get driver license info

                    alert(text);
                    if (text.search("Given Name") == -1)
                        document.getElementById("FirstName").value = GetField("First Name");
                    else
                        document.getElementById("FirstName").value = GetField("Given Name");
                    document.getElementById("LastName").value = GetField("Last Name");
                    document.getElementById("LicenseNumber").value = GetField("License Number");
                    document.getElementById("State").value = GetField("State");
                    document.getElementById("City").value = GetField("City");
                    document.getElementById("Address").value = GetField("Address");
                    document.getElementById("Zip").value = GetField("Zip");

                }
            }
        }

        function ReadBarcode() {

            if (DWObject) {
                if (DWObject.Addon.Barcode.GetLocalVersion() == "9, 6, 2, 303") {
                    if (DWObject.HowManyImagesInBuffer == 0) {
                        alert("Please scan or load an image first.");
                        return;
                    }

                    result = DWObject.Addon.Barcode.Read(
                            DWObject.CurrentImageIndexInBuffer, 1024, GetBarcodeInfo, OnFailure);
                }
                else {
                    DWObject.Addon.Barcode.Download("\\Resources\\Barcode.zip",ReadBarcode,OnFailure);
                }
            }
        }
    </script>
	</div>
</body>
</html>

Deploy the project to your Web server, and test it:

Source Code

https://github.com/DynamsoftRD/pdf417-barcode-reader

git clone https://github.com/DynamsoftRD/pdf417-barcode-reader.git

How to Make Java Barcode Reader with Dynamsoft Barcode SDK

$
0
0

Last week, Dynamsoft released Barcode Reader (DBR) SDK v2.0, which is available for Windows and Mac. The Windows installer contains Barcode libraries for ActiveX, C/C++, and .NET. If you are a Java developer, you have to use JNI to link native C/C++ libraries. In this tutorial, I’ll demonstrate how to invoke the native methods of Dynamsoft Barcode SDK via JNI to create a Java Barcode Reader.

Dynamsoft Barcode Reader SDK

Ads Powered by Dynamsoft

JNI for Linking Dynamsoft Barcode Reader DLL

Download and install Dynamsoft Barcode Reader.DBR download button

dbr folder

Create a new Java project in Eclipse. We need a Class for calling native methods.

package com.dynamsoft.barcode;

import java.util.Properties;

public class JBarcode {

	static {

		try {
			// get arch
			Properties props = System.getProperties();
			String bits = String.valueOf(props.get("sun.arch.data.model"));
			if (bits.equals("32")) {
				bits = "86";
			}

			String jniLib = "DynamsoftBarcodeJNIx" + bits;

			// load dll
			System.loadLibrary(jniLib);
		} catch (Exception e) {
			System.err.println("load jni error!");
		}

}

    public native static int DBR_InitLicense(
		String pLicense	//License Key
	);

    public native static int DBR_DecodeFile(
		String pFileName,

		int option_iMaxBarcodesNumPerPage,
		long option_lBarcodeFormat,

		tagBarcodeResultArray ppResults	//Barcode Results
	);	

    public native static int DBR_DecodeFileRect(
		String pFileName,

		int option_iMaxBarcodesNumPerPage,
		long option_lBarcodeFormat,

		int iRectLeft,			//Rectangle Left
		int iRectTop,			//Rectangle Top
		int iRectWidth,			//Rectangle 
		int iRectHeight,		//Rectangle 
		tagBarcodeResultArray ppResults	// Barcode Results
	);

    public native static int DBR_DecodeBuffer(
		byte[] pDIBBuffer,	//Buffer
        int iDIBSize,

		int option_iMaxBarcodesNumPerPage,
		long option_lBarcodeFormat,

        tagBarcodeResultArray ppResults	//Barcode Results
	);

    public native static int DBR_DecodeBufferRect(
		byte[] pDIBBuffer,	//Buffer
        int iDIBSize,	

		int option_iMaxBarcodesNumPerPage,
		long option_lBarcodeFormat,

        int iRectLeft,			//Rectangle Left
        int iRectTop,			//Rectangle Top
        int iRectWidth,			//Rectangle 
        int iRectHeight,		//Rectangle 
        tagBarcodeResultArray ppResults	//Barcode Results
	);

    public native String GetErrorString(int iErrorCode);

}

Create a new DLL project in Visual Studio, and then add Include directories of JDK and DBR.

dbr include

Add Library directories of DBR.

dbr lib

Declare JNI methods in a header file.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_dynamsoft_barcode_JBarcode */

#ifndef _Included_com_dynamsoft_barcode_JBarcode
#define _Included_com_dynamsoft_barcode_JBarcode

extern "C" {
/*
 * Class:     com_dynamsoft_barcode_JBarcode
 * Method:    DBR_InitLicense
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1InitLicense
  (JNIEnv *, jclass, jstring);

/*
 * Class:     com_dynamsoft_barcode_JBarcode
 * Method:    DBR_DecodeFile
 * Signature: (Ljava/lang/String;IJLcom/dynamsoft/barcode/tagBarcodeResultArray;)I
 */
JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeFile
  (JNIEnv *, jclass, jstring, jint, jlong, jobject);

/*
 * Class:     com_dynamsoft_barcode_JBarcode
 * Method:    DBR_DecodeFileRect
 * Signature: (Ljava/lang/String;IJIIIILcom/dynamsoft/barcode/tagBarcodeResultArray;)I
 */
JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeFileRect
  (JNIEnv *, jclass, jstring, jint, jlong, jint, jint, jint, jint, jobject);

/*
 * Class:     com_dynamsoft_barcode_JBarcode
 * Method:    DBR_DecodeBuffer
 * Signature: ([BIIJLcom/dynamsoft/barcode/tagBarcodeResultArray;)I
 */
JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeBuffer
  (JNIEnv *, jclass, jbyteArray, jint, jint, jlong, jobject);

/*
 * Class:     com_dynamsoft_barcode_JBarcode
 * Method:    DBR_DecodeBufferRect
 * Signature: ([BIIJIIIILcom/dynamsoft/barcode/tagBarcodeResultArray;)I
 */
JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeBufferRect
  (JNIEnv *, jclass, jbyteArray, jint, jint, jlong, jint, jint, jint, jint, jobject);

/*
 * Class:     com_dynamsoft_barcode_JBarcode
 * Method:    GetErrorString
 * Signature: (I)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_dynamsoft_barcode_JBarcode_GetErrorString
  (JNIEnv *, jclass, jint);

}
#endif

Add implementations in relevant CPP file. Make sure your Visual Studio can find the included header files and libraries.

#include "com_dynamsoft_barcode_JBarcode.h"

// BarcodeReaderDemo.cpp : Defines the entry point for the console application.

#include <windows.h>
#include "../../../Include/If_DBR.h"
#include "../../../Include/BarcodeFormat.h"
#include "../../../Include/BarcodeStructs.h"
#include "../../../Include/ErrorCode.h"

#ifdef _WIN64
#pragma comment(lib, "DBRx64.lib")
#else
#pragma comment(lib, "DBRx86.lib")
#endif

bool isGetClassBarcodeResult = false;
jclass    br_m_cls   = NULL;
jmethodID br_m_mid   = NULL;
jfieldID  br_m_Format = NULL;
jfieldID  br_m_BarcodeData = NULL;
jfieldID  br_m_BarcodeDataLength = NULL;
jfieldID  br_m_Left = NULL;
jfieldID  br_m_Top = NULL;
jfieldID  br_m_Width = NULL;
jfieldID  br_m_Height = NULL;
jfieldID  br_m_X1 = NULL;
jfieldID  br_m_Y1 = NULL;
jfieldID  br_m_X2 = NULL;
jfieldID  br_m_Y2 = NULL;
jfieldID  br_m_X3 = NULL;
jfieldID  br_m_Y3 = NULL;
jfieldID  br_m_X4 = NULL;
jfieldID  br_m_Y4 = NULL;
jfieldID  br_m_PageNum = NULL;

bool isGetClassBarcodeArrayResult = false;
jclass    brAry_cls   = NULL;
jmethodID brAry_mid   = NULL;
jfieldID  brAry_field_count = NULL;
jfieldID  brAry_field_brResult = NULL;

void loadJavaClassInfo(JNIEnv *env){
	if(!isGetClassBarcodeResult){
		br_m_cls   = env->FindClass("com/dynamsoft/barcode/tagBarcodeResult");
		br_m_mid   = env->GetMethodID(br_m_cls,"<init>","()V");

		br_m_Format = env->GetFieldID(br_m_cls,"lFormat","J");
		br_m_BarcodeData = env->GetFieldID(br_m_cls,"pBarcodeData","[B");
		br_m_BarcodeDataLength = env->GetFieldID(br_m_cls,"iBarcodeDataLength","I");
		br_m_Left = env->GetFieldID(br_m_cls,"iLeft","I");
		br_m_Top = env->GetFieldID(br_m_cls,"iTop","I");
		br_m_Width = env->GetFieldID(br_m_cls,"iWidth","I");
		br_m_Height = env->GetFieldID(br_m_cls,"iHeight","I");
		br_m_X1 = env->GetFieldID(br_m_cls,"iX1","I");
		br_m_Y1 = env->GetFieldID(br_m_cls,"iY1","I");
		br_m_X2 = env->GetFieldID(br_m_cls,"iX2","I");
		br_m_Y2 = env->GetFieldID(br_m_cls,"iY2","I");
		br_m_X3 = env->GetFieldID(br_m_cls,"iX3","I");
		br_m_Y3 = env->GetFieldID(br_m_cls,"iY3","I");
		br_m_X4 = env->GetFieldID(br_m_cls,"iX4","I");
		br_m_Y4 = env->GetFieldID(br_m_cls,"iY4","I");
		br_m_PageNum = env->GetFieldID(br_m_cls,"iPageNum","I");
		isGetClassBarcodeResult = true;
	}

	if(!isGetClassBarcodeArrayResult){
	    brAry_cls   = env->FindClass("com/dynamsoft/barcode/tagBarcodeResultArray");
		brAry_mid   = env->GetMethodID(brAry_cls,"<init>","()V");
		brAry_field_count = env->GetFieldID(brAry_cls,"iBarcodeCount","I");
		brAry_field_brResult = env->GetFieldID(brAry_cls,"ppBarcodes","[Lcom/dynamsoft/barcode/tagBarcodeResult;");
		isGetClassBarcodeArrayResult = true;
	}
}

jobject convertResultToJNIObject(JNIEnv *env, pBarcodeResult pBarcode){

	loadJavaClassInfo(env);

    jobject obj = env->NewObject(br_m_cls, br_m_mid);

	jbyteArray rtnbytes = env->NewByteArray((jsize)(pBarcode->iBarcodeDataLength)); 
	env->SetByteArrayRegion(rtnbytes, 0, (jsize)(pBarcode->iBarcodeDataLength), (jbyte*)pBarcode->pBarcodeData); 

	env->SetLongField(obj, br_m_Format, pBarcode->llFormat);
	env->SetObjectField(obj, br_m_BarcodeData, rtnbytes);
	env->SetIntField(obj, br_m_BarcodeDataLength, pBarcode->iBarcodeDataLength);
	env->SetIntField(obj, br_m_Left, pBarcode->iLeft);
	env->SetIntField(obj, br_m_Top, pBarcode->iTop);
	env->SetIntField(obj, br_m_Width, pBarcode->iWidth);
	env->SetIntField(obj, br_m_Height, pBarcode->iHeight);
	env->SetIntField(obj, br_m_X1, pBarcode->iX1);
	env->SetIntField(obj, br_m_Y1, pBarcode->iY1);
	env->SetIntField(obj, br_m_X2, pBarcode->iX2);
	env->SetIntField(obj, br_m_Y2, pBarcode->iY2);
	env->SetIntField(obj, br_m_X3, pBarcode->iX3);
	env->SetIntField(obj, br_m_Y3, pBarcode->iY3);
	env->SetIntField(obj, br_m_X4, pBarcode->iX4);
	env->SetIntField(obj, br_m_Y4, pBarcode->iY4);
	env->SetIntField(obj, br_m_PageNum, pBarcode->iPageNum);

	return obj;
}

void fillBarcodeResultArray(JNIEnv *env, jobject obj, pBarcodeResultArray pArrayResults){

	loadJavaClassInfo(env);

	int count = pArrayResults->iBarcodeCount;
	pBarcodeResult* ppBarcodes = pArrayResults->ppBarcodes;

	jobjectArray swArray = env->NewObjectArray(count, br_m_cls, 0); 

	for(int i=0; i<count; i++){
		env->SetObjectArrayElement(swArray, i, convertResultToJNIObject(env, ppBarcodes[i]));
	}

	env->SetIntField(obj, brAry_field_count, count);
	env->SetObjectField(obj, brAry_field_brResult, swArray);

}

void SetOptions(pReaderOptions pOption, jint option_iMaxBarcodesNumPerPage, jlong option_llBarcodeFormat){

	if(option_llBarcodeFormat > 0)
		pOption->llBarcodeFormat = option_llBarcodeFormat;
	else
		pOption->llBarcodeFormat = OneD;

	if(option_iMaxBarcodesNumPerPage > 0)
		pOption->iMaxBarcodesNumPerPage = option_iMaxBarcodesNumPerPage;
	else
		pOption->iMaxBarcodesNumPerPage = MAXINT;

}

JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1InitLicense
(JNIEnv *env, jclass, jstring pString){

	const char *nativeString = env->GetStringUTFChars(pString, 0);  

	//printf("%s", nativeString);
	int ret = DBR_InitLicense(nativeString);

	//DON'T FORGET THIS LINE!!!  
	env->ReleaseStringUTFChars(pString, nativeString);  

	return ret;
}

JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeFile
  (JNIEnv *env, jclass, jstring strFileName, jint option_iMaxBarcodesNumPerPage, jlong option_llBarcodeFormat, jobject pArrayResults)
{
	const char *pFileName = env->GetStringUTFChars(strFileName, 0);
	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	int ret = DBR_DecodeFile(
		pFileName,
		&option,
		&pResults
	);

	if(ret == DBR_OK){
		fillBarcodeResultArray(env, pArrayResults, pResults);
		DBR_FreeBarcodeResults(&pResults);
	}

	//DON'T FORGET THIS LINE!!!  
	env->ReleaseStringUTFChars(strFileName, pFileName);  
	return ret;
}

JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeFileRect
  (JNIEnv *env, jclass, jstring strFileName, jint option_iMaxBarcodesNumPerPage, jlong option_llBarcodeFormat, jint iRectLeft, jint iRectTop, jint iRectWidth, jint iRectHeight, jobject pArrayResults)
{
	const char *pFileName = env->GetStringUTFChars(strFileName, 0);
	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	int ret = DBR_DecodeFileRect(
		pFileName,
		&option,
		iRectLeft,	
		iRectTop,	
		iRectWidth,	
		iRectHeight,
		&pResults
	);

	if(ret == DBR_OK){

		fillBarcodeResultArray(env, pArrayResults, pResults);
		DBR_FreeBarcodeResults(&pResults);
	}

	//DON'T FORGET THIS LINE!!!  
	env->ReleaseStringUTFChars(strFileName, pFileName);  
	return ret;
}

JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeBuffer
  (JNIEnv *env, jclass, jbyteArray pDIBBuffer, jint iDIBSize, jint option_iMaxBarcodesNumPerPage, jlong option_llBarcodeFormat, jobject pArrayResults)
{
	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	int ret = DBR_DecodeBuffer(
		(unsigned char*) pDIBBuffer,		
		iDIBSize,
		&option,	
		&pResults
	);

	if(ret == DBR_OK){
		fillBarcodeResultArray(env, pArrayResults, pResults);
		DBR_FreeBarcodeResults(&pResults);
	}

	return ret;
}

JNIEXPORT jint JNICALL Java_com_dynamsoft_barcode_JBarcode_DBR_1DecodeBufferRect
  (JNIEnv *env, jclass, 
  jbyteArray pDIBBuffer, jint iDIBSize, jint option_iMaxBarcodesNumPerPage, jlong option_llBarcodeFormat, 
  jint iRectLeft, jint iRectTop, jint iRectWidth, jint iRectHeight, jobject pArrayResults)
{
	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	int ret = DBR_DecodeBufferRect(
		(unsigned char*) pDIBBuffer,		
		iDIBSize,
		&option,
		iRectLeft,	
		iRectTop,	
		iRectWidth,	
		iRectHeight,
		&pResults
	);

	if(ret == DBR_OK){
		fillBarcodeResultArray(env, pArrayResults, pResults);
		DBR_FreeBarcodeResults(&pResults);
	}

	return ret;
}

JNIEXPORT jstring JNICALL Java_com_dynamsoft_barcode_JBarcode_GetErrorString
  (JNIEnv *env, jclass, jint iErrorCode)
{
	const char *pError = GetErrorString( iErrorCode);
    return env->NewStringUTF(pError);
    // (*env)->ReleaseStringUTFChars(env, jstr, utf); 

}

Build the project, and copy the generated DLL and DBR DLL to the Java Barcode Reader project.

dbr java

Finally, we can specify the image file path as the argument, and run the Java project.

dbr argsdbr results

Source Code

https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/samples/Java

Wrapping C/C++ Methods of Dynamsoft Barcode SDK for Python

$
0
0

Previously, I shared an article – Make Java Barcode Reader with Dynamsoft Barcode SDK – demonstrating how to implement a Java Barcode Reader with Dynamsoft Barcode SDK. In this tutorial, I’d like to share how to wrap C/C++ methods of Dynamsoft Barcode SDK to create a Barcode extension for Python.

Dynamsoft Barcode Reader SDK

Ads Powered by Dynamsoft

Visual Studio Settings for Building Python Extensions on Windows

Let’s create a new win32 project named DynamsoftBarcodeReader in Visual Studio.
Open project properties, and include Python header files and libraries.
python_include python_lib

Add a dependency python27.lib.

python_dependency

Change the Target Extension to .pyd.

python_pyd

A .pyd file is same as DLL. It is the bridge between Python and C/C++. By default, the build configuration is Debug in Visual Studio. If you just build the project directly, you will see the following linkage error:

python build error

Why? The reason is that there is no python27_d.lib at all in Python’s official release package. If you want to link python27_d.lib, you have to download the source code and build a Debug version yourself. So, switch to Release and build the project.
building python successfully

Wrapping C/C++ Methods of Dynamsoft Barcode SDK for Python

Download and install Dynamsoft Barcode Reader.

DBR download button

 

 

When you import DynamsoftBarcodeReader in Python script, Python will search for DynamsoftBarcodeReader.pyd and then call initDynamsoftBarcodeReader() to make an initialization. Similar to JNI (Java Native Interface), we have to register the native methods that are accessible to Python.

Python native portal

Let’s add a method for decoding Barcode file. If you have learned the JNI sample code, you should be familiar with it. The only difference is that we need to convert final results to Python object type.

static PyObject *
decodeFile(PyObject *self, PyObject *args)
{
	char *pFileName;
	int option_iMaxBarcodesNumPerPage = -1;
	int option_llBarcodeFormat = -1;

	if (!PyArg_ParseTuple(args, "s", &pFileName)) {
		return NULL;
	}

	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	int ret = DBR_DecodeFile(
		pFileName,
		&option,
		&pResults
		);

	if (ret == DBR_OK){
		int count = pResults->iBarcodeCount;
		pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
		pBarcodeResult tmp = NULL;

		PyObject* list = PyList_New(count);
		PyObject* result = NULL;

		for (int i = 0; i < count; i++)
		{
			tmp = ppBarcodes[i];
			result = PyString_FromString(tmp->pBarcodeData);

			PyList_SetItem(list, i, Py_BuildValue("iN", (int)tmp->llFormat, result));
		}

        // release memory
		DBR_FreeBarcodeResults(&pResults);
		return list;
	}

	return Py_None;
}

static PyMethodDef methods[] = {
	{ "initLicense", initLicense, METH_VARARGS, NULL },
	{ "decodeFile", decodeFile, METH_VARARGS, NULL },
	{ NULL, NULL }
};

To automatically copy all relevant DLLs to output directory after building the project, add the following command line in Visual Studio.

copy dll in visual studio

Build the project to generate DynamsoftBarcodeReader.pyd.
Create a Python script under the output directory.
Python barcode programWrite a simple Python Barcode program with following code:

import os.path
import DynamsoftBarcodeReader

formats = {
    0x1FFL : "OneD",
    0x1L   : "CODE_39",
    0x2L : "CODE_128",
    0x4L   : "CODE_93",
    0x8L : "CODABAR",
    0x10L   : "ITF",
    0x20L : "EAN_13",
    0x40L   : "EAN_8",
    0x80L : "UPC_A",
    0x100L   : "UPC_E",
}

def initLicense(license):
    DynamsoftBarcodeReader.initLicense(license)

def decodeFile(fileName):
    results = DynamsoftBarcodeReader.decodeFile(fileName)
    for result in results:
        print "barcode format: " + formats[result[0]]
        print "barcode value: " + result[1]

if __name__ == "__main__":
    barcode_image = input("Enter the barcode file: ");
    if not os.path.isfile(barcode_image):
        print "It is not a valid file."
    else:
        decodeFile(barcode_image);

Use the image that provided by Dynamsoft Barcode SDK for a test.

test Python Barcode program

Now it’s your turn to create a fun Python Barcode program with Dynamsoft Barcode SDK.

Source Code

https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/samples/Python

Making Dynamsoft Barcode SDK an Addon for Node.js

$
0
0

Do you know which programming language is currently ranking first on GitHub? It is JavaScript! JavaScript is not only used for HTML5 Web application development, but also for server-side programming with runtime environment Node.js. With npm, the package manager for Node.js, it is so easy to install any Web frameworks or utilities. Although Node.js has provided many powerful JavaScript APIs, sometimes we have to create add-ons to empower Node.js with extra functionalities. In this tutorial, I’d like to share how to implement a JavaScript Barcode application with the custom addon, wrapped with C/C++ APIs of Dynamsoft Barcode SDK, for Node.js.

Dynamsoft Barcode Reader SDK

Ads Powered by Dynamsoft

Setting Up Environment for Node.js Addon Development

To build add-ons for Node.js, we need to install the tool node-gyp:

npm install -g node-gyp

Create an empty C/C++ file dbr.cc and a configuration file binding.gyp. Specify add-on name and C/C++ source files:

{
  "targets": [
    {
      "target_name": "dbr",
      "sources": [ "dbr.cc" ]
    }
  ]
}

Build dbr.node with the following command:

node-gyp configure install

Under folder build, you will see Visual Studio files and dbr.node:

build
	/ binding.sln
	/ dbr.vcxproj
	/ dbr.vcxproj.filters
	/ config.gypi
	/ Release
		/ dbr.node
		/ dbr.pdb
		/ obj

For more information, please read the basic tutorial of Node.js addons.

Wrapping Dynamsoft Barcode SDK as the Addon for Node.js

Download and install Dynamsoft Barcode Reader.
 DBR download button

 

 
Let’s double-click binding.sln to import the project to Visual Studio. Since node-gyp has added Node.js-relevant configurations, you just need to insert the directories of Dynamsoft Barcode SDK header files and libraries. Besides, add the post-build event:

copy "{installation directory}\Dynamsoft\Barcode Reader 2.0 Trial\Redist\C_C++\*.dll" "$(OutDir)"

Register a native method, and export the initialization function:

void Init(Handle<Object> exports) {
	NODE_SET_METHOD(exports, "decodeFile", DecodeFile);
}

NODE_MODULE(dbr, Init)

Convert barcode results to readable data for V8 JavaScript engine:

void DecodeFile(const FunctionCallbackInfo<Value>& args) {

	Isolate* isolate = Isolate::GetCurrent();
	HandleScope scope(isolate);

	// convert v8 string to char *
	String::Utf8Value utfStr(args[0]->ToString());
	char *pFileName = *utfStr;

	int option_iMaxBarcodesNumPerPage = -1;
	int option_llBarcodeFormat = -1;

	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	// decode barcode image file
	int ret = DBR_DecodeFile(
		pFileName,
		&option,
		&pResults
		);

	if (ret == DBR_OK){
		int count = pResults->iBarcodeCount;
		pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
		pBarcodeResult tmp = NULL;

		// javascript callback function
		Local<Function> cb = Local<Function>::Cast(args[1]);
		const unsigned argc = 1;

		// array for storing barcode results
		Local<Array> barcodeResults = Array::New(isolate);

		for (int i = 0; i < count; i++)
		{
			tmp = ppBarcodes[i];

			Local<Object> result = Object::New(isolate);
			result->Set(String::NewFromUtf8(isolate, "format"), Number::New(isolate, tmp->llFormat));
			result->Set(String::NewFromUtf8(isolate, "value"), String::NewFromUtf8(isolate, tmp->pBarcodeData));

			barcodeResults->Set(Number::New(isolate, i), result);
		}

		// release memory
		DBR_FreeBarcodeResults(&pResults);

		Local<Value> argv[argc] = { barcodeResults };
		cb->Call(isolate->GetCurrentContext()->Global(), argc, argv);
	}
}

For more information, please refer to v8.h and Chrome V8.

Create a JavaScript file for test:

var dbr = require('./build/Release/dbr');
var readline = require('readline');

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.question("Please input a barcode image path: ", function(answer) {
  // e.g. F:\git\Dynamsoft-Barcode-Reader\Images\AllSupportedBarcodeTypes.tif
  dbr.decodeFile(
    answer,
    function(msg){
      var result = null;
      for (index in msg) {
        result = msg[index]
        console.log(result['format']);
        console.log(result['value']);
        console.log("##################");
      }
    }
  );

  rl.close();
});

Finally, run your simple JavaScript Barcode application with command line tool:

Barcode addon for Node.js

Source Code

https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/samples/Node.js


Making PHP Barcode Extension with Dynamsoft Barcode SDK

$
0
0

After writing articles talking about how to wrap Dynamsoft Barcode SDK to make Barcode extensions for Java, Python and JavaScript, I started to consider PHP. It is one of the most popular tags on StackOverflow. Most Web developers prefer using PHP for server-side development. Since PHP allows developers to write extensions in C/C++, I was going to create a PHP Barcode extension with Dynamsoft Barcode Reader SDK. However, the whole process was not as easy as I expected. In this post, I’d like to share what troubles I’ve got and what solutions I’ve found.

Dynamsoft Barcode Reader SDK

Ads Powered by Dynamsoft

A Simple PHP Extension with Visual Studio 2012

As I did before, learning a “Hello World” program is always my first step.   I started to search the relevant keywords “PHP Windows extension” on StackOverflow, but only found a few snippets of information that are not useful enough. Alternatively, I spent some time Googling relevant articles and finally found the post – Creating a PHP 5 Extension with Visual C++ 2005. The post shared how to create extensions for PHP 5.2.4 with Visual Studio 2005, whereas the latest PHP Windows version is 5.6 that built with Visual Studio 2012. If you do not build PHP extension with the corresponding Visual Studio, you will have amounts of building errors.

Here are the steps to build and run the basic extension for PHP 5.6 with Visual Studio 2012 on Windows:

  1. Download and unzip PHP 5.6 source code and VC11 build.
  2. Create an empty Win32 project with application type DLL.PHP extension project
  3. Add Include directories:
    F:\php_pack\php-5.6.10-src
    F:\php_pack\php-5.6.10-src\Zend
    F:\php_pack\php-5.6.10-src\win32
    F:\php_pack\php-5.6.10-src\TSRM
    F:\php_pack\php-5.6.10-src\main
  4. Add Library directories:
    F:\php_pack\php-5.6.10-Win32-VC11-x86\dev
  5. Add dependency:
    php5ts.lib
  6. Create php_dbr.h with following code:
    #pragma once
    
    #include "zend_config.w32.h"    
    #include "php.h"
  7. Create php_dbr.cpp with following code:
    #include "php_dbr.h"
    
    ZEND_FUNCTION(DecodeBarcodeFile);
    
    zend_function_entry CustomExtModule_functions[] = {
        ZEND_FE(DecodeBarcodeFile, NULL)
        {NULL, NULL, NULL}
    };
    
    zend_module_entry CustomExtModule_module_entry = {
        STANDARD_MODULE_HEADER,
        "Dynamsoft Barcode Reader",
        CustomExtModule_functions,
        NULL, NULL, NULL, NULL, NULL,
        NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
    };
    
    ZEND_GET_MODULE(CustomExtModule)
    
    ZEND_FUNCTION(DecodeBarcodeFile){
    
        RETURN_STRING("No Barcode detected", true);
    }
  8. Add preprocessor definitions:
    ZEND_DEBUG=0
    ZTS=1
    ZEND_WIN32
    PHP_WIN32

    If you build the project directly, you will see many errors.

    PHP preprocessor errors

  9. Build your project to generate php_dbr.dll.

Making PHP Barcode Reader with Dynamsoft Barcode Reader SDK

Download and install Dynamsoft Barcode Reader.

DBR download button

Let’s take a glimpse of how to use PHP extension to call third-party DLL libraries:

  1. Add Include directories and Library directories of Dynamsoft Barcode Reader SDK to project properties.
  2. Copy the sample code written in previous Python or Node.js examples.
  3. Convert the returned results to PHP-readable type.
#include "php_dbr.h"

#include "If_DBR.h"
#include "BarcodeFormat.h"
#include "BarcodeStructs.h"
#include "ErrorCode.h"

#ifdef _WIN64
#pragma comment(lib, "DBRx64.lib")
#else
#pragma comment(lib, "DBRx86.lib")
#endif

void SetOptions(pReaderOptions pOption, int option_iMaxBarcodesNumPerPage, int option_llBarcodeFormat){

	if (option_llBarcodeFormat > 0)
		pOption->llBarcodeFormat = option_llBarcodeFormat;
	else
		pOption->llBarcodeFormat = OneD;

	if (option_iMaxBarcodesNumPerPage > 0)
		pOption->iMaxBarcodesNumPerPage = option_iMaxBarcodesNumPerPage;
	else
		pOption->iMaxBarcodesNumPerPage = INT_MAX;

}

ZEND_FUNCTION(DecodeBarcodeFile);

zend_function_entry CustomExtModule_functions[] = {
    ZEND_FE(DecodeBarcodeFile, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry CustomExtModule_module_entry = {
    STANDARD_MODULE_HEADER,
    "Dynamsoft Barcode Reader",
    CustomExtModule_functions,
    NULL, NULL, NULL, NULL, NULL,
    NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(CustomExtModule)

ZEND_FUNCTION(DecodeBarcodeFile){
	array_init(return_value);

	// Get Barcode image path
	char* pFileName = NULL;
	int iLen = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &pFileName, &iLen) == FAILURE) {
        RETURN_STRING("Invalid parameters", true);
    }

	// Dynamsoft Barcode Reader: init
	int option_iMaxBarcodesNumPerPage = -1;
	int option_llBarcodeFormat = -1;
	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;

	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	// decode barcode image file
	int ret = DBR_DecodeFile(
		pFileName,
		&option,
		&pResults
		);

	if (ret == DBR_OK)
	{
		int count = pResults->iBarcodeCount;
		pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
		pBarcodeResult tmp = NULL;

		// loop all results
		for (int i = 0; i < count; i++)
		{
			tmp = ppBarcodes[i];

			// convert format type to string
			char format[64]; 
			sprintf (format, "%d", tmp->llFormat); 

			// (barcode type, result)
			add_assoc_string(return_value, format, tmp->pBarcodeData, 1);
		}

		// Dynamsoft Barcode Reader: release memory
		DBR_FreeBarcodeResults(&pResults);
	}
	else
	{
		RETURN_STRING("No Barcode detected", true);
	}

}

Now, we need to deploy the generated DLL to PHP and write a PHP script to test it.

Here is the source code of your PHP Barcode Reader:

<?php

$filename = "F:\\git\\Dynamsoft-Barcode-Reader\\Images\\AllSupportedBarcodeTypes.tif";

if (file_exists($filename)) {
  echo "Barcode file: $filename \n";
  $resultArray = DecodeBarcodeFile($filename);

  if (is_array($resultArray)) {
    foreach($resultArray as $key => $value) {
      print "format:$key, result: $value \n";
      print "*******************\n";
    }
  }
  else {
    print "$resultArray";
  }

} else {
    echo "The file $filename does not exist";
}

?>

Open php.ini, and add our custom extension:

[Dynamsoft Barcode Reader]
extension=php_dbr.dll

php.ini configuration

As you know that we have to copy php_dbr.dll to {PHP root directory}\ext. What about the third-party DLL file DynamsoftBarcodeReaderx86.dll? If you just copy the DLL file with the PHP extension to the same folder, you will see the following error when running your PHP Barcode reader application:

PHP DLL error

How to fix this issue? You just need to copy the DLL file to PHP root directory. Try it again:

PHP Barcode Reader Extension

Source Code

https://github.com/yushulx/Dynamsoft-Barcode-Reader/tree/master/samples/PHP

Reading Barcode from Scanned Documents

$
0
0

Many industries, which need to process amounts of paper per day, like healthcare, finance, education and so on, are getting started to adopt Barcode scanning as the solution for the electronic document management system. For example, when you have a health examination, you will pick a form with some Barcode stickers. Once your health report generated, it is easy to track and record all relevant information. We can implement Barcode detection either on the client side or on the server side. Many client-side applications, especially mobile apps, tend to integrate Barcode functionality for shopping, boarding, social networking, logistics and so on. In contrast, some enterprise solutions, such as ECM (enterprise content management) system, need to detect Barcode on the server side while collecting various e-documents. In this post, I will demonstrate how to load and scan document images via a Web page and extract Barcode information on the server side.

Software for Building Document Barcode Scanning System

To create the online Barcode reader, we need to download Django, Dynamic Web TWAIN SDK and Dynamsoft Barcode SDK.

django

DWT download button

DBR download button

Online Barcode Reader in Python

Using Dynamic Web TWAIN SDK to Load and Scan Barcode Images

Read the article Uploading Files with Django and follow the necessary steps to create a Web page for image loading, scanning, and uploading.

load & scan images

Python Barcode Library with Dynamsoft Barcode C/C++ APIs

Read the article Wrapping C/C++ Methods of Dynamsoft Barcode SDK for Python to quickly create a Barcode library in Python

Python barcode sdk

Deploying Python Barcode Library to Django Project

Copy Python Barcode Reader to {Django Project Root}\dwtupload.
use Python Barcode
Create a Python module dbr.py.

import os.path
import DynamsoftBarcodeReader

formats = {
    0x1FFL : "OneD",
    0x1L   : "CODE_39",
    0x2L : "CODE_128",
    0x4L   : "CODE_93",
    0x8L : "CODABAR",
    0x10L   : "ITF",
    0x20L : "EAN_13",
    0x40L   : "EAN_8",
    0x80L : "UPC_A",
    0x100L   : "UPC_E",
}

def decodeFile(fileName):
    if not os.path.isfile(fileName):
        print "It is not a valid file."
        return

    results = DynamsoftBarcodeReader.decodeFile(fileName)
    json = {}
    tmp = []
    i = 0

    # Convert results to JSON
    for result in results:
        key = formats[result[0]]
        value = result[1]
        tmp = [key, value]
        json[i] = tmp
        i += 1;

    return str(json)

Import the module to views.py.

from django.shortcuts import render
from django.http import HttpResponse
import os
import dbr

# Create your views here.
def home(request):
    return render(request, 'index.htm', {'what':'Online Barcode Reader with Django'})

def upload(request):
    if request.method == 'POST':
        uploadedFile = handle_uploaded_file(request.FILES['RemoteFile'], str(request.FILES['RemoteFile']))
        results = dbr.decodeFile(uploadedFile)
        return HttpResponse(results)

    return HttpResponse("Failed")

def handle_uploaded_file(file, filename):
    if not os.path.exists('upload/'):
        os.mkdir('upload/')

    filePath = 'upload/' + filename

    with open(filePath, 'wb+') as destination:
        for chunk in file.chunks():
            destination.write(chunk)

    return filePath

Run the project as follows:

python manage.py runserver

Testing the Online Barcode Reader

Load a document image with multiple Barcodes.

Select Barcode images

Click Read Barcode.

load multi Barcode images

Check the returned results.
Barcode results

Source Code

https://github.com/dynamsoftsamples/django-barcode-reader

Reading Barcode with Webcam in OpenCV and Python

$
0
0

Barcode is an efficient way to make information readable for machines. There are many scenarios of using Barcode reader software. For example, companies use Barcode encoding and decoding software to manage various documents that captured by office scanners. Airport security uses handheld scanners to check the boarding pass and record personal information to the database. Students use the built-in camera of the smartphone to check attendance via Barcode reader software. Since I have a Webcam connected to my desktop PC, I want to empower it to work as a Barcode reader. To implement the solution, I decide to choose OpenCV and Dynamsoft Barcode Reader SDK.


Python Webcam Barcode Reader

Installation

How to Recognize Barcode via Webcam in Python

Here are the steps:

  1. Copy <opencv_installation_dir>\build\python\2.7\x86\cv2.pyd
    to <Python27>\Lib\site-packages\cv2.pyd
  2. Create a project folder.
  3. Build Python Barcode library with Dynamsoft Barcode Reader SDK.
  4. Copy Barcode library and all dependencies to the project folder.
  5. Connect a Webcam to your PC. Make sure you have installed the Webcam driver.
  6. Create a Python script to control Webcam, capture images from Webcam and decode images with Python Barcode library.

Creating Python Barcode Library with Dynamsoft Barcode SDK

The first step is to build the Python Barcode library yourself.

#include "Python.h"

#include "If_DBR.h"
#include "BarcodeFormat.h"
#include "BarcodeStructs.h"
#include "ErrorCode.h"

#ifdef _WIN64
#pragma comment(lib, "DBRx64.lib")
#else
#pragma comment(lib, "DBRx86.lib")
#endif

void SetOptions(pReaderOptions pOption, int option_iMaxBarcodesNumPerPage, int option_llBarcodeFormat){

	if (option_llBarcodeFormat > 0)
		pOption->llBarcodeFormat = option_llBarcodeFormat;
	else
		pOption->llBarcodeFormat = OneD;

	if (option_iMaxBarcodesNumPerPage > 0)
		pOption->iMaxBarcodesNumPerPage = option_iMaxBarcodesNumPerPage;
	else
		pOption->iMaxBarcodesNumPerPage = INT_MAX;

}

static PyObject *
initLicense(PyObject *self, PyObject *args)
{
	char *license;

	if (!PyArg_ParseTuple(args, "s", &license)) {
		return NULL;
	}

	printf("information: %s\n", license);

	int ret = DBR_InitLicense(license);

	printf("return value = %d", ret);

	return Py_None;
}

static PyObject *
decodeFile(PyObject *self, PyObject *args)
{
	char *pFileName;
	int option_iMaxBarcodesNumPerPage = -1;
	int option_llBarcodeFormat = -1;

	if (!PyArg_ParseTuple(args, "s", &pFileName)) {
		return NULL;
	}

	pBarcodeResultArray pResults = NULL;
	ReaderOptions option;
	SetOptions(&option, option_iMaxBarcodesNumPerPage, option_llBarcodeFormat);

	int ret = DBR_DecodeFile(
		pFileName,
		&option,
		&pResults
		);

	if (ret == DBR_OK){
		int count = pResults->iBarcodeCount;
		pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
		pBarcodeResult tmp = NULL;

		PyObject* list = PyList_New(count);
		PyObject* result = NULL;

		for (int i = 0; i < count; i++)
		{
			tmp = ppBarcodes[i];
			result = PyString_FromString(tmp->pBarcodeData);

			PyList_SetItem(list, i, Py_BuildValue("iN", (int)tmp->llFormat, result));
		}

		// release memory
		DBR_FreeBarcodeResults(&pResults);

		return list;
	}

	return Py_None;
}

static PyMethodDef methods[] = {
	{ "initLicense", initLicense, METH_VARARGS, NULL },
	{ "decodeFile", decodeFile, METH_VARARGS, NULL },
	{ NULL, NULL }
};

PyMODINIT_FUNC
initDynamsoftBarcodeReader(void)
{
	Py_InitModule("DynamsoftBarcodeReader", methods);
}

For detailed information, please refer to the source code on GitHub. Once the library built successfully, copy DynamsoftBarcodeReader.pyd and DynamsoftBarcodeReaderx64.dll /DynamsoftBarcodeReaderx86.dll to the project folder.

Opening Webcam with OpenCV

Using OpenCV, we can show Webcam preview and capture images with a few lines of Python code.

import cv2.cv as cv

title = "Dynamsoft Barcode Reader"
cv.NamedWindow(title, 1)
capture = cv.CaptureFromCAM(0)

while True:
    img = cv.QueryFrame(capture)
    cv.ShowImage(title, img)

Reading Barcode and Drawing Results over Image

line_type = cv.CV_AA
font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX,
                          0.1, 1, 1, 1, line_type)
fileName = 'test.jpg'
img = cv.QueryFrame(capture)
cv.SaveImage(fileName, img)

results = DynamsoftBarcodeReader.decodeFile(fileName)
top = 30
increase = 20
if results:
    for result in results:
        barcode_format = "Format: " + formats[result[0]]
        barcode_value = "Value: " + result[1]
        cv.PutText(img, barcode_format, (10, top), font, (254, 142, 20))
        top += increase
        cv.PutText(img, barcode_value, (10, top), font, (254, 142, 20))
        top += increase
        cv.PutText(img, "************************", (10, top), font, (254, 142, 20))
        top += increase

cv.ShowImage(title, img)

Source Code

https://github.com/yushulx/webcam-barcode-reader

 

How to Write and Read QR Code with ZXing in Java

$
0
0

ZXing is an open-source, 1D/2D barcode image processing library implemented in Java. The supported barcode formats include UPC-A, UPC-E, EAN-8, Code 93, Code 128, QR Code, Data Matrix, Aztec, PDF 417, etc. Besides the Java version, developers can leverage other ported projects such as QZXing, zxing-cpp, zxing_cpp.rb, python-zxing and ZXing .NET to quickly make barcode reader or writer software. According to the visualization report of Google trends, QR code seems to be the most popular barcode format since 2009. In this post, I’d like to share how to use ZXing to create QR code writer and reader for both desktop Java applications and Android mobile apps.


zxing barcode test

Getting ZXing Source Code

The ZXing project has moved from Google Code to GitHub. To get the source code, use the  following git command line:

git clone https://github.com/zxing/zxing

Linking ZXing to Projects

There are two ways to link ZXing:

  • Build the source code to a jar file, and then import it to Java projects.  If you want to use Android Studio instead of Eclipse, please read Time to Migrate Android Projects to Android Studio.
  • Directly import the ZXing source code to Java projects. In Eclipse, select Project Properties > Java Build Path > Source > Link Source, and specify the source folder location: <zxing>\core\src\main\java. If the folder location is incorrect, you will see many package errors in the console.
    link zxing source folder

Taking a Glimpse of ZXing Source Code

Before implementing QR code writer and reader, let’s take a look at the basic Java classes in ZXing barcode library.

In Eclipse, search for the text implements Writer.

zxing barcode writer
Here are the 1D/2D barcode writers. All barcode formats are defined in BarcodeFormat.java:

public enum BarcodeFormat {

  /** Aztec 2D barcode format. */
  AZTEC,

  /** CODABAR 1D format. */
  CODABAR,

  /** Code 39 1D format. */
  CODE_39,

  /** Code 93 1D format. */
  CODE_93,

  /** Code 128 1D format. */
  CODE_128,

  /** Data Matrix 2D barcode format. */
  DATA_MATRIX,

  /** EAN-8 1D format. */
  EAN_8,

  /** EAN-13 1D format. */
  EAN_13,

  /** ITF (Interleaved Two of Five) 1D format. */
  ITF,

  /** MaxiCode 2D barcode format. */
  MAXICODE,

  /** PDF417 format. */
  PDF_417,

  /** QR Code 2D barcode format. */
  QR_CODE,

  /** RSS 14 */
  RSS_14,

  /** RSS EXPANDED */
  RSS_EXPANDED,

  /** UPC-A 1D format. */
  UPC_A,

  /** UPC-E 1D format. */
  UPC_E,

  /** UPC/EAN extension format. Not a stand-alone format. */
  UPC_EAN_EXTENSION

}

The class MultiFormatWriter has covered all supported barcode writers. Instead of any specific bar code writer, we just need to use MultiFormatWriter with a specified barcode format.

@Override
  public BitMatrix encode(String contents,
                          BarcodeFormat format,
                          int width, int height,
                          Map<EncodeHintType,?> hints) throws WriterException {

    Writer writer;
    switch (format) {
      case EAN_8:
        writer = new EAN8Writer();
        break;
      case EAN_13:
        writer = new EAN13Writer();
        break;
      case UPC_A:
        writer = new UPCAWriter();
        break;
      case QR_CODE:
        writer = new QRCodeWriter();
        break;
      case CODE_39:
        writer = new Code39Writer();
        break;
      case CODE_128:
        writer = new Code128Writer();
        break;
      case ITF:
        writer = new ITFWriter();
        break;
      case PDF_417:
        writer = new PDF417Writer();
        break;
      case CODABAR:
        writer = new CodaBarWriter();
        break;
      case DATA_MATRIX:
        writer = new DataMatrixWriter();
        break;
      case AZTEC:
        writer = new AztecWriter();
        break;
      default:
        throw new IllegalArgumentException("No encoder available for format " + format);
    }
    return writer.encode(contents, format, width, height, hints);
  }

Similarly, we can search for implements Reader:

zxing barcode reader

The MultiFormatReader will also simplify the code work.

QR Code Writer and Reader for Windows, Mac and Linux

Since ZXing is implemented in Java, it is easy to create cross-platform QR writer and reader software for Windows, Mac and Linux. To operate image data in Java, we need to use the class BufferedImage.

Writing QR Code with QRCodeWriter

       public static void writeQRCode() {
		QRCodeWriter writer = new QRCodeWriter();
		int width = 256, height = 256;
		BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // create an empty image
		int white = 255 << 16 | 255 << 8 | 255;
		int black = 0;
		try {
			BitMatrix bitMatrix = writer.encode("http://www.codepool.biz/zxing-write-read-qrcode.html", BarcodeFormat.QR_CODE, width, height);
	        for (int i = 0; i < width; i++) {
	            for (int j = 0; j < height; j++) {
	            	image.setRGB(i, j, bitMatrix.get(i, j) ? black : white); // set pixel one by one
	            }
	        }

	        try {
				ImageIO.write(image, "jpg", new File("dynamsoftbarcode.jpg")); // save QR image to disk
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} catch (WriterException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

Reading QR Code with QRCodeReader

We need to use RGBLuminanceSource to wrap RGB data:

        public static String readQRCode(String fileName) {
		File file = new File(fileName);
		BufferedImage image = null;
		BinaryBitmap bitmap = null;
		Result result = null;

		try {
			image = ImageIO.read(file);
			int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
			RGBLuminanceSource source = new RGBLuminanceSource(image.getWidth(), image.getHeight(), pixels);
			bitmap = new BinaryBitmap(new HybridBinarizer(source));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (bitmap == null)
			return null;

		QRCodeReader reader = new QRCodeReader();	
		try {
			result = reader.decode(bitmap);
			return result.getText();
		} catch (NotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ChecksumException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

QR Code Generator and Reader for Android

Comparing to the Java code of the desktop application, the only difference is the way of operating image bytes on Android. In Android SDK, there is no class named BufferedImage. Instead, we should use Bitmap.

Generating QR Code to ImageView on Android

    QRCodeWriter writer = new QRCodeWriter();
    try {
        int width = mImageView.getWidth();
        int height = mImageView.getHeight();
        BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height);
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                bitmap.setPixel(i, j, bitMatrix.get(i, j) ? Color.BLACK: Color.WHITE);
            }
        }
        mImageView.setImageBitmap(bitmap);
    } catch (WriterException e) {
        e.printStackTrace();
    }

Reading QR Code from Android Camera Preview

The preview data type of Android camera is NV21. So We need to use PlanarYUVLuminanceSource to wrap it.

            MultiFormatReader reader = new MultiFormatReader();            
            LuminanceSource source = new PlanarYUVLuminanceSource(yuvData, dataWidth, dataHeight, left, top, width, height, false);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Result result;
            try {
                result = reader.decode(bitmap);
                if (result != null) {
                    mDialog.setTitle("Result");
                    mDialog.setMessage(result.getText());
                    mDialog.show();
                }
            } catch (NotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

How to Bridge C Code to Create Swift Barcode Reader on Mac

$
0
0

Have you implemented any barcode reader software in Swift on Mac OS X? Since Dynamsoft released the 1D/2D barcode SDK for Mac, I was wondering how I can bridge the C dylib with Swift. Why Swift, not Objective-C? Because Apple is encouraging developers to migrate to the new programming language, it is important to master the new tool if you want to create more excellent apps for Mac and iOS in the future. Swift is totally new to me, and thus I spent two days googling relevant resources and finally figured out the solution.

Prerequisites

Using Swift with C

It is recommended to read the e-book Using Swift with Cocoa and Objective-C published by Apple in iBooks. To quickly get familiar with how to make Swift work with C language types and features, we can pick the chapter Interacting with C APIs. You may use the following primitive type mapping and pointer mapping when interoperating Swift and C.

primitive type mapping

pointer mapping

Implementing 1D/2D Barcode Reader with Swift and C on Mac

Open Xcode, and then press Command+Shift+N to create a new project. I will demo both command line tool and Cocoa application.

create swift project

After initializing the new project, we need to import all relevant header files and libraries to the project. The quickest way is to use your mouse to drag header files and libraries to your project. Xcode will automatically add them to project configuration files.

Press Command+N to add a C file, which will be used to invoke Dynamsoft Barcode dylib.

create c for swift project

Once it’s done, you will see an alert dialog as follows:

objective-c bridging header

If press Yes, Xcode will automatically generate an Objective-C bridging header file. I had created native_lib.c and native_lib.h, so I opened the bridging header file and add the following line:

#import "native_lib.h"

Referring to the online sample of Dynamsoft Barcode SDK, we can make a few changes:

#include "native_lib.h"

int dbr_release_memory(pBarcodeResultArray paryResult)
{
    DBR_FreeBarcodeResults(&paryResult);
    printf("Game Over\n");
    return 0;
}

pBarcodeResultArray dbr_decodeBarcodeFile(char* pszImageFile)
{
    // Parse command
    __int64 llFormat = (OneD |QR_CODE);

    int iMaxCount = 0x7FFFFFFF;
    int iIndex = 0;
    ReaderOptions ro = {0};
    pBarcodeResultArray paryResult = NULL;
    int iRet = -1;
    char * pszTemp = NULL;
    char * pszTemp1 = NULL;
    struct timeval begin, end;

    if (NULL == pszImageFile)
    {
        printf("The syntax of the command is incorrect.\n");
        return NULL;
    }

    // Set license
    DBR_InitLicense("A825E753D10C6CAC7C661140EC5ABEC3");

    // Read barcode
    gettimeofday(&begin, NULL);
    ro.llBarcodeFormat = llFormat;
    ro.iMaxBarcodesNumPerPage = iMaxCount;
    iRet = DBR_DecodeFile(pszImageFile, &ro, &paryResult);
    gettimeofday(&end, NULL);

    // Output barcode result
    pszTemp = (char*)malloc(4096);
    if (iRet != DBR_OK)
    {
        sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
        printf("%s", pszTemp);
        free(pszTemp);
        return NULL;
    }

    if (paryResult->iBarcodeCount == 0)
    {
        sprintf(pszTemp, "No barcode found. Total time spent: %.3f seconds.\r\n",
                ((float)((end.tv_sec * 1000 * 1000 +  end.tv_usec) - (begin.tv_sec * 1000 * 1000 + begin.tv_usec))/(1000 * 1000)));
        printf("%s", pszTemp);
        DBR_FreeBarcodeResults(&paryResult);
        return 0;
    }

    sprintf(pszTemp, "Total barcode(s) found: %d. Total time spent: %.3f seconds\r\n\r\n", paryResult->iBarcodeCount,
            ((float)((end.tv_sec * 1000 * 1000 +  end.tv_usec) - (begin.tv_sec * 1000 * 1000 + begin.tv_usec))/(1000 * 1000)));
    printf("%s", pszTemp);

    return paryResult;
}

As for the corresponding header file, add the following code:

#ifndef __DBRConsole__native_lib__
#define __DBRConsole__native_lib__

#include <stdio.h>

#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "If_DBR.h"

pBarcodeResultArray dbr_decodeBarcodeFile(char* fileName);
int dbr_release_memory(pBarcodeResultArray paryResult);
const char * GetFormatStr(__int64 format);

#endif /* defined(__DBRConsole__native_lib__) */

Command Line Tool in Swift

When writing Swift code, I need to convert Swift String to Char* in order to pass image path.

var file: String = "/Applications/Dynamsoft/Barcode Reader 3.0 Trial/Images/AllSupportedBarcodeTypes.tif" // barcode file
//let namePtr = strdup(filePath.bridgeToObjectiveC().UTF8String)

var filePtr = strdup(file.cStringUsingEncoding(NSUTF8StringEncoding)!)
var fileName: UnsafeMutablePointer<CChar> = UnsafeMutablePointer(filePtr)

I found someone answered how to convert NSString to Char* with the commented line on StackOverflow. The method bridgeToObjectiveC was supported in earlier Xcode 6.x but has been removed in Xcode 6.4.

Get the barcode results:

var result : pBarcodeResultArray = dbr_decodeBarcodeFile(fileName)

free(filePtr)

println("Total barcode: \(String(result.move().iBarcodeCount))\n.......")

var count = result.move().iBarcodeCount
var pBarcodeResult: pBarcodeResult = nil
var barcodeIndex = 1

// print barcode recognition results
for i in 0..<Int(count) {
    pBarcodeResult = result.move().ppBarcodes.advancedBy(i).move()
    println("Barcode: \(barcodeIndex++)")
    println("Page: \(String(pBarcodeResult.move().iPageNum))")
    var lFormat: __int64 = pBarcodeResult.move().llFormat
    var format = String.fromCString(GetFormatStr(lFormat))
    println("Type: \(format!)")
    println("Value: \(String.fromCString(pBarcodeResult.move().pBarcodeData)!)")
    println(".......")

}

// free C memory
dbr_release_memory(result)

barcode console output

Cocoa Application in Swift

Create buttons and text fields in AppDelegate.swift:

@IBOutlet weak var window: NSWindow!
@IBOutlet weak var btLoad: NSButton!
@IBOutlet weak var btRead: NSButton!
@IBOutlet weak var text: NSTextField!
@IBOutlet weak var filePath: NSTextField!

Create a function to receive click event:

@IBAction func onClick(sender: NSButton) {
        var title = sender.title
        switch(title) {
        case "Load Barcode File":
            dispatch_async(dispatch_get_main_queue()) {
                self.openPanel()
            }
            break
        case "Read Barcode":

            if self.filePath.stringValue == "" {
                text.stringValue = "Please add image path!"
                return
            }

            println("default:" + self.filePath.stringValue)
            var dbr = DBR()
            text.stringValue = dbr.decodeFile(self.filePath.stringValue)!
            break
        default:
            break
        }

    }

In interface builder, connect outlets to UI elements.

app delegate

Using NSOpenPanel to load files:

func openPanel() {
        var openPanel = NSOpenPanel()
        openPanel.allowsMultipleSelection = false
        openPanel.canChooseDirectories = false
        openPanel.canCreateDirectories = false
        openPanel.canChooseFiles = true
        openPanel.beginWithCompletionHandler { (result) -> Void in
            if result == NSFileHandlingPanelOKButton {
                if let path = openPanel.URL?.path {
                    self.filePath.stringValue = path
                }
            }
        }

    }

Create DBR.swift for reading barcode images:

import Foundation

class DBR {
    func decodeFile(file: String)->String? {

        var filePtr = strdup(file.cStringUsingEncoding(NSUTF8StringEncoding)!)
        var fileName: UnsafeMutablePointer<CChar> = UnsafeMutablePointer(filePtr)
        var result : pBarcodeResultArray = dbr_decodeBarcodeFile(fileName)

        free(filePtr)

        println("Total barcode: \(String(result.move().iBarcodeCount))\n.......")

        var count = result.move().iBarcodeCount
        var barcodeIndex = 1
        var results: String = ""
        // print barcode recognition results
        for i in 0..<Int(count) {
            var pBarcodeResult = result.move().ppBarcodes.advancedBy(i).move()

            results += "Barcode: \(barcodeIndex++)\n"
            results += "Page: \(String(pBarcodeResult.move().iPageNum))\n"

            var lFormat: __int64 = pBarcodeResult.move().llFormat
            var format = String.fromCString(GetFormatStr(lFormat))

            results += "Type: \(format!)\n"
            results += "Value: \(String.fromCString(pBarcodeResult.move().pBarcodeData)!)\n"
            results += ".......\n"

        }

        // free C memory
        dbr_release_memory(result)

        return results
    }
}

Run the 1D/2D barcode reader with GUI:

swift barcode reader

Source Code

https://github.com/yushulx/swift-barcode-reader

 

How to Benchmark Barcode SDK Performance – ZXing vs ZBar

$
0
0

I saw many posts arguing the performance winner between ZXing and ZBar. As an engineer, who is developing commercial barcode reader software for Dynamsoft, I am curious about which open source project is better, ZXing or ZBar? Considering ZXing is implemented in Java, whereas ZBar is implemented in C/C++. To fairly compare their performance, I decided to use JNI to wrap ZBar C/C++ source code and benchmark them in a Java program.

Prerequisites

ZXing Source code

https://github.com/zxing/zxing

ZBar Source Code

https://github.com/ZBar/ZBar

ZBar Windows Installer

http://sourceforge.net/projects/zbar/files/zbar/

How to Decode TIFF in Java

I need to use a dataset that includes many TIFF files for testing barcode reading performance. The Java Class ImageIO could read many image formats such as JPEG, PNG, BMP, but not TIFF. I searched Oracle’s Website and found Java Advanced Imaging (JAI) API, which provides methods for decoding TIFF files.

Where to download JAI jar packages?

I was surprised that the download links of Oracle official Website pointed to 404 error page. If you Google Java JAI, you may find there is no valid link on the first page of searching results. I patiently looked for download links page by page, and even changed the search engine. Luckily there is a working page existed: http://www.java2s.com/Code/Jar/j/Downloadjaicore113jar.htm. To make JAI work, you need to download jai_codec-1.1.3.jar and jai_core-1.1.3.jar. Here is the source code demonstrating how to read TIFF file to int[]:

File file = new File(fileName);
RenderedImage tiff = JAI.create("tiffload", fileName);
BufferedImage image = PlanarImage.wrapRenderedImage(tiff).getAsBufferedImage();
int[] pixels = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());

How to Read Multiple Barcodes of an Image with ZXing

Previously, I shared a post – How to Write and Read QR Code with ZXing in Java, which demonstrates how to read barcodes with MultiFormatReader. But MultiFormatReader only returns one result. What if we want to read multiple barcodes from an image, such as a document with code39, code93 and QR code? In this case, we need to use another reader class GenericMultipleBarcodeReader.

About GenericMultipleBarcodeReader:

Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image. After one barcode is found, the areas left, above, right and below the barcode’s ResultPoints are scanned, recursively.

To read multiple barcode results, you can write Java code as follows:

         RGBLuminanceSource source = new RGBLuminanceSource(image.getWidth(),
				image.getHeight(), pixels);
		bitmap = new BinaryBitmap(new HybridBinarizer(source));

		Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
		hints.put(DecodeHintType.TRY_HARDER, null);
		Collection<BarcodeFormat> formats = new ArrayList<>();
		formats.add(BarcodeFormat.QR_CODE);
		formats.add(BarcodeFormat.CODABAR);
		formats.add(BarcodeFormat.CODE_39);
		formats.add(BarcodeFormat.CODE_93);
		formats.add(BarcodeFormat.CODE_128);
		formats.add(BarcodeFormat.EAN_8);
		formats.add(BarcodeFormat.EAN_13);
		formats.add(BarcodeFormat.ITF);
		formats.add(BarcodeFormat.UPC_A);
		formats.add(BarcodeFormat.UPC_E);
		formats.add(BarcodeFormat.UPC_EAN_EXTENSION);

		hints.put(DecodeHintType.POSSIBLE_FORMATS, formats);
		MultiFormatReader reader = new MultiFormatReader(); 

		// read multi barcodes
		GenericMultipleBarcodeReader multiReader = new GenericMultipleBarcodeReader(
				reader);
		try {
			Result[] results = multiReader.decodeMultiple(bitmap, hints);
			System.out.println(ZXING + TIME_COST
					+ ((System.nanoTime() - start) / 1000000) + MS);
			if (results != null) {
				for (Result result : results) {
					System.out.println(ZXING + TYPE + result.getBarcodeFormat() + VALUE + result.getText());
				}
			}
		} catch (NotFoundException e) {
			e.printStackTrace();
			return;
		}

Creating Java Native Interface (JNI) for ZBar

How to use ZBar to decode barcodes in C/C++? If no idea, you can refer to the sample scan_image.cpp provided by ZBar in source code or installer. With a few changes, the JNI sample may be as follows:

#include <iostream>
#include <Magick++.h>
#include <zbar.h>
#include <jni.h>
#define STR(s) #s

using namespace std;
using namespace zbar;

#ifndef DEBUG
#define DEBUG(...) printf(__VA_ARGS__)
#endif

extern "C" {
	JNIEXPORT jobjectArray JNICALL Java_com_dynamsoft_zbar_ZBarReader_decode(JNIEnv *env, jobject obj, jstring fileName);
}

JNIEXPORT jobjectArray JNICALL Java_com_dynamsoft_zbar_ZBarReader_decode(JNIEnv *env, jobject obj, jstring fileName)
{
	const char *pszFileName = env->GetStringUTFChars(fileName, 0);

#ifdef MAGICK_HOME
	// http://www.imagemagick.org/Magick++/
	//    under Windows it is necessary to initialize the ImageMagick
	//    library prior to using the Magick++ library
	Magick::InitializeMagick(MAGICK_HOME);
#endif

	// create a reader
	ImageScanner scanner;

	// configure the reader
	scanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);

	// obtain image data
	Magick::Image magick(pszFileName);  // read an image file
	int width = magick.columns();   // extract dimensions
	int height = magick.rows();
	Magick::Blob blob;              // extract the raw data
	magick.modifyImage();
	magick.write(&blob, "GRAY", 8);
	const void *raw = blob.data();

	// wrap image data
	Image image(width, height, "Y800", raw, width * height);

	// scan the image for barcodes
	int n = scanner.scan(image);

	// find java class
	jclass clsZBarResult = env->FindClass("com/dynamsoft/zbar/ZBarResult");
	// create java array
	int data_length = 0;
	for (Image::SymbolIterator symbol = image.symbol_begin();
		symbol != image.symbol_end();
		++symbol) {
		++data_length;
	}

	jobjectArray clsZBarResultArray = env->NewObjectArray(data_length, clsZBarResult, 0);
	int iIndex = 0;

	// extract results
	for (Image::SymbolIterator symbol = image.symbol_begin();
		symbol != image.symbol_end();
		++symbol) {
		// do something useful with results
		//cout << "ZBR Type: " << symbol->get_type_name()
		//	<< ", Value \"" << symbol->get_data() << '"' << endl;

		// save result to java array
		jmethodID init = env->GetMethodID(clsZBarResult, "<init>", "()V");
		jobject clsZBarResultObj = env->NewObject(clsZBarResult, init);
		jfieldID jType = env->GetFieldID(clsZBarResult, "mType", "Ljava/lang/String;");
		jfieldID jValue = env->GetFieldID(clsZBarResult, "mValue", "Ljava/lang/String;");
		env->SetObjectField(clsZBarResultObj, jType, env->NewStringUTF(symbol->get_type_name().c_str()));
		env->SetObjectField(clsZBarResultObj, jValue, env->NewStringUTF(symbol->get_data().c_str()));
		env->SetObjectArrayElement(clsZBarResultArray, iIndex, clsZBarResultObj);
		++iIndex;		
	}

	// clean up
	image.set_data(NULL, 0);

	// release string
	env->ReleaseStringUTFChars(fileName, pszFileName);

	return clsZBarResultArray;
}

I changed the main function to JNI method and packaged barcode results to Java objects. See the corresponding Java classes.

ZBarReader.java:

package com.dynamsoft.zbar;

import com.dynamsoft.utils.BaseReader;

public class ZBarReader extends BaseReader {

	static {
		System.loadLibrary("zbarjni");
	}

	public void testZBar(String fileName) {
		long start = System.nanoTime();
		ZBarReader reader =  new ZBarReader();
		ZBarResult[] results = (ZBarResult[])reader.decode(fileName);
		System.out.println(ZBAR + TIME_COST
				+ ((System.nanoTime() - start) / 1000000) + MS);

		if (results != null && results.length > 0) {
			mCount += 1;
			for (ZBarResult result : results) {
				System.out.println(ZBAR + TYPE + result.mType + VALUE + result.mValue);
			}
		}
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return super.getCount();
	}

	public native Object[] decode(String fileName);
}

ZBarResult.java:

package com.dynamsoft.zbar;

public class ZBarResult {
	public String mType;
	public String mValue;
}

Benchmark Test between ZXing and ZBar

Dynamsoft and ZXing provide some testing image sets, you can get them from https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/Images and https://github.com/zxing/zxing/tree/master/core/src/test/resources. To make results convincing, I used the testing images provided by ZXing: https://github.com/zxing/zxing/tree/master/core/src/test/resources/blackbox/qrcode-1 Here is the report:

F:\resources\blackbox\qrcode-1\1.png

ZXI Time cost: 122ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 33ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\10.png

ZXI Time cost: 66ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 28ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\11.png

ZXI Time cost: 53ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 29ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\12.png

ZXI Time cost: 71ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 29ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\13.png

ZXI Time cost: 84ms

ZXI Type: QR_CODE, value: http://google.com/gwt/n?u=bluenile.com

ZBA Time cost: 27ms

ZBA Type: QR-Code, value: http://google.com/gwt/n?u=bluenile.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\14.png

com.google.zxing.NotFoundException

ZBA Time cost: 32ms

ZBA Type: QR-Code, value: http://google.com/gwt/n?u=bluenile.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\15.png

ZXI Time cost: 90ms

ZXI Type: QR_CODE, value: http://google.com/gwt/n?u=bluenile.com

ZBA Time cost: 34ms

ZBA Type: QR-Code, value: http://google.com/gwt/n?u=bluenile.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\16.png

ZXI Time cost: 77ms

ZXI Type: QR_CODE, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

ZBA Time cost: 35ms

ZBA Type: QR-Code, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\17.png

ZXI Time cost: 82ms

ZXI Type: QR_CODE, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

ZBA Time cost: 32ms

ZBA Type: QR-Code, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\18.png

ZXI Time cost: 80ms

ZXI Type: QR_CODE, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

ZBA Time cost: 35ms

ZBA Type: QR-Code, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\19.png

ZXI Time cost: 64ms

ZXI Type: QR_CODE, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

ZBA Time cost: 28ms

ZBA Type: QR-Code, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\2.png

ZXI Time cost: 61ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 28ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\20.png

ZXI Time cost: 55ms

ZXI Type: QR_CODE, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

ZBA Time cost: 30ms

ZBA Type: QR-Code, value: Sean Owen

srowen@google.com

917-364-2918

http://awesome-thoughts.com

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\3.png

ZXI Time cost: 56ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 29ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\4.png

ZXI Time cost: 70ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 28ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\5.png

ZXI Time cost: 64ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 28ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\6.png

ZXI Time cost: 56ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 28ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\7.png

ZXI Time cost: 73ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 30ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\8.png

ZXI Time cost: 55ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 27ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

       F:\resources\blackbox\qrcode-1\9.png

ZXI Time cost: 55ms

ZXI Type: QR_CODE, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

ZBA Time cost: 27ms

ZBA Type: QR-Code, value: MEBKM:URL:http\://en.wikipedia.org/wiki/Main_Page;;

-------------------------------------------------------------------------------------

ZXI passed: 19

ZBA passed: 20

According to the results, ZBar seems to be much better than ZXing when reading QR code. Because I only tested QRcode, the conclusion may not be accurate. If you are interested, you can try other datasets yourself.

Source Code

https://github.com/Dynamsoft/Dynamsoft-Barcode-Reader/tree/master/samples/Java

How to Build ImageMagick for Software Distribution on Windows

$
0
0

If you have read the article How to Benchmark Barcode SDK Performance – ZXing vs ZBar, you may have noticed that ZBar relies on ImageMagick. ImageMagick is an open source software suite that capable of reading a variety of images. If you just want to write a barcode testing program, Windows Binary Release of ImageMagick is enough. However, if you consider distributing your applications, the Windows binary distribution is not suitable. Why? I’ll show you in the following content.

ImageMagick DLL Dependencies on Windows

When opening the ImageMagick installation directory, you will see the following dynamic libraries:
ImageMagick dependencies

Do you think all ZBar-dependent dynamic libraries are here? No! If you pack Jar package with these DLLs and send it to someone’s PC that has no ImageMagick installed, the program will throw exceptions of loading DLL. The reason is when running the program on your operating system, ImageMagick will read its installation directory from Registry Editor and dynamically load some modules:

ImageMagick modules

To distribute ImageMagick libraries, you’d better build it yourself.

How to Build the Source Code of ImageMagick

Visit http://www.imagemagick.org/script/install-source.php to download ImageMagick-windows.zip.

Find ImageMagick-6.9.2-0 > VisualMagick > configure > configure.exe:

ImageMagick configure

Run configure.exe and select Static Multi-threaded runtimes:

ImageMagick static multi-threaded runtimes

Click Next to generate Visual Studio solution file. Import the project to Visual Studio 2013, and then check all projects named with CORE_:

ImageMagick core libs

Build the project to generate static libs:
ImageMagick static libs

Open JNI project and change the Runtime Library to Multi-threaded (/MT):

multi-threaded

Link the static libraries of ImageMagick to your JNI dynamic library, and then you can pack the following files for distribution:

java barcode program


How to Create a Universal Barcode Reader on Windows 10 with C/C++ Legacy Code

$
0
0

Probably many Windows developers have upgraded operating systems to Windows 10. On Windows 10, Microsoft suggests developers create Universal Windows Apps (UWP) for a variety of devices, including PC, tablet, mobile phone, Hololens and so on. For development, I wonder whether legacy C/C++ SDKs can also seamlessly work on Windows 10, such as Dynamsoft Barcode SDK, which does not officially support UWP development yet. The answer is yes. Let’s see the tricks.

Prerequisites

Where do We Start?

Follow Microsoft’s tutorial to write your first “Hello World” App:

https://msdn.microsoft.com/en-us/library/windows/apps/dn996906.aspx

What’s the difference between Universal Windows app and desktop app?

Unlike Windows desktop app, Universal app is compiled into a package appx, which contains all resources, configurations and executable file. The application can only run in the context of an app container.

How to Invoke C/C++ APIs of Dynamsoft Barcode SDK in UWP App?

Create a new Universal Windows App.

uwp project

Add Image, Button and TextBlock to MainPage.xaml:

<ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
                <StackPanel>
                    <Grid x:Name="Image" Margin="0,0,0,5" VerticalAlignment="Top">
                        <Image x:Name="PreviewImage" HorizontalAlignment="Left" VerticalAlignment="Top" MaxWidth="600"/>
                    </Grid>
                    <StackPanel Orientation="Horizontal" Margin="0, 0, 0, 5" VerticalAlignment="Top">
                        <Button x:Name="button" Margin="0, 0, 5, 0" Click="button_Click" VerticalAlignment="Top">
                            <Viewbox MaxHeight="40" MaxWidth="40">
                                <SymbolIcon Symbol="OpenFile"/>
                            </Viewbox>
                        </Button>
                        <TextBlock x:Name="BarcodeResults" Margin="0,0,0,10" TextWrapping="Wrap" Text="Results:" Height="600" Width="300" VerticalAlignment="Stretch" HorizontalAlignment="Left" />
                    </StackPanel>
                </StackPanel>
            </ScrollViewer>

Loading barcode images with FileOpenPicker:

FileOpenPicker^ picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(".bmp");
picker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;

To get the C++ pointer of the image data buffers from WriteableBitmap, we can refer to the article – Obtaining pointers to data buffers. Here is the code:

byte* GetPointerToPixelData(IBuffer^ pixelBuffer, unsigned int *length)
{
	if (length != nullptr)
	{
		*length = pixelBuffer->Length;
	}
	// Query the IBufferByteAccess interface.
	ComPtr<IBufferByteAccess> bufferByteAccess;
	reinterpret_cast<IInspectable*>(pixelBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));

	// Retrieve the buffer data.
	byte* pixels = nullptr;
	bufferByteAccess->Buffer(&pixels);
	return pixels;
}

We’ll use the API DecodeBuffer, but the underlying required data structure is different. We need to construct the data buffer (BITMAPINFOHEADER + Image data) ourselves:

char *total = (char *)malloc(len + 40);
BITMAPINFOHEADER bitmap_info = { 40, width, height, 0, 32, 0, len, 0, 0, 0, 0 };
memcpy(total, &bitmap_info, 40);
char *data = total + 40;
memcpy(data, buffer, len);

Read barcode image and return results:

iRet = reader.DecodeBuffer((unsigned char*)total, len + 40);

	// Output barcode result
	pszTemp = (char*)malloc(4096);
	if (iRet != DBR_OK)
	{
		sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
		free(pszTemp);
		return nullptr;
	}

	pBarcodeResultArray paryResult = NULL;
	reader.GetBarcodes(&paryResult);

After getting the barcode results, convert C String to Platform::String^. I found the solution from StackOverflow.

results = ref new Array<String^>(paryResult->iBarcodeCount);
	for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
	{
		sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
		sprintf(pszTemp, "%s    Page: %d\r\n", pszTemp, paryResult->ppBarcodes[iIndex]->iPageNum);
		sprintf(pszTemp, "%s    Type: %s\r\n", pszTemp, GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
		pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
		memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
		memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
		sprintf(pszTemp, "%s    Value: %s\r\n", pszTemp, pszTemp1);

		// http://stackoverflow.com/questions/11545951/how-to-convert-from-char-to-platformstring-c-cli
		std::string s_str = std::string(pszTemp);
		std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
		const wchar_t* w_char = wid_str.c_str();
		OutputDebugString(w_char);
		barcode_result = ref new String(w_char);
		results->set(iIndex, barcode_result);
		free(pszTemp1);
	}

Copy DynamsoftBarcodeReaderx86.dll from <Dynamsoft Barcode SDK>\Redist\C_C++ to DynamsoftBarcodeReader\Debug\DynamsoftBarcodeReader\AppX.

appx

Run the UWP Barcode Reader directly from Visual Studio by CTRL+F5 or the Start menu:

UWP from start menu

See the screenshot:

universal windows barcode reader

Known Issues

Source Code

https://github.com/dynamsoftsamples/universal-windows-barcode-reader

How to Make Ruby Barcode Reader with C++ Barcode SDK on Mac OS X

$
0
0

Dynamsoft Barcode SDK, which written in C/C++, supports both Windows and Mac OS X. Last week, I spent some time taking the Ruby online course on codecademy, thereby I decided to create a Ruby Barcode Reader by wrapping Dynamsoft C/C++ Barcode APIs.

Download and Installation

http://www.dynamsoft.com/Downloads/Dynamic-Barcode-Reader-Download.aspx

How to Create and Build Ruby Barcode Reader Project

Create extconf.rb:

require 'mkmf'

extension_name = 'dynamsoftbarcode'

dir_config(extension_name)

create_makefile(extension_name)

Automatically generate Makefile with:

ruby extconf.rb

Open Makefile and change configurations.

  • Dynamsoft Barcode include directory:
    dbrdir = /Applications/Dynamsoft/Barcode\ Reader\ 3.0\ Trial/Include
    
    INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) -I$(dbrdir)
  • Dynamsoft Barcode dylib:
    LIBS = $(LIBRUBYARG_SHARED)  -lpthread -ldl -lobjc -lDynamsoftBarcodeReader

Open dynamsoftbarcode.c. Add entry point and methods:

VALUE BarcodeReader = Qnil;

void Init_dynamsoftbarcode();

VALUE method_decodeFile(VALUE self, VALUE path);

void Init_dynamsoftbarcode() {
	BarcodeReader = rb_define_module("BarcodeReader");
	rb_define_method(BarcodeReader, "decodeFile", method_decodeFile, 1);
}

VALUE method_decodeFile(VALUE self, VALUE path) {
	char *pszPath = StringValueCStr(path);
	VALUE ary = decode(pszPath);
	return ary;
}

Import the sample code and license that provided by Dynamsoft Barcode SDK:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <If_DBR.h>

#define strcmpi(dst, src) strcasecmp(dst, src)

__int64 GetFormat(const char * pstr)
{
	__int64 llFormat = 0;
	const char * pszFormat = pstr;

	if (strcasestr(pszFormat, "code_39") != NULL)
		llFormat |= CODE_39;
	if (strcasestr(pszFormat, "code_128") != NULL)
		llFormat |= CODE_128;
	if (strcasestr(pszFormat, "code_93") != NULL)
		llFormat |= CODE_93;
	if (strcasestr(pszFormat, "codabar") != NULL)
		llFormat |= CODABAR;
	if (strcasestr(pszFormat, "itf") != NULL)
		llFormat |= ITF;
	if (strcasestr(pszFormat, "upc_a") != NULL)
		llFormat |= UPC_A;
	if (strcasestr(pszFormat, "upc_e") != NULL)
		llFormat |= UPC_E;
	if (strcasestr(pszFormat, "ean_13") != NULL)
		llFormat |= EAN_13;
	if (strcasestr(pszFormat, "ean_8") != NULL)
		llFormat |= EAN_8;
	if (strcasestr(pszFormat, "industrial_25") != NULL)
		llFormat |= INDUSTRIAL_25;
	if (strcasestr(pszFormat, "oned") != NULL)
		llFormat = OneD;
	if (strcasestr(pszFormat, "qr_code") != NULL)
		llFormat |= QR_CODE;

	return llFormat;
}

const char * GetFormatStr(__int64 format)
{
	if (format == CODE_39)
		return "CODE_39";
	if (format == CODE_128)
		return "CODE_128";
	if (format == CODE_93)
		return "CODE_93";
	if (format == CODABAR)
		return "CODABAR";
	if (format == ITF)
		return "ITF";
	if (format == UPC_A)
		return "UPC_A";
	if (format == UPC_E)
		return "UPC_E";
	if (format == EAN_13)
		return "EAN_13";
	if (format == EAN_8)
		return "EAN_8";
	if (format == INDUSTRIAL_25)
		return "INDUSTRIAL_25";
	if (format == QR_CODE)
		return "QR_CODE";

	return "UNKNOWN";
}

int decode(const char *pszImageFile)
{
	__int64 llFormat = (OneD |QR_CODE);
	int iMaxCount = 0x7FFFFFFF;
	int iIndex = 0;
	ReaderOptions ro = {0};
	pBarcodeResultArray paryResult = NULL;
	int iRet = -1;
	char * pszTemp = NULL;
	char * pszTemp1 = NULL;
	struct timeval begin, end;

	if (NULL == pszImageFile)
	{
		printf("The syntax of the command is incorrect.\n");
		return 1;
	}

	// Set license
	DBR_InitLicense("B8DF4560D0953299D5454C71A38D1FEB");

	// Read barcode
	gettimeofday(&begin, NULL);
	ro.llBarcodeFormat = llFormat;
	ro.iMaxBarcodesNumPerPage = iMaxCount;
	iRet = DBR_DecodeFile(pszImageFile, &ro, &paryResult);
	gettimeofday(&end, NULL);

	// Output barcode result
	pszTemp = (char*)malloc(4096);
	if (iRet != DBR_OK)
	{
		sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
		printf("%s", pszTemp);
		free(pszTemp);
		return 1;
	}

	if (paryResult->iBarcodeCount == 0)
	{
		sprintf(pszTemp, "No barcode found. Total time spent: %.3f seconds.\r\n",
					((float)((end.tv_sec * 1000 * 1000 +  end.tv_usec) - (begin.tv_sec * 1000 * 1000 + begin.tv_usec))/(1000 * 1000)));
		printf("%s", pszTemp);
		DBR_FreeBarcodeResults(&paryResult);
		return 0;
	}

	sprintf(pszTemp, "Total barcode(s) found: %d. Total time spent: %.3f seconds\r\n\r\n", paryResult->iBarcodeCount,
					((float)((end.tv_sec * 1000 * 1000 +  end.tv_usec) - (begin.tv_sec * 1000 * 1000 + begin.tv_usec))/(1000 * 1000)));
	printf("%s", pszTemp);
	for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
	{
		sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
		// printf("%s", pszTemp);
		sprintf(pszTemp, "%s    Page: %d\r\n", pszTemp, paryResult->ppBarcodes[iIndex]->iPageNum);
		// printf("%s", pszTemp);
		sprintf(pszTemp, "%s    Type: %s\r\n", pszTemp, GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
		// printf("%s", pszTemp);
		pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
		memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
		memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
		sprintf(pszTemp, "%s    Value: %s\r\n", pszTemp, pszTemp1);
		// printf("%s", pszTemp);
		free(pszTemp1);
	}

	free(pszTemp);
	DBR_FreeBarcodeResults(&paryResult);

	return iRet;
}

Convert returned C String to VALUE (VALUE is the C data type for all Ruby objects).

VALUE ary = rb_ary_new();
rb_ary_push(ary, rb_str_new_cstr(pszTemp));

Create a Ruby script barcode_reader.rb to invoke native API:

require 'dynamsoftbarcode'
include BarcodeReader

if ARGV.length == 0
  puts "Please add a barcode file path!"
else
  $filePath = ARGV[0]
  $results = decodeFile($filePath)
  $results.each do |i|
     puts "#{i}"
  end

  puts "Game Over!"
end

Run make. If you get the warnings:

ld: warning: directory not found for option '-L/usr/local/lib'
ld: warning: directory not found for option '-L/usr/local/lib'

Open Makefile and change

ldflags = -L. -L/usr/local/lib

to

ldflags = -L. -L/usr/lib.

If there’s no warning, you will see:

linking shared-object dynamsoftbarcode.bundle

Run sudo make install (The command will copy dynamsoftbarcode.bundle to/Library/Ruby/Site/2.0.0/universal-darwin14).

Run Ruby script:

ruby barcode_reader.rb barcode_file

Here is the screenshot:
Ruby Barcode Reader

References

Source Code

https://github.com/dynamsoftsamples/ruby-barcode-reader

How to Create a Web Barcode Reader App with PHP and Nginx

$
0
0

Dynamsoft Barcode Reader SDK written in C/C++ is capable of reading a variety of 1D and 2D barcode formats including Code 39, Code 93, Code 128, Codabar, QRCode, DataMatrix, PDF417 and so on. In this post, I’m going to demo how to use the SDK to make a simple Web barcode reader app with PHP and Nginx.

Prerequisites

Step 1: How to Build PHP Custom Extension with Dynamsoft Barcode Reader SDK

To use Dynamsoft Barcode Reader SDK with PHP, we need to create a PHP custom extension – php_dbr.dll. Read the tutorial Making PHP Barcode Extension with Dynamsoft Barcode SDK  to build your own PHP barcode extension.

Step 2: How to Configure PHP Environment

  1. Copy php_dbr.dll to %php%\ext.
  2. Copy DynamsoftBarcodeReaderx86.dll to PHP root directory %php%\.
  3. Open %php%\php.ini and add following line:
    extension=php_dbr.dll

    Change max file size if you want to upload big image files:

    upload_max_filesize=20M

Step 3: How to Configure Nginx for PHP

Open %nginx%\conf\nginx.conf and add PHP configuration:

location ~ \.php$ {

    root           html;

    fastcgi_pass   127.0.0.1:9000;

    fastcgi_index  index.php;

    fastcgi_param  SCRIPT_FILENAME <Your Web App Folder>/$fastcgi_script_name;

    include        fastcgi_params;

}

When uploading big files, you may see the error nginx 413 Request Entity Too Large. To fix it, change file size in configuration file:

client_max_body_size 50M;

Step 4: How to Implement Web Barcode App in PHP on Windows

Create a page index.php.

<!DOCTYPE html>
<html>
<head>
  <title>Dynamsoft PHP Barcode Reader</title>
  <script src="jquery-1.11.3.min.js"></script>
  <script src="tiff.min.js"></script>
</head>
<body>
<H1>Dynamsoft PHP Barcode Reader</H1>
<form action="dbr.php" method="post" enctype="multipart/form-data">
    Select barcode image:
    <input type="file" name="readBarcode" id="readBarcode" accept="image/*"><br>
    <input type="submit" value="Read Barcode" name="submit">
</form>
<div id="tiff"></div>
<div id='image'></div>
<script>
      function reset() {
        $("#image").empty();
        $("#tiff").empty();
      }
			var input = document.querySelector('input[type=file]');
			input.onchange = function() {
        reset();
				var file = input.files[0];
				var fileReader = new FileReader();
        // get file extension
        var extension = file.name.split('.').pop().toLowerCase();
        var isTiff = false;
        if (extension == "tif" || extension == "tiff") {
          isTiff = true;
        }
				fileReader.onload = function(e) {
          if (isTiff) {
            console.debug("Parsing TIFF image...");
            //initialize with 100MB for large files
            Tiff.initialize({
              TOTAL_MEMORY: 100000000
            });
            var tiff = new Tiff({
              buffer: e.target.result
            });
            var tiffCanvas = tiff.toCanvas();
            $(tiffCanvas).css({
              "max-width": "800px",
              "width": "100%",
              "height": "auto",
              "display": "block",
              "padding-top": "10px"
            }).addClass("TiffPreview");
            $("#tiff").append(tiffCanvas);
          }
          else {
            var dataURL = e.target.result, img = new Image();
            img.src = dataURL;
            $("#image").append(img);
          }
				}
        if (isTiff) {
            fileReader.readAsArrayBuffer(file);
        }
        else
				    fileReader.readAsDataURL(file);
			}
</script>

</body>
</html>

Because Dynamsoft Barcode Reader supports TIFF image format, in order to load TIFF in HTML5, we can use the tiff js library.

Create dbr.php for reading uploaded barcode images.

<?php
// create absolute file path
function file_build_path(...$segments) {
    return join(DIRECTORY_SEPARATOR, $segments);
}
$file = basename($_FILES["readBarcode"]["name"]);
echo "<p>$file</p>";
if ($file != NULL && $file != "") {
  // get current working directory
  $root = getcwd();
  // tmp dir for receiving uploaded barcode images
  $tmpDir = "uploads/";
  if (!file_exists($tmpDir)) {
    mkdir($tmpDir);
  }
  $target_file = $tmpDir . basename($_FILES["readBarcode"]["name"]);
  $isSuccessful = true;
  $fileType = pathinfo($target_file,PATHINFO_EXTENSION);
  if (!$isSuccessful) {
      echo "Fail to read barcode";
  } else {
      if (move_uploaded_file($_FILES["readBarcode"]["tmp_name"], $target_file)) {
        // dynamsoft barcode reader
        $path = file_build_path($root, $target_file);
        /*
         * Description:
         * array DecodeBarcodeFile( string $filename , bool $isNativeOutput [, bool $isLogOn ] )
         *
         * Return Values:
         * If barcode detected, $array[0] is an array.
         */
        $resultArray = DecodeBarcodeFile($path, false);
        if (is_array($resultArray[0])) {
        	$resultCount = count($resultArray);
        	echo "Total count: $resultCount\n";
        	for($i = 0; $i < $resultCount ; $i++) {
        		$result = $resultArray[$i];
                	echo "<p>Barcode format: $result[0], value: $result[1]</p>";
        	}
        }
        else {
          echo "<p>$resultArray[0]</p>";
        }
        // delete the uploaded barcode image
        unlink($path);
      } else {
          echo "Fail to read barcode.";
      }
  }
}
?>

Run php-cgi:

%php%\php-cgi.exe -b 127.0.0.1:9000 -c %php%\php.ini

Run Nginx:

%nginx%\nginx.exe

Visit localhost:8080/index.php:

php file upload

php barcode reader

Source Code

https://github.com/dynamsoftsamples/php-barcode-reader

How to Make HTML5 Barcode Reader with Desktop and Mobile Cameras

$
0
0

Recently, I noticed someone asked whether Dynamsoft Barcode Reader SDK can work for mobile devices. Because Dynamsoft Barcode Reader SDK does not support ARM yet, we can’t use it to develop native mobile apps. However, don’t be frustrated. Inspired by the article - Face detection using HTML5, javascript, webrtc, websockets, Jetty and OpenCV, I figured out the alternative solution. You can transmit the real-time camera stream to a remote server using HTML5 in Web browsers and decode the barcode image with Dynamsoft Barcode Reader SDK on the server that running on Windows, Linux or Mac. In this article, I will illustrate how to implement an HTML5 Barcode Reader with Cameras for PC and mobile devices step by step.

Prerequisites

  • Server-side Barcode SDK: Dynamsoft Barcode SDK 4.0 - available for Windows, Linux and Mac.
  • WebSocket Server: Jetty – a Java HTTP (Web) Server and Java Servlet container.
  • Web browsers: Chrome and Firefox for Android or Windows. Not supported for iOS.

How to Open Webcam or Mobile Cameras in Chrome and Firefox with HTML5

In HTML5, Navigator.getUserMedia() prompts the user for camera permission. The method behaves differently in Chrome and Firefox, here is how we can correctly use it:

// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia
navigator.getUserMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia;

if (navigator.getUserMedia) {
   navigator.getUserMedia({ audio: true, video: { width: 1280, height: 720 } },
      function(stream) {
         var video = document.querySelector('video');
         video.src = window.URL.createObjectURL(stream);
         video.onloadedmetadata = function(e) {
           video.play();
         };
      },
      function(err) {
         console.log("The following error occured: " + err.name);
      }
   );
} else {
   console.log("getUserMedia not supported");
}

Camera Preview Data for Transmission: Base64 or Binary?

When using Webcam or cameras in Web browsers, we can capture preview image as base64 String and then convert it to binary:

Convert canvas to base64 String:

data = canvas.toDataURL('image/png', 1.0);

Convert base64 to binary:

// stackoverflow: http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata/5100158
function dataURItoBlob(dataURI) {
    // convert base64/URLEncoded data component to raw binary data held in a string
    var byteString;
    if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
    else
        byteString = unescape(dataURI.split(',')[1]);

    // separate out the mime component
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

    // write the bytes of the string to a typed array
    var ia = new Uint8Array(byteString.length);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    return new Blob([ia], {type:mimeString});
}

// convert base64 to binary
newblob = dataURItoBlob(data);
ws.send(newblob);

We can wrap received binary data as BufferedImage on server-side:

        ByteArrayInputStream in = new ByteArrayInputStream(data);
    	BufferedImage bi;
		try {
			bi = ImageIO.read(in);
			File file = new File(mFile);
			// save client data to local image file
			ImageIO.write(bi, "PNG", file);

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

However, the conversion of base64 to binary may affect the performance on mobile devices. If so, we can send base64 String to Jetty WebSocket server and convert base64 String to binary in Java on server-side.

// StackOverflow: http://stackoverflow.com/questions/23979842/convert-base64-string-to-image
String base64Image = message.split(",")[1];
byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(base64Image);

Besides data type, we also need to consider the resolution of the preview image. Since PC is more powerful than the smartphone, we can set resolution 640×480 for desktop and 240×320 (holding your smartphone in portrait orientation) for mobile.

How to Use WebSocket to Send and Receive Data

WebSocket Client in JavaScript

Create WebSocket:

// create websocket
var ws = new WebSocket("ws://192.168.8.84:88");

ws.onopen = function() {

};

ws.onmessage = function (evt) {

};

ws.onclose = function() {

};

ws.onerror = function(err) {

};

Set an interval time for sending camera stream:

// scan barcode
function scanBarcode() {
  intervalId = window.setInterval(function() {
    if (!isConnected || isPaused) {
        return;
    }

    var data = null, newblob = null;

    if (isPC) {
      ws.send("is pc");
      ctx.drawImage(videoElement, 0, 0, videoWidth, videoHeight);
      // convert canvas to base64
      data = canvas.toDataURL('image/png', 1.0);
      // convert base64 to binary
      newblob = dataURItoBlob(data);
      ws.send(newblob);
    }
    else {
      ws.send("is phone");
      mobileCtx.drawImage(videoElement, 0, 0, mobileVideoWidth, mobileVideoHeight);
      // convert canvas to base64
      data = mobileCanvas.toDataURL('image/png', 1.0);
      ws.send(data);
    }

  }, 200);
  console.log("create id: " + intervalId);
}

Do not forget to empty interval events if you stop scanning barcode:

window.clearInterval(intervalId);

To detect PC or mobile devices, you can use following code:

// check devices
function browserRedirect() {
   var deviceType;
   var sUserAgent = navigator.userAgent.toLowerCase();
   var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
   var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
   var bIsMidp = sUserAgent.match(/midp/i) == "midp";
   var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
   var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
   var bIsAndroid = sUserAgent.match(/android/i) == "android";
   var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
   var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
   if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
    deviceType = 'phone';
   } else {
    deviceType = 'pc';
   }
   return deviceType;
}

WebSocket Server in Java

Create server:

public class WebSocketServer {

    public static void main(String[] args) throws Exception {
        Server server = new Server(88);
        server.setHandler(new WSHandler());
        server.setStopTimeout(0);
        server.start();
        server.join();
    }
}

Configure policies:

@WebSocket
public class WSHandler extends WebSocketHandler {

	@Override
	public void configure(WebSocketServletFactory factory) {
		// TODO Auto-generated method stub
		factory.setCreator(new BarcodeCreator());

		// configuration
		factory.getPolicy().setMaxBinaryMessageBufferSize(1024 * 1024);
		factory.getPolicy().setMaxTextMessageBufferSize(1024 * 1024);
		factory.getPolicy().setMaxTextMessageSize(1024 * 1024);
		factory.getPolicy().setMaxBinaryMessageSize(1024 * 1024);
	}
}

Create WebSocket:

@WebSocket
public class BarcodeSocket {

    @OnWebSocketClose
    public void onClose(int statusCode, String reason) {

    }

    @OnWebSocketError
    public void onError(Throwable t) {

    }

    @OnWebSocketConnect
    public void onConnect(Session session) {

    }

    @OnWebSocketMessage
    public void onMessage(byte[] data, int off, int len) {

    }

    @OnWebSocketMessage
    public void onMessage(String message) {

    }

}

public class BarcodeCreator implements WebSocketCreator {

	@Override
	public Object createWebSocket(ServletUpgradeRequest arg0, ServletUpgradeResponse arg1) {
		// TODO Auto-generated method stub
		return new BarcodeSocket();
	}

}

How to Read Barcode in Java with Dynamsoft Barcode Reader SDK

Dynamsoft Barcode Reader does not provide any Java APIs. If you want to use the SDK in Java, you need to create a JNI (Java Native Interface) wrapper DynamsoftBarcodeJNIx64.dll. Please read the article How to Make Java Barcode Reader with Dynamsoft Barcode SDK.

Create a new project in Eclipse. Copy DynamsoftBarcodeJNIx64.dll and DynamsoftBarcodeReaderx64.dll to the project root directory.

jetty project

Reading barcode with a few lines of code:

      JBarcode.DBR_InitLicense(DBRLicense);

      private String readBarcode(String fileName) {
		// Result array
		tagBarcodeResultArray paryResults = new tagBarcodeResultArray();
		// Read barcode
		int iret = JBarcode.DBR_DecodeFile(fileName, 100,
				EnumBarCode.OneD | EnumBarCode.QR_CODE
				| EnumBarCode.PDF417 | EnumBarCode.DATAMATRIX, paryResults);

		System.out.println("DBR_DecodeFile return value: " + iret);
		String r = "";
		for (int iIndex = 0; iIndex < paryResults.iBarcodeCount; iIndex++) {
			tagBarcodeResult result = paryResults.ppBarcodes[iIndex];
			int barcodeDataLen = result.iBarcodeDataLength;

			byte[] pszTemp1 = new byte[barcodeDataLen];
			for (int x = 0; x < barcodeDataLen; x++) {
				pszTemp1[x] = result.pBarcodeData[x];
			}

			r += "Value: " + new String(pszTemp1);
		}

		return r;
      }

Testing HTML5 Barcode Reader in Chrome for Android and Windows

Chrome for Android

mobile android camera

mobile barcode reader

Chrome for Windows

desktop barcode reader

Source Code

https://github.com/dynamsoftsamples/HTML5-Webcam-Barcode-Reader

 

How to Make Web Barcode Reader with NodeJS REST Framework

$
0
0

As cloud computing market continues to skyrocket, more and more IT companies tend to release cloud APIs for developers. Most cloud APIs are exposed via REST (Representational state transfer) Web service. In this post, I will illustrate how to create a barcode reader with Node REST Framework Restify and Dynamsoft Barcode Reader SDK.

Prerequisites

Step 1: How to Build Barcode Extension for Node with Dynamsoft Barcode Reader SDK

To use Dynamsoft Barcode Reader SDK, which implemented in C/C++, we need to create a Node extension. Please read the post – Making Dynamsoft Barcode SDK an Addon for Node.js – to learn how to build dbr.node step by step.

Step 2: How to Create REST Service with Restify

Install restify:

npm install restify

Initialization:

var restify = require('restify');
var fs = require('fs');
var server = restify.createServer();
var dbr = require('./build/Release/dbr');

Use body parser to extract base64 String from HTTP request:

server.use(restify.bodyParser());

Load static resources:

server.get(/.*/, restify.serveStatic({
  directory: __dirname,
  default: 'index.html'
}));

Processing post event with specified route:

server.post('/dbr', function create(req, res, next) {

});

Save Base64 String to a PNG image file:

  var data = new Buffer(req.body, 'base64');
  var file = __dirname + '/' + new Date().getTime() + '.png';

  fs.writeFile(file, data, function(err) {

  });

Decode barcode image with dbr.node:

dbr.decodeFile(
      file,
      function(msg) {
        fs.unlink(file, function(err) {
          console.log('Removed cached: ' + file);
        });

        var final_result = "";
        var hasResult = false;
        for (index in msg) {
          hasResult = true;
          var result = msg[index]
          final_result += "value: " + result['value'] + "; ";
          console.log(result['format']);
          console.log(result['value']);
          console.log("##################");
        }

        if (!hasResult) {
          final_result = "No barcode detected";
        }

        res.send(200, final_result);
        next();
      }
    );

Why getUserMedia doesn’t open Webcam in Chrome?

If you have upgraded Chrome to the latest version 47.0.2526.80, the HTML5 API getUserMedia no longer works:

getusermedia deprecated in chrome

Use OpenSSL to create key and certificate, and then change your code for SSL access:

var server = restify.createServer({
  certificate: fs.readFileSync('path/to/server/certificate'),
  key: fs.readFileSync('path/to/server/key'),
  name: 'MyApp',
});

Run RESTful service:

node server.js

Send camera preview data from Web client to REST server:

var base64 = dbrCanvas.toDataURL('image/png', 1.0);
    var data = base64.replace(/^data:image\/(png|jpeg|jpg);base64,/, "");
    var imgData = JSON.stringify(data);
    $.ajax({
      url: '/dbr',
      dataType: 'json',
      data: imgData,
      type: 'POST',
      success: function(result) {
        console.log(result);
        if (isPaused) {
          return;
        }
        var barcode_result = document.getElementById('dbr');
        barcode_result.textContent = result;

        // display barcode result
        if (result.indexOf("No barcode") == -1) {
          isPaused = true;
          window.clearInterval(intervalId);
          console.log("Get result, clean id: " + intervalId);
          buttonGo.disabled = false;
          if (isPC) {
            canvas.style.display = 'block';
          } else {
            mobileCanvas.style.display = 'block';
          }
        }
      }
    });

Connect a Webcam to your PC and test the RESTful Barcode Reader:

node barcode reader

Source Code

https://github.com/dynamsoftsamples/node-barcode-reader

Viewing all 145 articles
Browse latest View live