Building Node.js Barcode Addon with DBR v5.0

Dynamsoft recently released Barcode Reader SDK v5.0 for Windows. You can think of it as a brand new product because a large number of APIs and data structures are redefined. If you have downloaded DBR v5.0 and tried to build Node.js barcode addon with it, you have to spend some time modifying the sample code that written for DBR v4.x. In this article, I will share the difference between DBR v4.x and DBR v5.0, as well as how to update the current code to fit the new interfaces.

Prerequisites

  • DBR v5.0
  • Node v5.5.0
  • Npm 3.3.12
  • Node-gyp v3.5.0

The Changes of DBR v5.0

The multiple header files used in version 4.3 are now merged into a header file called DynamsoftBarcodeReader.h. It is more concise now:

barcode sdk header changes

All barcode formats have been renamed, so you have to modify the code:

barcode sdk API change

The ends of the interfaces that used in DBR v4.3 are added with “Ex”.

Before

  • DBR_API int DBR_DecodeFile(const char* pFileName,

const pReaderOptions pOption,

pBarcodeResultArray *ppResults);

  • DBR_API int DBR_DecodeBuffer(unsigned char* pDIBBuffer,

int iBufferSize,

const pReaderOptions pOptions,

pBarcodeResultArray *ppResults

);

  • DBR_API int DBR_DecodeStream(unsigned char* pFileStream,int iFileSize,

const pReaderOptions pOptions,

pBarcodeResultArray* ppResults);

After

  • DBR_API int DBR_DecodeFileEx(void*  hBarcode, const char* pFileName, SBarcodeResultArray **ppResults);
  • DBR_API int DBR_DecodeBufferEx(void*  hBarcode, unsigned char* pBuffer, int iWidth, int iHeight, int iStride, ImagePixelFormat format, SBarcodeResultArray **ppResults);
  • DBR_API int DBR_DecodeStreamEx(void*  hBarcode, unsigned char* pFileStream, int iFileSize, SBarcodeResultArray **ppResults);

Barcode-relevant data structures are also renamed.

Before

typedef struct tagBarcodeResult
{
    __int64 llFormat;
    char* pBarcodeData;
    int iBarcodeDataLength;
    int iLeft;
    int iTop;
    int iWidth;
    int iHeight;
    int iX1;
    int iY1;
    int iX2;
    int iY2;
    int iX3;
    int iY3;
    int iX4;
    int iY4;
    int iPageNum;
} BarcodeResult, *pBarcodeResult;

typedef struct tagBarcodeResultArray
{
    int iBarcodeCount;
    pBarcodeResult *ppBarcodes;
} BarcodeResultArray, *pBarcodeResultArray;

After

typedef struct tagSBarcodeResult
{
    BarcodeFormat emBarcodeFormat;
    char* pBarcodeData;
    int iBarcodeDataLength;
    int iLeft;
    int iTop;
    int iWidth;
    int iHeight;
    int iX1;
    int iY1;
    int iX2;
    int iY2;
    int iX3;
    int iY3;
    int iX4;
    int iY4;
    int iPageNum;
    wchar_t* pBarcodeText;
    int iAngle;
    int iModuleSize;
    BOOL bIsUnrecognized;
    const char* pBarcodeFormatString;
} SBarcodeResult;

typedef struct tagSBarcodeResultArray
{
    int iBarcodeCount;
    SBarcodeResult **ppBarcodes;
} SBarcodeResultArray;

Upgrading Node.js Barcode Addon

Open binding.gyp and set the header and library paths of DBR v5.0. Because DBR v5.0 only supports Windows, you don’t need to add settings for macOS and Linux.

{
  "targets": [
    {
      'target_name': "dbr",
      'sources': [ "dbr.cc" ],
      'conditions': [
          ['OS=="win"', {
            'defines': [
              'WINDOWS_DBR',
            ],
            'include_dirs': [
                "E:\Program Files (x86)\Dynamsoft\Barcode Reader 5.0\Components\C_C++\Include"
            ],
            'libraries': [
                "-lE:\Program Files (x86)\Dynamsoft\Barcode Reader 5.0\Components\C_C++\Lib\DBRx64.lib"
            ],
            'copies': [
            {
              'destination': 'build/Release/',
              'files': [
                'E:\Program Files (x86)\Dynamsoft\Barcode Reader 5.0\Components\C_C++\Redist\DynamsoftBarcodeReaderx64.dll'
              ]
            }]
          }]
      ]
    }
  ]
}

Open dbr.cc. When using DBR v4.x, the function InitLicense does not have to be called. With DBR v5.0, you need to use it to create a DBR handler.

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

    String::Utf8Value license(args[0]->ToString());
    char *pszLicense = *license;
    hBarcode = DBR_CreateInstance();
    DBR_InitLicenseEx(hBarcode, pszLicense);
}

Modify detection code with new methods:

static void DetectionWorking(uv_work_t *req)
{
    if (!hBarcode)
    {
        printf("Barcode reader handler not initialized.\n");
        return;
    }
    // get the reference to BarcodeWorker
    BarcodeWorker *worker = static_cast<BarcodeWorker *>(req->data);

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

    // decode barcode image
    int ret = 0;
    switch(worker->bufferType)
    {
        case FILE_STREAM:
            {
                if (worker->buffer)
                    ret = DBR_DecodeStreamEx(hBarcode, worker->buffer, worker->size, &pResults);
            }
            break;
        case YUYV_BUFFER:
            {
                if (worker->buffer)
                {
                    int dibsize = 0;
                    int width = worker->width, height = worker->height;
                    int size = width * height;
                    int index = 0;
                    unsigned char* data = new unsigned char[size];
                    // get Y from YUYV
                    for (int i = 0; i < size; i++)
                    {
                        data[i] = worker->buffer[index];
                        index += 2;
                    }
                    // gray conversion
                    // ConvertCameraGrayDataToDIBBuffer(data, size, width, height, &pdibdata, &dibsize);
                    // read barcode
                    ret = DBR_DecodeBufferEx(hBarcode, data, width, height, width, IPF_GrayScaled, &pResults);
                    // release memory
                    delete []data, data=NULL;
                }
            }
            break;
        default:
            {
                ret = DBR_DecodeFileEx(hBarcode, worker->filename, &pResults);
            }
    }
    
    if (ret)
        printf("Detection error code: %d\n", ret);

    // save results to BarcodeWorker
    worker->errorCode = ret;
    worker->pResults = pResults;
}

Build the addon:

node-gyp configure
node-gyp build

In dbr.js, call initLicense first and then invoke other barcode detection interfaces.

rl.question("Please input a barcode image path: ", function(answer) {
    dbr.initLicense("");
    decodeFileStreamAsync(answer);
    decodeFileAsync(answer);
    // decodeYUYVAsync(answer, 640, 480);
    rl.close();
});

It is time to use Dynamsoft Barcode Reader v5.0 to create Node.js barcode addon now.

Source Code

https://github.com/yushulx/nodejs-barcode-for-win-linux-mac/tree/DBR5.0