Building Python Barcode Extension with DBR 5.0 on Windows

DBR 5.x is a big leap comparing to version 4.x. A lot of code has been refactored and optimized. This tutorial aims to help developers get familiar with new APIs, and learn how to build a Python barcode application using Dynamsoft Barcode Reader SDK 5.0.

Prerequisites

Python Barcode Extension

Create dbr.c and include three header files.

#include <Python.h>
#include "DynamsoftBarcodeReader.h"
#include <ndarraytypes.h>

DBR 5.x defines all data structures with one header file, which is more readable than multiple header files in DBR 4.x.

Define Python methods and initialize Python module:

static PyMethodDef Methods[] =
{
    {"create", create, METH_VARARGS, NULL},
    {"destroy", destroy, METH_VARARGS, NULL},
    {"initLicense", initLicense, METH_VARARGS, NULL},
    {"decodeFile", decodeFile, METH_VARARGS, NULL},
    {"decodeBuffer", decodeBuffer, METH_VARARGS, NULL},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initdbr(void)
{
     (void) Py_InitModule("dbr", Methods);
}

Set a global DBR handler:

#define DBR_NO_MEMORY 0
#define DBR_SUCCESS   1

void* hBarcode = NULL; 

/**
 * Create DBR instance
 */
static int createDBR() 
{
    if (!hBarcode) {
        hBarcode = DBR_CreateInstance();
        if (!hBarcode)
        {
            printf("Cannot allocate memory!\n");
            return DBR_NO_MEMORY;
        }
    }

    return DBR_SUCCESS;
}

/**
 * Destroy DBR instance
 */
static void destroyDBR()
{
    if (hBarcode) {
        DBR_DestroyInstance(hBarcode);
    }
}

Set a valid DBR license:

static PyObject *
initLicense(PyObject *self, PyObject *args)
{
    if (!createDBR()) 
    {
        return NULL;
    }

    char *pszLicense;
    if (!PyArg_ParseTuple(args, "s", &pszLicense)) {
        return NULL;
    }

	int ret = DBR_InitLicenseEx(hBarcode, pszLicense);
    return Py_BuildValue("i", ret);
}

Detect barcodes from an image that captured by OpenCV API:

static PyObject *
decodeBuffer(PyObject *self, PyObject *args)
{
    if (!createDBR()) 
    {
        return NULL;
    }

    PyObject *o;
    int iFormat;
    if (!PyArg_ParseTuple(args, "Oi", &o, &iFormat))
        return NULL;

    PyObject *ao = PyObject_GetAttrString(o, "__array_struct__");

    if ((ao == NULL) || !PyCObject_Check(ao)) {
        PyErr_SetString(PyExc_TypeError, "object does not have array interface");
        return NULL;
    }

    PyArrayInterface *pai = (PyArrayInterface*)PyCObject_AsVoidPtr(ao);
    if (pai->two != 2) {
        PyErr_SetString(PyExc_TypeError, "object does not have array interface");
        Py_DECREF(ao);
        return NULL;
    }

    // Get image information
    char *buffer = (char*)pai->data; // The address of image data
    int width = pai->shape[1];       // image width
    int height = pai->shape[0];      // image height
    int size = pai->strides[0] * pai->shape[0]; // image size = stride * height

    // Initialize Dynamsoft Barcode Reader
    int iMaxCount = 0x7FFFFFFF;
	SBarcodeResultArray *pResults = NULL;
	DBR_SetBarcodeFormats(hBarcode, iFormat);
	DBR_SetMaxBarcodesNumPerPage(hBarcode, iMaxCount);

    // Detect barcodes
    int iRet = DBR_DecodeBufferEx(hBarcode, buffer, width, height, width * 3, IPF_RGB_888, &pResults);
    
    // Wrap results
    PyObject *list = createPyResults(pResults);
    
    Py_DECREF(ao);
    return list;
}

How to Build the Extension

Set Visual Studio environment:

  • Visual Studio 2010 (VS10): SET VS90COMNTOOLS=%VS100COMNTOOLS%
  • Visual Studio 2012 (VS11): SET VS90COMNTOOLS=%VS110COMNTOOLS%
  • Visual Studio 2013 (VS12): SET VS90COMNTOOLS=%VS120COMNTOOLS%
  • Visual Studio 2015 (VS14): SET VS90COMNTOOLS=%VS140COMNTOOLS%

If you are using Visual Studio 2015, use the following command:

SET VS90COMNTOOLS=%VS140COMNTOOLS%

Add the header file directories of DBR 5.0 and NumPy  to setup.py:

from distutils.core import setup, Extension

module_dbr = Extension('dbr',
                        sources = ['dbr.c'], 
                        include_dirs=["F:\\Python27\\Lib\\site-packages\\numpy\\core\\include\\numpy", 'e:\\Program Files (x86)\\Dynamsoft\\Barcode Reader 5.0\\Components\\C_C++\\Include'],
                        library_dirs=['e:\\Program Files (x86)\\Dynamsoft\Barcode Reader 5.0\\Components\\C_C++\\Lib'],
                        libraries=['DBRx86'])

setup (name = 'DynamsoftBarcodeReader',
        version = '1.0',
        description = 'Python barcode extension',
        ext_modules = [module_dbr])

Build the Python extension:

python setup.py build install

Copy Dynamsoft\Barcode Reader 5.0\Components\C_C++\Redist\DynamsoftBarcodeReaderx86.dll to Python27\Lib\site-packages

A Simple Python Barcode Reader

Create camera.py.

Import OpenCV and DBR:

import cv2
import dbr

Open the default camera:

vc = cv2.VideoCapture(0)

Set a trial or full SDK license. With an invalid license, the SDK will return an incomplete result:

dbr.initLicense("t0260NQAAALGw+aCAePXdOS3p1xkqT5hesExKVpEe7NiIhkdlUz/Jvx8km3ItI0ykUcmeP67BYVlJ2PDW++bjSYmDLmyMgOmmvc0mdvhlSy500kqnLoBAL+TybcdAP42b5p5WehK9Gsmweqi+ydK6B0KaUNQMDJZ1DrnhDXZ209pfpJoVybPk/CMcDKXaF2oRLKEOYVscXTF6mbiWUnMP5lj4OdTvFa0eVRcE0q9BckiqYgUZLK4L6DVgRXWRL5nRPtvEtd+qZe6psu0JZ7HEPhsbodfAVH2G436z1QahLGJXdQCoQv8UQ/quGQP2wCWemfueeKJ4Y6WsvEvmkUpizbTOE3Njjaw=")

Capture a frame:

rval, frame = vc.read();

Read barcodes:

results = dbr.decodeBuffer(frame, formats)
if (len(results) > 0):
    print(get_time())
    print("Total count: " + str(len(results)))
    for result in results:
        print("Type: " + result[0])
        print("Value: " + result[1] + "\n")

How to Run the App

  1. Connect a USB webcam to your PC.
  2. Run camera.py:
    python camera.py

python barcode reader

Source Code

https://github.com/dynamsoft-dbr/python-barcode-windows