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

Raspberry Pi Barcode Scanner with GPIO

$
0
0

Previously, I shared two articles demonstrating how to build a Raspberry Pi barcode scanner in C/C++ with Dynamsoft Barcode Reader SDK, and how to optimize the code with thread. The hardware I used only includes Raspberry Pi 2 and Webcam. Now it is time to have fun with GPIO (General-purpose input/output). Assume you want to get rid of the display screen for making a robot with power bank, wheel, and webcam. And you need to use some indicators to monitor the status of barcode recognition. How to make it with GPIO pins and other peripherals?

raspberry pi GPIO and LED

Compose the GPIO Circuit and Blink LED in Python

To get started with Raspberry Pi physical interface, it is recommended to read the official tutorial.

With an LED, a resistor and jumper leads, we can compose a simple GPIO circuit :

GPIO circuit

GPIO Zero is a pre-installed Python library for controlling GPIO components. With the library, we can easily flash the LED on and off at run-time in Python:

from gpiozero import LED
from time import sleep

led = LED(17)

while True:
    led.on()
    sleep(1)
    led.off()
    sleep(1)

Improve Raspberry Pi Barcode Scanner with GPIO in C/C++

Do you want to use the above code? Although you can make a Python wrapper for Dynamsoft Barcode Reader SDK, it is better to use a GPIO access library written in C – WiringPi.

Install WiringPi with following commands:

git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

Here is the simplest blink program with WiringPi:

#include <wiringPi.h>
int main (void)
{
  wiringPiSetup () ;
  pinMode (0, OUTPUT) ;
  for (;;)
  {
    digitalWrite (0, HIGH) ; delay (500) ;
    digitalWrite (0,  LOW) ; delay (500) ;
  }
  return 0 ;
}

According to the API, we can update the source code of Raspberry Pi barcode scanner:

Raspberry Pi barcode scanner

When barcodes detected, flash the LED with:

digitalWrite(0, HIGH); 
delay(500);

Here is the demo video:

If you are interested in Dynamsoft Barcode Reader SDK for Raspberry Pi, contact support@dynamsoft.com.

Source Code

https://github.com/dynamsoftlabs/cplusplus-webcam-barcode-reader

 

The post Raspberry Pi Barcode Scanner with GPIO appeared first on Code Pool.


Android Barcode Scanner with Dynamsoft Mobile Barcode SDK

$
0
0

Dynamsoft aims to make barcode SDK available for all mainstream platforms, including Windows, Linux, macOS, iOS, and Android. There are many developers devoted to developing mobile barcode scanner app for iOS and Android platforms. To expedite the developing work, some of them may rely on a powerful detection and recognition libraries, like Dynamsoft mobile barcode SDK. In this post, let’s take a glimpse of how to use barcode SDK for Android to build Android barcode scanner with a few lines of code.

Android Barcode SDK

Download

Android Barcode Scanner

Open Android Studio and select File > New > New Project the menu option to create a new project with the template Empty Activity.

Import the AAR package DynamsoftBarcodeReader.aar, which is included in SDK, as a module:

aar import

Press F4 to open Project Structure and then add the dependent module:

aar dependency

Now, you can use Dynamsoft Barcode Reader in your Android project.

UI design

The app mainly consists of an About dialog, the Camera Preview layout, and a Setting view.

About Dynamsoft Android Barcode SDK:

android barcode scanner about

Camera preview for scanning barcode:

android barcode scanner result

Optional barcode types:

android barcode scanner type

Configuration

Edit AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.dynamsoft.demo.dynamsoftbarcodereaderdemo">
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/logo"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait"
            android:theme="@style/Theme.AppCompat.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".BarcodeTypeActivity"></activity>
    </application>
</manifest>

To invoke camera API, you need to declare the permission and feature:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

The main Activity has no action bar, therefore we can choose the following theme style:

android:theme="@style/Theme.AppCompat.NoActionBar"

The BarcodeTypeActivity is for selecting barcode types:

<activity android:name=".BarcodeTypeActivity"></activity>

Source Code Anatomy

Since from Android 6.0 (API level 23), you need to request permissions while the app is running. Here is the code for requesting the camera permission:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) !=  PackageManager.PERMISSION_GRANTED) {

            if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                    Manifest.permission.CAMERA)) {
            }
            else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.CAMERA}, PERMISSIONS_REQUEST_CAMERA);
            }
}

Initialize Dynamsoft Barcode Reader with a valid license:

BarcodeReader  mBarcodeReader = new BarcodeReader("<license>");

Open a camera and set its focus continuous:

private void openCamera()
{
        new Thread(new Runnable() {
            @Override
            public void run() {
                mCamera = getCameraInstance();

                if (mCamera != null) {
                    mCamera.setDisplayOrientation(90);
                    Camera.Parameters cameraParameters = mCamera.getParameters();
                    cameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
                    mCamera.setParameters(cameraParameters);
                }

                Message message = handler.obtainMessage(OPEN_CAMERA, 1);
                message.sendToTarget();
            }

        }).start();
}

Set preview callback and start the preview:

if (mCamera != null) {
                        mCamera.setPreviewCallback(MainActivity.this);
                        mSurfaceHolder.setCamera(mCamera);
                        Camera.Parameters p = mCamera.getParameters();
                        if (mFlashTextView.getText().equals("Flash on"))
                            p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);

                        mCamera.setParameters(p);
                        mSurfaceHolder.startPreview();
}

Switch the flash:

public void setFlash(View v) {

        if (mCamera != null) {
            Camera.Parameters p = mCamera.getParameters();
            String flashMode = p.getFlashMode();
            if (flashMode.equals(Camera.Parameters.FLASH_MODE_OFF)) {
                 p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
                 mFlashImageView.setImageResource(R.mipmap.flash_on);
                 mFlashTextView.setText("Flash on");
            }
            else {
                 p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                 mFlashImageView.setImageResource(R.mipmap.flash_off);
                 mFlashTextView.setText("Flash off");
             }

            mCamera.setParameters(p);
            mCamera.startPreview();
        }
}

Implement Camera.PreviewCallback and read barcode in function onPreviewFrame:

@Override
public void onPreviewFrame(byte[] data, Camera camera) {

        if (mFinished && !mIsDialogShowing) {
            mFinished = false;

            Camera.Size size = camera.getParameters().getPreviewSize();

            mImageHeight = size.height;

            mBarcodeReader.readSingleAsync(data, size.width, size.height, mBarcodeFormat, new FinishCallback() {

                @Override

                public void onFinish(ReadResult readResult) {
                    Message message = handler.obtainMessage(READ_RESULT, readResult);
                    message.sendToTarget();
                }
            });
        }
}

Show About dialog:

public void showAbout(View v) {
        CustomDialog.Builder builder = new CustomDialog.Builder(this);
        builder.setTitle("About");
        builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
                mIsDialogShowing = false;
            }
        });

        Spanned spanned = Html.fromHtml("<font color='#FF8F0D'><a href=\"http://www.dynamsoft.com\">Download Free Trial here</a></font><br/>");
        builder.setMessage(spanned);
        builder.create(R.layout.about, R.style.AboutDialog).show();
        mIsDialogShowing = true;
}

Start BarcodeTypeActivity to select barcode types:

Intent intent = new Intent(this, BarcodeTypeActivity.class);
intent.putExtra(BarcodeTypeActivity.BarcodeFormat, mBarcodeFormat);
startActivityForResult(intent, RC_BARCODE_TYPE);

Video

https://www.youtube.com/watch?v=TNOAMCsCi-I

App Download

Install the app from Google Play.

Source Code

https://github.com/dynamsoft-dbr/Android-barcode-scanner

The post Android Barcode Scanner with Dynamsoft Mobile Barcode SDK appeared first on Code Pool.

WinForm Barcode Reader with Webcam and C#

$
0
0

When building a .NET application to read barcodes on Windows via camera, you need two types of SDKs – one for webcam, and the other for barcodes. In this post, I want to share how to use .Net webcam and barcode SDKs to create a simple WinForm barcode reader application in C#.

webcam barcode reader in C#

WinForm Barcode Reader

.NET Webcam SDK – Touchless

Touchless SDK is a free and open source SDK for .NET applications. It enables developers to create multi-touch based applications using a webcam for input. The SDK simplified the camera interface by wrapping DirectShow API.

.NET Barcode SDK – Dynamsoft Barcode Reader

Dynamsoft Barcode Reader SDK is a commercial barcode SDK developed by Dynamsoft. If you do not have a valid license, you can use the trial version for evaluation. As for free barcode SDK, ZXing.NET is a good option.

How to build a Windows barcode app

Launch Visual Studio 2015 to create a WinForm project.

Add Dynamsoft Barcode Reader to the project via Nuget:

install .NET barcode SDK via nuget

Add TouchlessLib.dll to reference:

touchless sdk

Add WebCamLib.dll to project. Set ‘Copy always’ to ‘Copy to Output Directory’ in order to automatically copy the dll to output directory when building the project.

webcamlib

Initialize Touchless and Dynamsoft Barcode Reader:

// Initialize Dynamsoft Barcode Reader
_barcodeReader = new BarcodeReader();
// Initialize Touchless
_touch = new TouchlessMgr();

Show a system dialog to load an image into PictureBox:

            using (OpenFileDialog dlg = new OpenFileDialog())
            {
                dlg.Title = "Open Image";

                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    Bitmap bitmap = null;
                    
                    try
                    {
                        bitmap =  new Bitmap(dlg.FileName);
                    }
                    catch (Exception exception)
                    {
                        MessageBox.Show("File not supported.");
                        return;
                    }

                    pictureBox1.Image = new Bitmap(dlg.FileName);
                }
            }

Start webcam to acquire images and register a callback function for receiving frames:

            // Start to acquire images
            _touch.CurrentCamera = _touch.Cameras[0];
            _touch.CurrentCamera.CaptureWidth = _previewWidth; // Set width
            _touch.CurrentCamera.CaptureWidth = _previewHight; // Set height
            _touch.CurrentCamera.OnImageCaptured += new EventHandler<CameraEventArgs>(OnImageCaptured); // Set preview callback function

The frame event is triggered in camera thread. You have to render results in UI thread:

        private void OnImageCaptured(object sender, CameraEventArgs args)
        {
            // Get the bitmap
            Bitmap bitmap = args.Image;

            // Read barcode and show results in UI thread
            this.Invoke((MethodInvoker)delegate
            {
                pictureBox1.Image = bitmap;
                ReadBarcode(bitmap);
            });
        }

Read bitmap and display results on TextBox:

        private void ReadBarcode(Bitmap bitmap)
        {
            // Read barcodes with Dynamsoft Barcode Reader
            Stopwatch sw = Stopwatch.StartNew();
            sw.Start();
            BarcodeResult[] results = _barcodeReader.DecodeBitmap(bitmap);
            sw.Stop();
            Console.WriteLine(sw.Elapsed.TotalMilliseconds + "ms");

            // Clear previous results
            textBox1.Clear();

            if (results == null)
            {
                textBox1.Text = "No barcode detected!";
                return;
            }

            // Display barcode results
            foreach (BarcodeResult result in results)
            {                
                textBox1.AppendText(result.BarcodeText + "\n");
                textBox1.AppendText("\n");
            }
        }

Build and run the WinForm barcode application:

WinForm barcode reader in C#

How to monitor .NET API performance

When using an algorithm API, you may care about the time cost more than accuracy. To calculate the elapsed time, use the code as follows:

            Stopwatch sw = Stopwatch.StartNew();
            sw.Start();
            BarcodeResult[] results = _barcodeReader.DecodeBitmap(bitmap);
            sw.Stop();
            Console.WriteLine(sw.Elapsed.TotalMilliseconds + "ms");

Source Code

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

 

The post WinForm Barcode Reader with Webcam and C# appeared first on Code Pool.

Read Barcode from Webcam Viewer with DirectShow.NET

$
0
0

Previously I shared how to use Touchless, which wraps the win32 APIs of DirectShow, to control webcam in C#. In this article, let’s take a further step to see how to use the more complicated DirectShow.NET APIs to capture the video stream and read barcode from preview frames on Windows.

DirectShow.NET Webcam barcode reader

Resources for Learning DirectShow.NET

Webcam Viewer with DirectShow.NET

If you have downloaded the samples of DirectShow.NET, you can open Samples\Capture\PlayCap to learn how to implement a basic webcam viewer.

Get connected devices

DsDevice[] devices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);

If there is nothing connected, the returned array size is zero.

Get DirectShow interfaces

int hr = 0;

this.graphBuilder = (IFilterGraph2)new FilterGraph();
this.captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
this.mediaControl = (IMediaControl)this.graphBuilder;
this.videoWindow = (IVideoWindow)this.graphBuilder;
DsError.ThrowExceptionForHR(hr);

Attach the filter graph to the capture graph

hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(hr);

Bind Moniker to a filter object

Use the first video capture device:

            int hr = 0;
            IEnumMoniker classEnum = null;
            IMoniker[] moniker = new IMoniker[1];
            object source = null;

            // Create the system device enumerator
            ICreateDevEnum devEnum = (ICreateDevEnum)new CreateDevEnum();

            // Create an enumerator for the video capture devices
            hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, 0);
            DsError.ThrowExceptionForHR(hr);

            // The device enumerator is no more needed
            Marshal.ReleaseComObject(devEnum);

            // If there are no enumerators for the requested type, then 
            // CreateClassEnumerator will succeed, but classEnum will be NULL.
            if (classEnum == null)
            {
                throw new ApplicationException("No video capture device was detected.\r\n\r\n" +
                                               "This sample requires a video capture device, such as a USB WebCam,\r\n" +
                                               "to be installed and working properly.  The sample will now close.");
            }

            // Use the first video capture device on the device list.
            // Note that if the Next() call succeeds but there are no monikers,
            // it will return 1 (S_FALSE) (which is not a failure).  Therefore, we
            // check that the return code is 0 (S_OK).

            if (classEnum.Next(moniker.Length, moniker, IntPtr.Zero) == 0)
            {
                // Bind Moniker to a filter object
                Guid iid = typeof(IBaseFilter).GUID;
                moniker[0].BindToObject(null, null, ref iid, out source);
            }
            else
            {
                throw new ApplicationException("Unable to access video capture device!");
            }

            // Release COM objects
            Marshal.ReleaseComObject(moniker[0]);
            Marshal.ReleaseComObject(classEnum);

            // An exception is thrown if cast fail
            return (IBaseFilter)source;

Add camera source to graph

hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
DsError.ThrowExceptionForHR(hr);

Add SampleGrabber to graph

Configure SampleGrabber and set callback function for video stream:

sampleGrabber = new SampleGrabber() as ISampleGrabber;

{
            AMMediaType media;
            int hr;
            // Set the media type to Video/RBG24
            media = new AMMediaType();
            media.majorType = MediaType.Video;
            media.subType = MediaSubType.RGB24;
            media.formatType = FormatType.VideoInfo;
            hr = sampleGrabber.SetMediaType(media);
            DsError.ThrowExceptionForHR(hr);
            DsUtils.FreeAMMediaType(media);
            media = null;
            hr = sampleGrabber.SetCallback(this, 1);
            DsError.ThrowExceptionForHR(hr);
}

Add the filter to graph:

hr = this.graphBuilder.AddFilter(sampleGrabber as IBaseFilter, "Frame Callback");
DsError.ThrowExceptionForHR(hr);

Configure the preview settings

Set the width, height, and color format:

private void SetConfigParams(ICaptureGraphBuilder2 capGraph, IBaseFilter capFilter, int iFrameRate, int iWidth, int iHeight)
        {
            int hr;
            object config;
            AMMediaType mediaType;
            // Find the stream config interface
            hr = capGraph.FindInterface(
                PinCategory.Capture, MediaType.Video, capFilter, typeof(IAMStreamConfig).GUID, out config);

            IAMStreamConfig videoStreamConfig = config as IAMStreamConfig;
            if (videoStreamConfig == null)
            {
                throw new Exception("Failed to get IAMStreamConfig");
            }

            // Get the existing format block
            hr = videoStreamConfig.GetFormat(out mediaType);
            DsError.ThrowExceptionForHR(hr);

            // copy out the videoinfoheader
            VideoInfoHeader videoInfoHeader = new VideoInfoHeader();
            Marshal.PtrToStructure(mediaType.formatPtr, videoInfoHeader);

            // if overriding the framerate, set the frame rate
            if (iFrameRate > 0)
            {
                videoInfoHeader.AvgTimePerFrame = 10000000 / iFrameRate;
            }

            // if overriding the width, set the width
            if (iWidth > 0)
            {
                videoInfoHeader.BmiHeader.Width = iWidth;
            }

            // if overriding the Height, set the Height
            if (iHeight > 0)
            {
                videoInfoHeader.BmiHeader.Height = iHeight;
            }

            // Copy the media structure back
            Marshal.StructureToPtr(videoInfoHeader, mediaType.formatPtr, false);

            // Set the new format
            hr = videoStreamConfig.SetFormat(mediaType);
            DsError.ThrowExceptionForHR(hr);

            DsUtils.FreeAMMediaType(mediaType);
            mediaType = null;
        }

Render the preview

hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, (sampleGrabber as IBaseFilter), null);
DsError.ThrowExceptionForHR(hr);

Video Window Configuration

Set PictureBox as the video window and resize the video position:

            int hr = 0;
            // Set the video window to be a child of the PictureBox
            hr = this.videoWindow.put_Owner(pictureBox1.Handle);
            DsError.ThrowExceptionForHR(hr);

            hr = this.videoWindow.put_WindowStyle(WindowStyle.Child);
            DsError.ThrowExceptionForHR(hr);

            // Make the video window visible, now that it is properly positioned
            hr = this.videoWindow.put_Visible(OABool.True);
            DsError.ThrowExceptionForHR(hr);

            // Set the video position
            Rectangle rc = pictureBox1.ClientRectangle;
            hr = videoWindow.SetWindowPosition(0, 0, _previewWidth, _previewHeight);
            DsError.ThrowExceptionForHR(hr);

Start webcam preview

rot = new DsROTEntry(this.graphBuilder);
hr = this.mediaControl.Run();
DsError.ThrowExceptionForHR(hr);

Asynchronously Read Barcode

Because it takes the time to read barcodes, once the callback function triggered, we should call the algorithm method and render GUI asynchronously. Do not forget to flip the bitmap:

public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
        {

            Bitmap v = new Bitmap(_previewWidth, _previewHeight, _previewStride,
                PixelFormat.Format24bppRgb, pBuffer);
            v.RotateFlip(RotateFlipType.Rotate180FlipX);

            if (isFinished)
            {   
                this.BeginInvoke((MethodInvoker)delegate
                {
                    isFinished = false;
                    ReadBarcode(v);
                    isFinished = true;
                });
            }
            return 0;
        }

Source Code

https://github.com/yushulx/DirectShow.NET-Webcam-Barcode-Reader

The post Read Barcode from Webcam Viewer with DirectShow.NET appeared first on Code Pool.

How to Convert OpenCV Image Data from Python to C

$
0
0

OpenCV officially provides both C++ and Python APIs for developers. Most of the time, developers just need to use one kind of programming languages to read, write and process images with hundreds of computer vision algorithms. However, if you want to use OpenCV Python APIs with an extended C/C++ library, it will be tricky to pass the data. In this article, I will share how to read camera stream with OpenCV-Python and detect barcode with Dynamsoft C/C++ Barcode SDK.

webcam barcode reader with OpenCV Python

Development Environment

Python Extension for Reading Barcode from OpenCV Image Data

Installation

Copy DynamsoftBarcodeReaderx86.dll and cv2.pyd to Python27\Lib\site-packages.

What is the type of the frame data that output by OpenCV?

To convert the image data, we have to know what type it is. The type is numpy.ndarray:

> rval, frame = vc.read();
> print type(frame)
> <type 'numpy.ndarray'>

How to get the C/C++ pointer that pointing to numpy.ndarray?

According to the OpenCV source file opencv\modules\python\src2\cv2.cv.hpp, we can use the following code to get the memory address of the data in C:

    PyObject *o;
    if (!PyArg_ParseTuple(args, "O", &o))
        return NULL;

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

    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;
    }

    // Construct data with header info and image data 
    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

How to use the barcode detection API?

You can’t just pass the data pointer directly to DBR_DecodeBuffer(). The data needs to be reconstructed with some extra information:

    char *total = (char *)malloc(size + 40); // buffer size = image size + header size
    memset(total, 0, size + 40);
    BITMAPINFOHEADER bitmap_info = {40, width, height, 0, 24, 0, size, 0, 0, 0, 0};
    memcpy(total, &bitmap_info, 40);

    // Copy image data to buffer from bottom to top
    char *data = total + 40;
    int stride = pai->strides[0];
    for (int i = 1; i <= height; i++) {
        memcpy(data, buffer + stride * (height - i), stride);
        data += stride;
    }

Read barcode from images and return results:

// Dynamsoft Barcode Reader initialization
    __int64 llFormat = (OneD | QR_CODE | PDF417 | DATAMATRIX);
    int iMaxCount = 0x7FFFFFFF;
    ReaderOptions ro = {0};
    pBarcodeResultArray pResults = NULL;
    ro.llBarcodeFormat = llFormat;
    ro.iMaxBarcodesNumPerPage = iMaxCount;
    printf("width: %d, height: %d, size:%d\n", width, height, size);
    int iRet = DBR_DecodeBuffer((unsigned char *)total, size + 40, &ro, &pResults);
    printf("DBR_DecodeBuffer ret: %d\n", iRet);
    free(total); // Do not forget to release the constructed buffer 
    
    // Get results
    int count = pResults->iBarcodeCount;
    pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
    pBarcodeResult tmp = NULL;
    retval = PyList_New(count); // The returned Python object
    PyObject* result = NULL;
    for (int i = 0; i < count; i++)
    {
        tmp = ppBarcodes[i];
        result = PyString_FromString(tmp->pBarcodeData);
        printf("result: %s\n", tmp->pBarcodeData);
        PyList_SetItem(retval, i, Py_BuildValue("iN", (int)tmp->llFormat, result)); // Add results to list
    }
    // release memory
    DBR_FreeBarcodeResults(&pResults);

What if you see the error ‘Unable to find vcvarsall.bat’ when building Python extension on Windows?

According to the answer from StackOverflow, execute the following command based on the version of Visual Studio installed:

  • 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%

I’m using Visual Studio 2015, and thus I can build Python extension as follows:

SET VS90COMNTOOLS=%VS140COMNTOOLS%
python setup.py build install

Python Script for Testing

Open camera:

import cv2
from dbr import *
import time

vc = cv2.VideoCapture(0)

Read and render camera video stream:

cv2.imshow(windowName, frame)
rval, frame = vc.read();

Detect barcode from frame and show results in console:

initLicense("<license>") # Invalid license is fine.
results = decodeBuffer(frame)
if (len(results) > 0):
    print "Total count: " + str(len(results))
    for result in results:
        print "Type: " + types[result[0]]
        print "Value: " + result[1] + "\n"

Source Code

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

 

The post How to Convert OpenCV Image Data from Python to C appeared first on Code Pool.

Streaming Webcam Video with Dynamic .NET TWAIN

$
0
0

C# is the preferred programming language for developing Windows applications. However, Microsoft only provides .NET camera APIs for UWP applications. If you plan to write a classic Windows desktop application using a webcam, it will be complicated to create a C/C++ wrapper for DirectShow Win32 APIs. Dynamic .NET TWAIN is an SDK that supports programming for both scanner and webcam. In this article, you will see how easy to build a webcam application with the SDK. In addition, you can learn how to detect and recognize barcodes from the video stream with Dynamsoft Barcode Reader SDK.

This article has been published on CodeProject.

dotnet webcam barcode reader

Using Webcam and Barcode APIs

Webcam Video Viewer

Open Visual Studio to Create a Windows Forms Application.

Install Dynamic .NET TWAIN and Dynamsoft Barcode Reader via NuGet Package Manager:

install sdk via nuget

Initialize DotNet TWAIN object:

private Dynamsoft.DotNet.TWAIN.DynamicDotNetTwain dynamicDotNetTwain = new Dynamsoft.DotNet.TWAIN.DynamicDotNetTwain();
dynamicDotNetTwain.LicenseKeys = "*******";
dynamicDotNetTwain = "dynamicDotNetTwain";
dynamicDotNetTwain.Visible = true;dynamicDotNetTwain.OnFrameCapture += new Dynamsoft.DotNet.TWAIN.Delegate.OnFrameCaptureHandler(this.dynamicDotNetTwain_OnFrameCapture);

The OnFrameCaptureHandler event will be triggered when captured video frames are ready. If you want to do something for the video stream, such as processing image and reading barcode, you can put your code into the function dynamicDotNetTwain_OnFrameCapture.

Use a PictureBox to show the video stream:

dynamicDotNetTwain.SupportedDeviceType = EnumSupportedDeviceType.SDT_WEBCAM;

SetWebCamAsDntSrc(cbxWebCamSrc.Text);

dynamicDotNetTwain.SetVideoContainer(picBoxWebCam);

dynamicDotNetTwain.OpenSource();

dynamicDotNetTwain.IfShowUI = true;

ResizeVideoWindow(0);

picBoxWebCam.Visible = true;

picBoxWebCam.BringToFront();

panelResult.BringToFront();

So far, a simple webcam viewer is done. Let’s take a further step to process the frames.

Barcode Reader

Initialize the barcode reader object:

private readonly BarcodeReader _br = new BarcodeReader { LicenseKeys = "<Put your license key here>" };
Create an event handler for rendering UI:
private delegate void PostShowFrameResultsHandler(Bitmap _bitmap, BarcodeResult[] _bars);
private PostShowFrameResultsHandler _postShowFrameResults = new PostShowFrameResultsHandler(this.postShowFrameResults);
private void postShowFrameResults(Bitmap _bitmap, BarcodeResult[] _bars)
        {
            this.TurnOnWebcam(false);

            if (_bars == null)
                panelResult.Visible = false;
            else
            {
                picBoxWebCam.Image = null;
                rtbBarcodeResult.Text = "Total barcodes: " + _bars.Length + "\n";
               var tempBitmap = new Bitmap(_bitmap.Width, _bitmap.Height);
                using (var g = Graphics.FromImage(tempBitmap))
                {
                    g.DrawImage(_bitmap, 0, 0);
                    foreach (BarcodeResult result in _bars)
                    {
                        g.DrawRectangle(new Pen(Color.FromArgb(255, 0, 0), 2), result.BoundingRect);
                        rtbBarcodeResult.Text += "Barcode Format: " + result.BarcodeFormat + "\n";
                        rtbBarcodeResult.Text += "Barcode Value: " + result.BarcodeText + "\n";
                    }
                }
                picBoxWebCam.Image = tempBitmap;
                panelResult.Location = picBoxWebCam.Location;
                panelResult.Height = 100;
                panelResult.Visible = true;
            }
        }

Get the video frames from the callback function:

        private Bitmap _tmpBitmap = null;
        private void dynamicDotNetTwain_OnFrameCapture(Dynamsoft.DotNet.TWAIN.Interface.OnFrameCaptureEventArgs arg)
        {
            if (_bTurnOnWebcam)
            {
                lock (this)
                {
                    Rectangle rect = new Rectangle(0, 0, arg.Frame.Width, arg.Frame.Height);
                    if (_tmpBitmap == null)
                    {
                        _tmpBitmap = new Bitmap(rect.Width, rect.Height);
                    }
                    CopyTo(arg.Frame, _tmpBitmap, rect);
                }
            }
        }

A function for copying bitmap in C#:

static public void CopyTo(Bitmap srcBitmap, Bitmap Dest, Rectangle section)
        {
            Graphics g = Graphics.FromImage(Dest);
            // Draw the specified section of the source bitmap to the new one
            g.DrawImage(srcBitmap, 0, 0, section, GraphicsUnit.Pixel);
            // Clean up
            g.Dispose();
        }

In case of blocking UI thread, create a worker thread to invoke barcode detection API:

private volatile bool _isThreadRunning = true;
private Thread _dbrThread = new Thread(new ThreadStart(run));
_dbrThread.Start();

public void run()
        {
            while (_tmpBitmap == null)
            {
                Thread.Sleep(30);
                continue;
            }

            Bitmap bitmap = null;
            Rectangle rect = new Rectangle(0, 0, _tmpBitmap.Width, _tmpBitmap.Height);
            while (_isThreadRunning)
            {
                lock (this)
                {
                    if (bitmap == null)
                    {
                        bitmap = new Bitmap(rect.Width, rect.Height);
                    }
                    CopyTo(_tmpBitmap, bitmap, rect);
                }
                ReadFromFrame(bitmap);
            }
        }

Read barcodes and draw returned results:

        private void ReadFromFrame(Bitmap bitmap)
        {
            BarcodeResult[] bars = null;
            try
            {
                bars = _br.DecodeBitmap(bitmap);
                if (bars == null || bars.Length <= 0)
                {
                    return;
                }
                this.BeginInvoke(_postShowFrameResults, new object[] { bitmap, bars });
            }
            catch (Exception ex)
            {
                this.BeginInvoke(_postShowFrameResults, new object[] { bitmap, bars });
                MessageBox.Show(ex.Message);
            }
        }

Connect a USB webcam to your PC.

Build and run the application.

Source Code

https://github.com/dynamsoft-dnt/DotNet-Webcam-Video-Streaming

 

The post Streaming Webcam Video with Dynamic .NET TWAIN appeared first on Code Pool.

Raspberry Pi Barcode Scanner in Python

$
0
0

Previously, I wrote an article Raspberry Pi Barcode Scanner with Webcam and Python illustrating how to build a simple barcode scanner using Dynamsoft Barcode Reader SDK and OpenCV from scratch. The method decodeFile() was used for detecting barcodes from an image file. To use the API, you have to firstly write image buffer that obtained by OpenCV API to a file. Because the I/O operation takes too much time, this API is not good for real-time barcode detection from webcam video stream. Considering this scenario, I have added a new Python API decodeBuffer(). In this article, I will illustrate how to create and use the new API.

Raspberry Pi Barcode Scanner in Python

Testing Environment

  • Device: Raspberry Pi 3
  • Operating System: RASPBIAN JESSIE WITH PIXEL

Prerequisites

  • Dynamsoft Barcode Reader for Raspberry Pi
  • Python 2.7.0
  • OpenCV 3.0.0
  • Raspberry Pi 2 or 3
  • USB webcam

Building and Installation

How to Build OpenCV on Raspberry Pi

  1. Download and extract the source code.
  2. Install dependencies:
    sudo apt-get install cmake
    sudo apt-get install libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
    sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
    sudo apt-get install libxvidcore-dev libx264-dev
    sudo apt-get install python-dev
  3. Setting up the build:
    cd ~/opencv-3.0.0/
    mkdir build
    cd build
    cmake -D CMAKE_BUILD_TYPE=RELEASE \
                    -D CMAKE_INSTALL_PREFIX=/usr/local \
                    -D INSTALL_C_EXAMPLES=ON \
                    -D INSTALL_PYTHON_EXAMPLES=ON \
                    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.0.0/modules \
                    -D BUILD_EXAMPLES=ON ..
  4. Compile and install OpenCV:
    make -j4
    sudo make install

The shared library will be installed at /usr/local/lib/python2.7/dist-packages/cv2.so.

How to build the Python extension with Dynamsoft Barcode Reader SDK

  1. Download and extract the SDK package.
  2. Create a symbolic link for libDynamsoftBarcodeReader.so:
    sudo ln –s <Your dbr path>/lib/libDynamsoftBarcodeReader.so /usr/lib/libDynamsoftBarcodeReader.so
  3. Open setup.py and modify the paths of include and lib files:
    include_dirs=["/usr/lib/python2.7/dist-packages/numpy/core/include/numpy", "<Your dbr path>/include"],
    library_dirs=['<Your dbr path>/lib'],
  4. Build the extension:
    sudo python setup.py build install

How to implement the decodeBuffer method?

Because the source code is transplanted from Windows edition, we have to define following types and structure:

typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned short WORD;

typedef struct tagBITMAPINFOHEADER {
  DWORD biSize;
  LONG biWidth;
  LONG biHeight;
  WORD biPlanes;
  WORD biBitCount;
  DWORD biCompression;
  DWORD biSizeImage;
  LONG biXPelsPerMeter;
  LONG biYPelsPerMeter;
  DWORD biClrUsed;
  DWORD biClrImportant;
} BITMAPINFOHEADER;

Convert the numpy data from Python to C in decodeBuffer(). Besides that, we have to construct a native buffer for barcode reading:

#include <ndarraytypes.h>

static PyObject *
decodeBuffer(PyObject *self, PyObject *args)
{
    PyObject *o;
    if (!PyArg_ParseTuple(args, "O", &o))
        return NULL;

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

    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;
    }

    // Construct data with header info and image data 
    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
    char *total = (char *)malloc(size + 40); // buffer size = image size + header size
    memset(total, 0, size + 40);
    BITMAPINFOHEADER bitmap_info = {40, width, height, 0, 24, 0, size, 0, 0, 0, 0};
    memcpy(total, &bitmap_info, 40);

    // Copy image data to buffer from bottom to top
    char *data = total + 40;
    int stride = pai->strides[0];
    int i = 1;
    for (; i <= height; i++) {
        memcpy(data, buffer + stride * (height - i), stride);
        data += stride;
    }

    // Dynamsoft Barcode Reader initialization
    __int64 llFormat = (OneD | QR_CODE | PDF417 | DATAMATRIX);
    int iMaxCount = 0x7FFFFFFF;
    ReaderOptions ro = {0};
    pBarcodeResultArray pResults = NULL;
    ro.llBarcodeFormat = llFormat;
    ro.iMaxBarcodesNumPerPage = iMaxCount;
    printf("width: %d, height: %d, size:%d\n", width, height, size);
    int iRet = DBR_DecodeBuffer((unsigned char *)total, size + 40, &ro, &pResults);
    printf("DBR_DecodeBuffer ret: %d\n", iRet);
    free(total); // Do not forget to release the constructed buffer 
    
    // Get results
    int count = pResults->iBarcodeCount;
    pBarcodeResult* ppBarcodes = pResults->ppBarcodes;
    pBarcodeResult tmp = NULL;
    retval = PyList_New(count); // The returned Python object
    PyObject* result = NULL;
    i = 0;
    for (; i < count; i++)
    {
        tmp = ppBarcodes[i];
        result = PyString_FromString(tmp->pBarcodeData);
        printf("result: %s\n", tmp->pBarcodeData);
        PyList_SetItem(retval, i, Py_BuildValue("iN", (int)tmp->llFormat, result)); // Add results to list
    }
    // release memory
    DBR_FreeBarcodeResults(&pResults);

    Py_DECREF(ao);
    return retval;
}

Raspberry Pi Barcode Scanner

How to set video frame rate, frame width, and frame height?

You can refer to the Property identifier:

  • CV_CAP_PROP_FRAME_WIDTH: Width of the frames in the video stream.
  • CV_CAP_PROP_FRAME_HEIGHT: Height of the frames in the video stream.
  • CV_CAP_PROP_FPS: Frame rate.

If failed to use the property identifier, set the value directly as follows:

vc = cv2.VideoCapture(0)
vc.set(5, 30)  #set FPS
vc.set(3, 320) #set width
vc.set(4, 240) #set height

How to use the API decodeBuffer()?

while True:
        cv2.imshow(windowName, frame)
        rval, frame = vc.read();
        results = decodeBuffer(frame)
        if (len(results) > 0):
            print "Total count: " + str(len(results))
            for result in results:
                print "Type: " + types[result[0]]
                print "Value: " + result[1] + "\n"

        # 'ESC' for quit
        key = cv2.waitKey(20)
        if key == 27:
            break

How to run the Raspberry Pi Barcode Scanner?

  1. Connect a USB webcam to Raspberry Pi 2 or 3.
  2. Run app.py:
    python app.py

Source Code

https://github.com/yushulx/opencv-python-webcam-barcode-reader/tree/master/raspberrypi

 

The post Raspberry Pi Barcode Scanner in Python appeared first on Code Pool.

How to Use Xamarin to Bind a Fat iOS Framework on Windows

$
0
0

When developing an Android project with Xamarin, I didn’t get any trouble. However, it is totally a different experience when building an iOS app with Xamarin – it is more complicated. In this article, I will share my experience of binding DynamsoftBarcodeReader.framework using Xamarin.

Binding an iOS Framework with Xamarin

Download

DynamsoftBarcodeReader.framework is an SDK used for barcode detection.

Link the dependencies with Linkwith.cs File

Create an iOS bindings library project in Visual Studio 2015:

xamarin ios binding

Rename DynamsoftBarcodeReader.framework\DynamsoftBarcodeReader to DynamsoftBarcodeReader.framework\DynamsoftBarcodeReader.a, and then drag the static library to the project. The IDE will automatically generate a corresponding DynamsoftBarcodeReader.linkwith.cs file:

xamarin bind ios dbr

DynamsoftBarcodeReader.framework relies on libc++.1.dylib. Referring to ObjCRuntime.LinkWithAttribute Class, the DynamsoftBarcodeReader.linkwith.cs is written as follows:

using System;
using ObjCRuntime;

[assembly: LinkWith ("DynamsoftBarcodeReader.a", LinkTarget.ArmV7 | LinkTarget.Simulator, ForceLoad = true, LinkerFlags = "-lc++.1")]

Generate ApiDefinition.cs with Objective Sharpie

The ApiDefinition.cs is where you will define the API contract, this is the file that describes how the underlying Objective-C API is projected into C#. You can manually define all APIs for your library or automatically generate definitions with Objective Sharpie, which only runs on macOS.

Here is the command to generate ApiDeifinition.cs for DynamsoftBarcodeReader.framework:

sharpie -tlm-do-not-submit bind -framework ~/Desktop/DynamsoftBarcodeReader.framework -sdk iphoneos10.2

xmarin objective sharpie

You have to modify the generated file because Objective Sharpie uses [Verify] attributes to annotate APIs. After confirming the APIs, you can delete the lines of [verify]. Here is mine:

using System;
using CoreGraphics;
using Foundation;
using ObjCRuntime;
using UIKit;

namespace DBRiOS {
	
	[Static]
	partial interface Constants
	{
		// extern double DynamsoftBarcodeReaderVersionNumber;
		[Field ("DynamsoftBarcodeReaderVersionNumber", "__Internal")]
		double DynamsoftBarcodeReaderVersionNumber { get; }

		// extern const unsigned char [] DynamsoftBarcodeReaderVersionString;
		[Field ("DynamsoftBarcodeReaderVersionString", "__Internal")]
		NSString DynamsoftBarcodeReaderVersionString { get; }
	}

	// @interface Barcode : NSObject
	[BaseType (typeof(NSObject))]
	interface Barcode
	{
		// @property (nonatomic) long format;
		[Export ("format")]
		nint Format { get; set; }

		// @property (copy, nonatomic) NSString * formatString;
		[Export ("formatString")]
		string FormatString { get; set; }

		// @property (copy, nonatomic) NSString * displayValue;
		[Export ("displayValue")]
		string DisplayValue { get; set; }

		// @property (copy, nonatomic) NSData * rawValue;
		[Export ("rawValue", ArgumentSemantic.Copy)]
		NSData RawValue { get; set; }

		// @property (copy, nonatomic) NSArray * cornerPoints;
		[Export ("cornerPoints", ArgumentSemantic.Copy)]
		NSObject[] CornerPoints { get; set; }

		// @property (nonatomic) CGRect boundingbox;
		[Export ("boundingbox", ArgumentSemantic.Assign)]
		CGRect Boundingbox { get; set; }

		// +(long)OneD;
		[Static]
		[Export ("OneD")]
		nint OneD { get; }

		// +(long)CODE_39;
		[Static]
		[Export ("CODE_39")]
		nint CODE_39 { get; }

		// +(long)CODE_128;
		[Static]
		[Export ("CODE_128")]
		nint CODE_128 { get; }

		// +(long)CODE_93;
		[Static]
		[Export ("CODE_93")]
		nint CODE_93 { get; }

		// +(long)CODABAR;
		[Static]
		[Export ("CODABAR")]
		nint CODABAR { get; }

		// +(long)ITF;
		[Static]
		[Export ("ITF")]
		nint ITF { get; }

		// +(long)EAN_13;
		[Static]
		[Export ("EAN_13")]
		nint EAN_13 { get; }

		// +(long)EAN_8;
		[Static]
		[Export ("EAN_8")]
		nint EAN_8 { get; }

		// +(long)UPC_A;
		[Static]
		[Export ("UPC_A")]
		nint UPC_A { get; }

		// +(long)UPC_E;
		[Static]
		[Export ("UPC_E")]
		nint UPC_E { get; }

		// +(long)INDUSTRIAL_25;
		[Static]
		[Export ("INDUSTRIAL_25")]
		nint INDUSTRIAL_25 { get; }

		// +(long)PDF417;
		[Static]
		[Export ("PDF417")]
		nint PDF417 { get; }

		// +(long)DATAMATRIX;
		[Static]
		[Export ("DATAMATRIX")]
		nint DATAMATRIX { get; }

		// +(long)QR_CODE;
		[Static]
		[Export ("QR_CODE")]
		nint QR_CODE { get; }

		// +(long)UNKNOWN;
		[Static]
		[Export ("UNKNOWN")]
		nint UNKNOWN { get; }
	}

	// @interface ReadResult : NSObject
	[BaseType (typeof(NSObject))]
	interface ReadResult
	{
		// @property (nonatomic) int errorCode;
		[Export ("errorCode")]
		int ErrorCode { get; set; }

		// @property (copy, nonatomic) NSString * errorString;
		[Export ("errorString")]
		string ErrorString { get; set; }

		// @property (nonatomic) NSArray * barcodes;
		[Export ("barcodes", ArgumentSemantic.Assign)]
		Barcode[] Barcodes { get; set; }
	}

	// @interface BarcodeReader : NSObject
	[BaseType (typeof(NSObject))]
	interface BarcodeReader
	{
		// +(int)DBRERROR_OK;
		[Static]
		[Export ("DBRERROR_OK")]
		int DBRERROR_OK { get; }

		// +(int)DBRERROR_UNKNOWN;
		[Static]
		[Export ("DBRERROR_UNKNOWN")]
		int DBRERROR_UNKNOWN { get; }

		// +(int)DBRERROR_NOMEMORY;
		[Static]
		[Export ("DBRERROR_NOMEMORY")]
		int DBRERROR_NOMEMORY { get; }

		// +(int)DBRERROR_NULL_POINTER;
		[Static]
		[Export ("DBRERROR_NULL_POINTER")]
		int DBRERROR_NULL_POINTER { get; }

		// +(int)DBRERROR_LICENSE_INVALID;
		[Static]
		[Export ("DBRERROR_LICENSE_INVALID")]
		int DBRERROR_LICENSE_INVALID { get; }

		// +(int)DBRERROR_LICENSE_EXPIRED;
		[Static]
		[Export ("DBRERROR_LICENSE_EXPIRED")]
		int DBRERROR_LICENSE_EXPIRED { get; }

		// +(int)DBRERROR_BARCODE_FORMAT_INVALID;
		[Static]
		[Export ("DBRERROR_BARCODE_FORMAT_INVALID")]
		int DBRERROR_BARCODE_FORMAT_INVALID { get; }

		// +(int)DBRERROR_PARAMETER_INVALID;
		[Static]
		[Export ("DBRERROR_PARAMETER_INVALID")]
		int DBRERROR_PARAMETER_INVALID { get; }

		// -(id)initWithLicense:(NSString *)license;
		[Export ("initWithLicense:")]
		IntPtr Constructor (string license);

		// -(ReadResult *)readSingle:(UIImage *)image barcodeFormat:(long)format;
		[Export ("readSingle:barcodeFormat:")]
		ReadResult ReadSingle (UIImage image, nint format);

		// -(void)readSingleAsync:(UIImage *)image barcodeFormat:(long)format sender:(id)sender onComplete:(SEL)callback;
		[Export ("readSingleAsync:barcodeFormat:sender:onComplete:")]
		void ReadSingleAsync (UIImage image, nint format, NSObject sender, Selector callback);

		// -(ReadResult *)readSingle:(NSData *)buffer width:(int)width height:(int)height barcodeFormat:(long)format;
		[Export ("readSingle:width:height:barcodeFormat:")]
		ReadResult ReadSingle (NSData buffer, int width, int height, nint format);

		// -(void)readSingleAsync:(NSData *)buffer width:(int)width height:(int)height barcodeFormat:(long)format sender:(id)sender onComplete:(SEL)callback;
		[Export ("readSingleAsync:width:height:barcodeFormat:sender:onComplete:")]
		void ReadSingleAsync (NSData buffer, int width, int height, nint format, NSObject sender, Selector callback);
	}
}

Now you can build DBRiOS.dll.

Building a Simple iOS Barcode Reader App

Create an iOS Single View App in Visual Studio 2015 and add DBRiOS.dll to References.

Add Button, Lable and UIImageView to Main.storyboard.

xamarin storyboard

Open ViewController.cs to add the following code:

using System;

using UIKit;
using DBRiOS;

namespace BarcodeDemo
{
    public partial class ViewController : UIViewController
    {
        public ViewController(IntPtr handle) : base(handle)
        {
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            // Perform any additional setup after loading the view, typically from a nib.
        }

        public override void DidReceiveMemoryWarning()
        {
            base.DidReceiveMemoryWarning();
            // Release any cached data, images, etc that aren't in use.
        }

        partial void Button_read_TouchUpInside(UIButton sender)
        {
            BarcodeReader barcodeReader = new BarcodeReader("");
            ReadResult result = barcodeReader.ReadSingle(qrimage.Image, Barcode.QR_CODE);
            Barcode barcode = result.Barcodes[0];
            text.Text = barcode.DisplayValue;
        }

        partial void UIButton16_TouchUpInside(UIButton sender)
        {
            text.Text = "";
        }
    }
}

Build and run the iOS barcode reader on your device or simulator.

xamarin ios barcode reader

Troubleshooting

Failed to Connect Xamarin Mac Agent

xamarin failed to connect mac agent

If you suffered from the above error, check whether you have installed all required software on macOS. You can use Xamarin Installer to download xamarin.ios, xamarin.mac, Xamarin Studio, and MonoFramework. You have to ensure that matching Xamarin.iOS versions are installed on your macOS and Windows.

Couldn’t resolve address

xamarin ios connection failed

This issue is weird. Sometimes, it will succeed after rebuilding the project. Sometimes it doesn’t work at all no matter how many times you rebuild the project. If so, you probably have to re-launch Visual Studio to solve the issue.

For more information, you can read the article Connecting to Mac.

Add Native Framework Reference

Have you ever tried to add native framework reference directly? I built the same project with Windows Visual Studio and Mac Visual Studio, the result was different. Only the DBRiOS.dll built from Mac Visual Studio could work.

xamarin ios native reference windows

xamarin ios bindings library macOS

However, this way does not work perfectly. There is no ‘LinkTarget’ property. DynamsoftBarcodeReader.framework is a fat framework supporting armv7, i386, x86_64, and arm64.

xamarin ios fat framework

When building the bindings library with the framework, not all architecture slices were linked. I found the size of the generated DBRiOS.dll is much smaller than the original framework. And I can only build iOS app for the device, not the simulator.

Source Code

https://github.com/yushulx/xamarin-bind-ios-framework

 

The post How to Use Xamarin to Bind a Fat iOS Framework on Windows appeared first on Code Pool.


How to Use Dart with Barcode RESTful Web Service

$
0
0

A few months ago, Google announced a new operating system named Fuchsia. It was my first time to hear about Dart, which is the primary programming language for Fuchsia. Dart is a programming language designed by Google.  It is used to build the web (Dart webdev), mobile (Flutter) and server (Dart VM) applications. In this article, I will share how to write my first Dart console application with Dynamsoft barcode RESTful web service.

Setting Up the Dart Development Environment

Install Dart SDK, which includes Dart VM, libraries, package manager and more.

Install IDE IntelliJ IDEA. The community edition is free. When launching the IDE first time, click menu File > Settings > Plugins to install Dart plugin.

IntelliJ Dart Plugin

Dart Console Application with Barcode RESTful Web Service

Create a new console application project:

Dart Console Application Project

Using libraries

Here are the required libraries:

import 'dart:io';
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;

The dart: scheme is for built-in libraries, and the package: scheme is for external libraries provided by a package manager such as the pub tool.

You may see a prompt message “Target of URI doesn’t exist”. To use the external libraries, open pubspec.yaml and add dependencies:

name: barcode
version: 0.0.1
description: A simple console application.
dependencies:
  http:

Then click Get Dependencies to download the libraries.

Read a file and convert bytes to base64

Reading file as bytes is pretty easy:

var bytes = await new File(filename).readAsBytes();

If you have read the Dart tutorial, you may have noticed the code for base64 conversion:

import 'package:crypto/crypto.dart';
String base64 = CryptoUtils.bytesToBase64(bytes);

However, after getting the latest crypto package, I got the error “Undefined name ‘CryptoUtils’”.

I searched Dart APIs for “base64”, and found the following substitute:

import 'dart:convert';
String base64 = BASE64.encode(bytes);

Send JSON to RESTful web service

Construct the JSON data:

String jsonData = '{"image":"$base64","barcodeFormat":234882047,"maxNumPerPage":1}';

The value of barcode format represents all barcode types including Code 39, Code 93, Code 128, Codabar, Interleaved 2 of 5, EAN-8, EAN-13, UPC-A, UPC-E, Industrial 2 of 5, QR code, Datamatrix, and PDF417. I got this value from Dynamsoft barcode web service sample.

Send HTTP request and wait for the responded result:

var response = await http.post(url, headers: {'Content-Type': 'application/json'}, body: jsonData);
print("Response status: ${response.statusCode}");
print(response.headers);
if (response.statusCode != 200) {
  print("Server Error !!!");
  return;
}
print("Response body: ${response.body}");

// https://api.dartlang.org/stable/1.21.0/dart-convert/JSON-constant.html
Map result = JSON.decode(response.body);
print("Barcode result: " + result['barcodes'][0]['displayValue']);

Screenshot

Run the Dart console application with the test barcode image:

Dart barcode RESTful web service

Source Code

https://github.com/yushulx/dartlang-barcode-webservice

The post How to Use Dart with Barcode RESTful Web Service appeared first on Code Pool.

Building Dart Native Extension with Dynamsoft Barcode SDK on Windows

$
0
0

I just finished reading the article – Native Extensions for the Standalone Dart VM. In this post, I will share my experience about how to build a Dart native extension from scratch with Dynamsoft C/C++ barcode SDK on Windows.

Why Asynchronous Extension

Dart is a single-threaded programming language, similar to JavaScript. Any code with time-consuming operations will block the main Dart thread, freezing the program. The asynchronous extension runs a native function on a separate thread, scheduled by the Dart VM. Invoking third-party barcode APIs in asynchronous extension is recommended.

Building Dart Native Extension using Visual Studio 2015

Install Dart SDK and Dynamsoft Barcode Reader. Learn the sample code of native extension that included in Dart SDK repository.

A Dart native extension contains a *.dart file and a *.dll file on Windows. The *.dart file defines a class that provides functions to forward arguments to the native port. A reply port is used to receive the message back from C function. Create sample_asynchronous_extension.dart:

library sample_asynchronous_extension;

import 'dart:async';
import 'dart:isolate';
import 'dart-ext:sample_extension';

class BarcodeReader {
  static SendPort _port;

  Future<List> readBarcode(String filename) {
    var completer = new Completer();
    var replyPort = new RawReceivePort();
    var args = new List(2);
    args[0] = filename;
    args[1] = replyPort.sendPort;
    _servicePort.send(args);
    replyPort.handler = (result) {
      replyPort.close();
      if (result != null) {
        completer.complete(result);
      } else {
        completer.completeError(new Exception("Reading barcode failed"));
      }
    };
    return completer.future;
  }

  SendPort get _servicePort {
    if (_port == null) {
      _port = _newServicePort();
    }
    return _port;
  }

  SendPort _newServicePort() native "BarcodeReader_ServicePort";
}

Launch Visual Studio 2015 to create an empty Win32 project. Set DLL as the Application type and check the option Empty project. Add the paths of include and lib files:Dart include header

Dart lib path

Add dependencies dart.lib and DBRx64.lib:

Dart dependency

Add preprocessor DART_SHARED_LIB:

Dart preprocessor

Include relevant header files:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "include/dart_api.h"
#include "include/dart_native_api.h"

#include "If_DBRP.h"

Use  sample_extension_Init() and ResolveName() to initialize the native extension:

DART_EXPORT Dart_Handle sample_extension_Init(Dart_Handle parent_library) {
  if (Dart_IsError(parent_library)) {
    return parent_library;
  }

  Dart_Handle result_code =
      Dart_SetNativeResolver(parent_library, ResolveName, NULL);
  if (Dart_IsError(result_code)) {
    return result_code;
  }

  return Dart_Null();
}

struct FunctionLookup {
  const char* name;
  Dart_NativeFunction function;
};


FunctionLookup function_list[] = {
	{"BarcodeReader_ServicePort", barcodeReaderServicePort},
    {NULL, NULL}};

Dart_NativeFunction ResolveName(Dart_Handle name,
                                int argc,
                                bool* auto_setup_scope) {
  if (!Dart_IsString(name)) {
    return NULL;
  }
  Dart_NativeFunction result = NULL;
  if (auto_setup_scope == NULL) {
    return NULL;
  }

  Dart_EnterScope();
  const char* cname;
  HandleError(Dart_StringToCString(name, &cname));

  for (int i=0; function_list[i].name != NULL; ++i) {
    if (strcmp(function_list[i].name, cname) == 0) {
      *auto_setup_scope = true;
      result = function_list[i].function;
      break;
    }
  }

  if (result != NULL) {
    Dart_ExitScope();
    return result;
  }

  Dart_ExitScope();
  return result;
}

Read barcode with Dynamsoft C/C++ barcode APIs:

char **readBarcode(char *pszFileName, int *out_len) {
	char **values = NULL;

	__int64 llFormat = (OneD | QR_CODE | PDF417 | DATAMATRIX);

	char pszBuffer[512] = { 0 };
	int iMaxCount = MAX_BARCODE_AMOUNT;
	int iIndex = 0;
	ReaderOptions ro = { 0 };
	int iRet = -1;
	char * pszTemp = NULL;
	unsigned __int64 ullTimeBegin = 0;
	unsigned __int64 ullTimeEnd = 0;
	size_t iLen = 0;
	FILE* fp = NULL;
	int iExitFlag = 0;

	// Set license
	CBarcodeReader reader;
	reader.InitLicense("38B9B94D8B0E2B41FDE1FB60861C28C0");

	// Read barcode
	ullTimeBegin = GetTickCount();
	ro.llBarcodeFormat = llFormat;
	ro.iMaxBarcodesNumPerPage = iMaxCount;
	reader.SetReaderOptions(ro);
	iRet = reader.DecodeFile(pszFileName);
	ullTimeEnd = GetTickCount();

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

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

	if (paryResult->iBarcodeCount == 0)
	{
		sprintf_s(pszTemp, 4096, "No barcode found. Total time spent: %.3f seconds.\r\n", ((float)(ullTimeEnd - ullTimeBegin) / 1000));
		printf(pszTemp);
		free(pszTemp);
		reader.FreeBarcodeResults(&paryResult);
		return NULL;
	}

	sprintf_s(pszTemp, 4096, "Total barcode(s) found: %d. Total time spent: %.3f seconds\r\n\r\n", paryResult->iBarcodeCount, ((float)(ullTimeEnd - ullTimeBegin) / 1000));
	//printf(pszTemp);

	values = (char **)malloc((paryResult->iBarcodeCount + 1) * sizeof(char *));

	for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
	{
		char* pszValue = (char*)calloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1, sizeof(char));
		memcpy(pszValue, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
		values[iIndex] = pszValue;
	}

	free(pszTemp);
	reader.FreeBarcodeResults(&paryResult);
	values[iIndex] = NULL;
	*out_len = iIndex;

	return values;
}

Wrap the results into a Dart_CObjects:

void wrappedBarcodeReader(Dart_Port dest_port_id,
	Dart_CObject* message) {
	Dart_Port reply_port_id = ILLEGAL_PORT;
	if (message->type == Dart_CObject_kArray &&
		2 == message->value.as_array.length) {
		// Use .as_array and .as_int32 to access the data in the Dart_CObject.
		Dart_CObject* param0 = message->value.as_array.values[0];
		Dart_CObject* param1 = message->value.as_array.values[1];

		if (param0->type == Dart_CObject_kString &&
			param1->type == Dart_CObject_kSendPort) {
			char * pszFileName = param0->value.as_string;
			reply_port_id = param1->value.as_send_port.id;

			int length = 0;
			char **values = readBarcode(pszFileName, &length);
			char **pStart = values;
			if (values != NULL) {
				Dart_CObject* results[MAX_BARCODE_AMOUNT];
				Dart_CObject collection[MAX_BARCODE_AMOUNT];
				int index = 0;
				char * pszValue = NULL;
				while ((pszValue = *pStart) != NULL) {
					Dart_CObject value;
					value.type = Dart_CObject_kString;
					value.value.as_string = pszValue;
					collection[index] = value;

					++pStart;
					++index;
				}

				for (int i = 0; i < length; i++) {
					results[i] = &(collection[i]);
				}

				Dart_CObject message;
				message.type = Dart_CObject_kArray;
				message.value.as_array.length = length;
				message.value.as_array.values = results;
				Dart_PostCObject(reply_port_id, &message);
				freeString(values);

				return;
			}
		}
	}
	Dart_CObject result;
	result.type = Dart_CObject_kNull;
	Dart_PostCObject(reply_port_id, &result);
}

Dart_PostCObject() is the only Dart Embedding API function that should be called from the wrapper or the C function.

Dart_CObjects is defined in dart_native_api.h as follows:

typedef struct _Dart_CObject {
  Dart_CObject_Type type;
  union {
    bool as_bool;
    int32_t as_int32;
    int64_t as_int64;
    double as_double;
    char* as_string;
    struct {
      bool neg;
      intptr_t used;
      struct _Dart_CObject* digits;
    } as_bigint;
    struct {
      Dart_Port id;
      Dart_Port origin_id;
    } as_send_port;
    struct {
      int64_t id;
    } as_capability;
    struct {
      intptr_t length;
      struct _Dart_CObject** values;
    } as_array;
    struct {
      Dart_TypedData_Type type;
      intptr_t length;
      uint8_t* values;
    } as_typed_data;
    struct {
      Dart_TypedData_Type type;
      intptr_t length;
      uint8_t* data;
      void* peer;
      Dart_WeakPersistentHandleFinalizer callback;
    } as_external_typed_data;
  } value;
} Dart_CObject;

Set up the native port:

void barcodeReaderServicePort(Dart_NativeArguments arguments) {
	Dart_EnterScope();
	Dart_SetReturnValue(arguments, Dart_Null());
	Dart_Port service_port =
		Dart_NewNativePort("BarcodeReaderService", wrappedBarcodeReader, true);
	if (service_port != ILLEGAL_PORT) {
		Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port));
		Dart_SetReturnValue(arguments, send_port);
	}
	Dart_ExitScope();
}

Build the project to generate sample_extension.dll. Copy sample_asynchronous_extension.dart, sample_extension.dll and DynamsoftBarcodeReaderx64.dll to the same folder:

Dart native extension

Create barcode_reader.dart to test the Dart native extension:

import 'sample_asynchronous_extension.dart';

void main() {
  BarcodeReader reader = new BarcodeReader();
  reader.readBarcode(r'f:\AllSupportedBarcodeTypes.bmp').then((values) {
    if (values != null) {
      for (var number in values) {
        print(number);
      }
    }
  });
}

Dart console barcode reader

Source Code

https://github.com/yushulx/dart-native-extension

The post Building Dart Native Extension with Dynamsoft Barcode SDK on Windows appeared first on Code Pool.

Cordova Plugin with Android AAR File for Barcode

$
0
0

Cordova is a mobile application development framework that enables developers to build Android, iOS and Windows Phone apps using HTML5, JavaScript, and CSS3. It uses web views to render UI elements instead of the platform’s native UI framework. Cordova can be extended to add more functionalities with plugins. There are many learning resources of Cordova plugin on GitHub. In this article, I want to share how to make a Cordova barcode plugin with a third-party Android library, an AAR file, step by step.

Environment

  • Android Studio 2.2.3
  • Gradle 2.14.1
  • Cordova 6.5.0
  • Dynamsoft Barcode Reader for Android 4.2

Cordova for Android

Initialize a new project:

cordova create simplebarcode com.dynamsoft.simplebarcode SimpleBarcode

Add Android platform:

cd simplebarcode
cordova platform add android --save

Add a button to simplebarcode\platforms\android\assets\www\index.html:

<body>
        <div class="app">
            <div id="deviceready">
                <button id="scan">scan barcode</button>
            </div>
        </div>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>

Build and run the app:

cordova android

Cordova Plugin with Android AAR File

A Cordova plugin for barcode scanning is available on GitHub. The plugin depends on barcodescanner-release-2.1.2.aar that built with ZXing – the open source barcode recognition library. What I want to do is to rebuild the plugin with Dynamsoft Barcode Reader for Android.

Here is the look of Cordova plugin folder:

- src/
  - android/
    - *.java
    - *.aar
    - *.gradle
- www/
    - *.js
- plugin.xml

Open src\android\com\phonegap\plugins\barcodescanner\BarcodeScanner.java. Invoke Activity DBR wrapped in dbr.aar within function scan():

public void scan(final JSONArray args) {

        final CordovaPlugin that = this;

        cordova.getThreadPool().execute(new Runnable() {
            public void run() {

                Intent intentScan = new Intent(that.cordova.getActivity().getBaseContext(), DBR.class);
                intentScan.setAction("com.dynamsoft.dbr");

                // avoid calling other phonegap apps
                intentScan.setPackage(that.cordova.getActivity().getApplicationContext().getPackageName());

                that.cordova.startActivityForResult(that, intentScan, REQUEST_CODE);
            }
        });
    }

The project depends on dbr.aar and DynamsoftBarcodeReader.aar, therefore, add them to barcodescanner.gradle:

dependencies {
    compile 'com.android.support:support-v4:+'
    compile(name:'dbr', ext:'aar')
    compile(name:'DynamsoftBarcodeReader', ext:'aar')
}

Configure Activity, Permission and resource files in plugin.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0" xmlns:android="http://schemas.android.com/apk/res/android" id="phonegap-plugin-barcodescanner" version="6.0.5">
  <name>BarcodeScanner</name>
  <description>Use Dynamsoft Barcode Reader plugin to scan different types of barcodes.</description>
  <license>MIT</license>
  <engines>
    <engine name="cordova" version=">=3.0.0"/>
  </engines>
  <js-module src="www/barcodescanner.js" name="BarcodeScanner">
    <clobbers target="cordova.plugins.barcodeScanner"/>
  </js-module>
  <platform name="android">
    <source-file src="src/android/com/phonegap/plugins/barcodescanner/BarcodeScanner.java" target-dir="src/com/phonegap/plugins/barcodescanner"/>
    <config-file target="res/xml/config.xml" parent="/*">
      <feature name="BarcodeScanner">
        <param name="android-package" value="com.phonegap.plugins.barcodescanner.BarcodeScanner"/>
      </feature>
    </config-file>
    <config-file target="AndroidManifest.xml" parent="/manifest/application">
      <activity android:name="com.dynamsoft.demo.dynamsoftbarcodereaderdemo.DBR" android:clearTaskOnLaunch="true" android:configChanges="orientation|keyboardHidden|screenSize" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:windowSoftInputMode="stateAlwaysHidden" android:exported="false" />
    </config-file>
    <config-file target="AndroidManifest.xml" parent="/manifest">
      <uses-permission android:name="android.permission.CAMERA"/>
      <uses-permission android:name="android.permission.FLASHLIGHT"/>
      <uses-feature android:name="android.hardware.camera" android:required="true"/>
    </config-file>
    <framework src="src/android/barcodescanner.gradle" custom="true" type="gradleReference"/>
    <resource-file src="src/android/dbr.aar" target="libs/dbr.aar"/>
    <resource-file src="src/android/DynamsoftBarcodeReader.aar" target="libs/DynamsoftBarcodeReader.aar"/>
    <dependency id="cordova-plugin-compat" version="^1.0.0"/>
  </platform>
</plugin>

Add the plugin to Cordova project:

cordova plugin add <plugin folder>

Add button event to trigger barcode scanning in simplebarcode\platforms\android\assets\www\js\index.js:

onDeviceReady: function() {
        document.getElementById("scan").onclick = function() {
                        cordova.plugins.barcodeScanner.scan(
                                                            function (result) {
                                                            alert("We got a barcode\n" +
                                                                  "Result: " + result.text + "\n" +
                                                                  "Format: " + result.format + "\n" +
                                                                  "Cancelled: " + result.cancelled);
                                                            },
                                                            function (error) {
                                                            alert("Scanning failed: " + error);
                                                            },
                                                            {
                                                            "preferFrontCamera" : false, // iOS and Android
                                                            "showFlipCameraButton" : true, // iOS and Android
                                                            }
                                                            );
                    }
        this.receivedEvent('deviceready');
    },

Build and run the barcode reader app:

cordova plugin android barcode

cordova barcode reader result

Source Code

https://github.com/dynamsoft-dbr/cordova-plugin-android-barcode

 

The post Cordova Plugin with Android AAR File for Barcode appeared first on Code Pool.

HTTP POST Request with Base64 Barcode Image in Golang

$
0
0

Dynamsoft has deployed a REST web service for barcode detection. This post shares how to call the service by sending HTTP POST request using Golang.

golang barcode web service

Barcode Detection in Golang

Environment

  • IDE: JetBrain Gogland.
  • Go 1.7.4.
  • Windows 10.
  • Workspace structure:
    <GOPATH>
        - src
        - bin
        - pkg
    
  • Settings:
    GOROOT=E:\Go
    GOPATH=g:\gowork

Basic Steps to Call Barcode Web Service

  1. Read an image file as bytes.
  2. Convert the bytes to a base64 string.
  3. Encode the base64 string as JSON string.
  4. Send HTTP POST request with JSON.
  5. Get HTTP response.
  6. Decode response body as JSON and get the barcode detection result.

Read File and Encode as Base64

Read an image file as bytes with Package ioutil:

import "io/ioutil"
data, err := ioutil.ReadFile(filename)

Encode bytes as base64 with Package base64. When using goroutine for I/O, you can use a channel to send and receive values:

import "encoding/base64"
channel <- base64.StdEncoding.EncodeToString(data)

Encode and Decode JSON

Store data in a map:

base64data := <-channel
data := make(map[string]interface{})
data["image"] = base64data
data["barcodeFormat"] = 234882047
data["maxNumPerPage"] = 1

Generate the JSON encoding of the map with Package json:

jsonData, err := json.Marshal(data)

Decode JSON to get the barcode result with Token:

result, _ := ioutil.ReadAll(resp.Body)

// decode JSON
const resultKey = "displayValue"
dec := json.NewDecoder(bytes.NewReader(result))
for {
    t, err := dec.Token()
    if err == io.EOF {
        break
    }
    if err != nil {
        log.Fatal(err)
    }
    tmp := fmt.Sprintf("%v", t)
    if tmp == resultKey {
        t, _ := dec.Token()
        tmp := fmt.Sprintf("%v", t)
        fmt.Println("Barcode result: ", tmp)
        break
    }
}

HTTP POST Request

Send HTTP request with Package http:

import "net/http"
url := "http://demo1.dynamsoft.com/dbr/webservice/BarcodeReaderService.svc/Read"
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))

Demo

  1. Get the package:
    go get github.com/dynamsoft-dbr/golang/web-service
  2. Import the package to a Go project:
    import "github.com/dynamsoft-dbr/golang/web-service"
  3. Create main.go:
    package main
    
    import (
        "os"
        "fmt"
        "github.com/dynamsoft-dbr/golang/web-service"
    )
    
    func main()  {
        var filename string
        if len(os.Args) == 1 {
            fmt.Println("Please specify a file.")
            return
        }
        filename = os.Args[1]
    
        _, err := os.Stat(filename)
    
        if err != nil {
            fmt.Println(err)
            fmt.Println("Please specify a vailid file name.")
            return
        }
    
        channel := make(chan string)
        // read file to base64
        go web_service.File2Base64(filename, channel)
        // read barcode with Dynamsoft web service
        web_service.ReadBarcode(channel)
        fmt.Println("Done.")
    }
  4. Build and run the console app:
    go install
    <GOPATH>/bin/main <barcode image file>

    golang barcode result

Source Code

https://github.com/dynamsoft-dbr/golang

The post HTTP POST Request with Base64 Barcode Image in Golang appeared first on Code Pool.

Node.js Barcode Scanner with UVC Camera for Raspberry Pi

$
0
0

Raspberry Pi has been widely used in industrial environments. For instance, you can make a barcode scanner with Raspberry Pi and camera. This article will be useful for developers who want to create Node.js barcode reader applications for IoT devices. I will share how to use Dynamsoft barcode SDK for ARM, build Node.js C++ addon, as well as create a simple barcode application in JavaScript.

Barcode SDK for ARM

Dynamsoft released C++ barcode SDK for ARM on labs page. The SDK can be used on Raspberry Pi and BeagleBone.

Download and unzip dbr-V4.2.0-linux-armv7l.zip.

Create a symlink for libDynamsoftBarcodeReader.so:

sudo ln –s /home/pi/dbr-V4.2.0-linux-armv7l/lib/libDynamsoftBarcodeReader.so /usr/lib/libDynamsoftBarcodeReader.so

Build and run the sample code:

cd ~/dbr-V4.2.0-linux-armv7l/samples/c
make
./BarcodeReaderDemo

C++ Addon for Node.js

To use a C++ SDK with Node.js, you need to create an addon.

Install node-gyp:

npm install -g node-gyp

Create binding.gyp. Add paths of header files and libraries:

{
  "targets": [
    {
      'target_name': "dbr",
      'sources': [ "dbr.cc" ],
      'conditions': [
          ['OS=="linux"', {
            'defines': [
              'LINUX_DBR',
            ],
            'include_dirs': [
                "/home/pi/dbr-V4.2.0-linux-armv7l/include"
            ],
            'libraries': [
                "-lDynamsoftBarcodeReader", "-L/home/pi/dbr-V4.2.0-linux-armv7l/lib"
            ]
          }]
      ]
    }
  ]
}

Create dbr.cc to implement native C++ interfaces.

Build the addon:

node-gyp configure
node-gyp build

Import the addon in JavaScript:

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

Node.js Barcode Reader with Camera

Connect a UVC camera to Raspberry Pi.

Install Node.js module v4l2camera:

npm install v4l2camera

Print the formats that your camera supported:

var v4l2camera = require("v4l2camera");

var cam = new v4l2camera.Camera("/dev/video0");

// list all supported formats
console.log(cam.formats);

Here is mine:

v4l2 camera configuration

The format of camera frame is YUYV:

YUYV

To read barcodes from the frame, we just need to allocate a byte array with all Y values and convert it to DIB buffer:

bool ConvertCameraGrayDataToDIBBuffer(unsigned char* psrc, int size, int width, int height, unsigned char** ppdist, int *psize)
{
	BITMAPINFOHEADER bitmapInfo;
	memset(&bitmapInfo, 0, sizeof(BITMAPINFOHEADER));

	bitmapInfo.biBitCount = 8;
	bitmapInfo.biWidth = width;
	bitmapInfo.biHeight = height;
	bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);

	int iStride = ((width * 8 + 31) >> 5) << 2;
	int iImageSize = iStride * height;
	if (size < iImageSize)
		return false;

	bitmapInfo.biSizeImage = iImageSize;

	*psize = iImageSize + bitmapInfo.biSize + 1024;
	*ppdist = new unsigned char[*psize];

	//1. copy BITMAPINFOHEADER
	memcpy(*ppdist, &bitmapInfo, sizeof(BITMAPINFOHEADER));

	//2. copy gray color map
	char rgba[1024] = { 0 };
	for (int i = 0; i < 256; ++i)
	{
		rgba[i * 4] = rgba[i * 4 + 1] = rgba[i * 4 + 2] = rgba[i * 4 + 3] = i;
	}
	memcpy(*ppdist + sizeof(BITMAPINFOHEADER), rgba, 1024);

	//3. copy gray data (should be fliped)
	unsigned char* srcptr = psrc + (height - 1)*width;
	unsigned char* dstptr = *ppdist + sizeof(BITMAPINFOHEADER) + 1024;

	for (int j = 0; j < height; ++j, srcptr -= width, dstptr += iStride)
	{
		memcpy(dstptr, srcptr, width);
	}

	return true;
}

unsigned char* pdibdata = NULL;
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_DecodeBuffer(pdibdata, dibsize, &ro, &pResults);
// release memory
delete []data, data=NULL;
delete []pdibdata, pdibdata=NULL;

Only YUYV frame data is supported! If you want to support other camera formats, add interfaces as what I did.

Keep capturing frames from camera and invoking barcode detection API:

cam.start();

function capture() {
    cam.capture(function(success) {
        var frame = cam.frameRaw();

        dbr.decodeYUYVAsync(frame, format.width, format.height, barcodeTypes,
            function(msg) {
                var result = null;
                for (index in msg) {
                    result = msg[index]
                    console.log("Format: " + result['format']);
                    console.log("Value : " + result['value']);
                    console.log("##################");
                }
                setTimeout(capture, 0);
            });
    });
}

setTimeout(capture, 0);

Run camera_barcode_reader.js:

node.js barcode scanner for raspberry pi

Source Code

https://github.com/dynamsoftlabs/raspberry-pi-nodejs-barcode-reader-

The post Node.js Barcode Scanner with UVC Camera for Raspberry Pi appeared first on Code Pool.

Building Node.js Barcode Addon with DBR v5.0

$
0
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

 

The post Building Node.js Barcode Addon with DBR v5.0 appeared first on Code Pool.

Android Barcode Detection Component for React Native

$
0
0

Last week, I shared how to build a simplest React Native component from scratch. Now I want to do something more complicated. I will link Dynamsoft Barcode Reader SDK, which released as an AAR bundle file, to a React Native Barcode project and write some Java code as the bridge between JavaScript code and the library.

Building React Native Project with a Native Module and an AAR File

Before writing code, I had to figure out two things: which tool should I use to write Java code and how to compile the project with a dependent AAR file.

Plugin with id ‘com.android.library’ not found

For the first question, the answer is no doubt Android Studio. However, I found the module project which successfully built with React Native project cannot work in Android Studio.

Here is the original build.gradle file:

apply plugin: 'com.android.library'
	
android {
    compileSdkVersion 23
    buildToolsVersion "25.0.0"


    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    compile "com.facebook.react:react-native:+" 
}

When importing the project into Android Studio, you will see the error message:

gradle android library error

To solve this issue, change build.gradle as follows:

apply plugin: 'com.android.library'

 buildscript {
     repositories {
         jcenter()
     }
     dependencies {
         classpath 'com.android.tools.build:gradle:2.3.0'
     }
 }

allprojects {
    repositories {
         mavenLocal()
         jcenter()
         maven {
             // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
             url "$rootDir/../node_modules/react-native/android"
         }
        flatDir{
            dirs "$rootDir/lib"
        }
    }
}

android {
    compileSdkVersion 23
    buildToolsVersion '25.0.0'

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
}

dependencies {
    compile 'com.facebook.react:react-native:+'
    compile(name:'DynamsoftBarcodeReader', ext:'aar')
}

There are two ways to link AAR files using Gradle. One is to import an AAR file as a module and then add dependencies. The other is to specify the library path and add the line as follows:

compile(name:'DynamsoftBarcodeReader', ext:'aar')

Could not find the AAR file

Once everything is fine in Android Studio, try to build the native module with React Native project:

npm install
react-native link
react-native run-android

Something is wrong here:

react native aar error

The AAR file cannot be found! How to solve this issue? My solution is to add the library path to android/build.gradle. The path is different from that used in module project because $rootDir is the directory of the current build.gradle file.

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'
    }
}

allprojects {
    repositories {
        mavenLocal()
        jcenter()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        flatDir{
            dirs "$rootDir/../node_modules/react-native-dbr/android/lib"
        }
    }
}

Try to build the project again. It should work now.

Android Barcode Reader

UI elements

The UI only contains two elements: text and button. Click the button to scan barcode and use the text view to display results:

constructor(props) {
    super(props);
    this.state = {
      result: 'N/A'
    };

    this.onButtonPress = this
      .onButtonPress
      .bind(this);
  }

  onButtonPress() {
    BarcodeReaderManager.readBarcode('C6154D1B6B9BD0CBFB12D32099F20B35', (msg) => {
      this.setState({result: msg});
    }, (err) => {
      console.log(err);
    });
  };

  render() {
    return (
      <View style={styles.container}>
        <Button title='Read Barcode' onPress={this.onButtonPress}/>
        <Text style={styles.display}>
          Barcode Result: {this.state.result}
        </Text>
      </View>
    );
  }
}

Barcode Detection Logic

The native code mainly consists of two parts: a barcode detection activity and a React Native module that used to launch the barcode activity:

private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {

        @Override

        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {

            if (requestCode == REQUEST_CODE) {

                if (mResultCallback != null) {

                    if (resultCode == Activity.RESULT_OK) {
                        JSONObject obj = new JSONObject();
                        try {
                            obj.put(TEXT, intent.getStringExtra("SCAN_RESULT"));
                            obj.put(FORMAT, intent.getStringExtra("SCAN_RESULT_FORMAT"));
                        } catch (JSONException e) {
                            Log.d(LOG_TAG, "This should never happen");
                        }
                        mResultCallback.invoke(obj.toString());

                    } else if (resultCode == Activity.RESULT_CANCELED) {
                        Toast.makeText(getReactApplicationContext(), "Cancelled", Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(getReactApplicationContext(), "Unexpected error", Toast.LENGTH_LONG).show();
                    }
                }
            }
        }

    };

    @ReactMethod

    public void readBarcode(String license, Callback resultCallback, Callback errorCallback) {

        mResultCallback = resultCallback;
        Activity currentActivity = getCurrentActivity();

        if (currentActivity == null) {
            errorCallback.invoke("Activity doesn't exist");
            return;
        }

        Intent cameraIntent = new Intent(currentActivity.getBaseContext(), DBR.class);
        cameraIntent.setAction("com.dynamsoft.dbr");
        cameraIntent.putExtra("license", license);
        cameraIntent.setPackage(currentActivity.getApplicationContext().getPackageName());
        currentActivity.startActivityForResult(cameraIntent, REQUEST_CODE);
    }

Do not forget to add permissions and declare the activity in AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.dynamsoft.barcodescanner"
          xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.FLASHLIGHT"/>
    <uses-feature
        android:name="android.hardware.camera"
        android:required="false"/>
    <uses-feature
        android:name="android.hardware.camera.front"
        android:required="false"/>
    <uses-sdk android:minSdkVersion="15" tools:overrideLibrary="com.dynamsoft.barcode"/>

    <application android:allowBackup="true"
                 android:label="@string/app_name">

        <activity
            android:name="com.dynamsoft.camera.DBR"
            android:clearTaskOnLaunch="true"
            android:configChanges="orientation|keyboardHidden|screenSize"
            android:exported="false"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
            android:windowSoftInputMode="stateAlwaysHidden"/>
    </application>
</manifest>

How to use the module

Create a new React Native project:

react-native init NewProject

Add the dependent module from the local drive:

"dependencies": {
	"react": "16.0.0-alpha.6",
	"react-native": "0.43.3",
	"react-native-dbr":"file:../"
},

Or through npm:

npm i react-native-dbr --save

Link the dependency:

react-native link

Define the library path in android/build.gradle:

flatDir {
    dirs "$rootDir/../node_modules/react-native-dbr/android/lib"
}

Use the module in index.android.js:

import BarcodeReaderManager from 'react-native-dbr';

BarcodeReaderManager.readBarcode('C6154D1B6B9BD0CBFB12D32099F20B35', (msg) => {
    this.setState({result: msg});
}, 
(err) => {
    console.log(err);
});

How to use the app

Launch the barcode reader app.

react native barcode app

Press the button to invoke barcode scanning view:

react native barcode detection

Once a barcode detected, display the result:

react native barcode result

Remember to add a valid license. Without a valid license, the library can still work, but cannot fully display the result. Please contact support@dynamsoft.com if your license is expired.

react native barcode license

Source Code

https://github.com/dynamsoft-dbr/react-native-dbr

The post Android Barcode Detection Component for React Native appeared first on Code Pool.


Building Python Barcode Extension with DBR 5.0 on Windows

$
0
0

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

The post Building Python Barcode Extension with DBR 5.0 on Windows appeared first on Code Pool.

.NET Core Barcode Reader for Windows, Linux & macOS

$
0
0

.NET Core empowers C# developers to build DotNet applications for Windows, Linux, and macOS using one codebase. In this article, I want to share how to create a cross-platform .NET Core barcode app with Dynamsoft Barcode Reader SDK.

.NET Core barcode reader

.NET Core Installation

The latest .NET Core does not support the project.json files anymore. Instead, it uses MSBuild/csproj files for project configuration. If you have an old version installed and want to upgrade, you’d better read the article: A mapping between project.json and csproj properties.

C/C++ Barcode Libraries for Windows, Linux, and macOS

Although Dynamsoft Barcode SDK supports all platforms, the version numbers are not consistent. What you should know is the library for Windows is version 5.x, whereas the libraries for Linux and macOS are version 4.x.

Get Dynamsoft C/C++ Barcode libraries now.

.NET Core Barcode Reader

Create a new console project:

dotnet new console –o DynamsoftBarcode

The command line will generate two files: DynamsoftBarcode.csproj and Program.cs.

Copy shared libraries to the project root folder. To run the app, you have to copy *.dll, *.so, and *.dylib files to the output directory after building the project. Therefore, create an item group in DynamsoftBarcode.csproj file:

<ItemGroup>
    <None Update="DynamsoftBarcodeReader.dll">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Update="libDynamsoftBarcodeReader.dylib">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
    <None Update="libDynamsoftBarcodeReader.so">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </None>
</ItemGroup>

It is time to write some C# code in Program.cs.

To learn how to interoperate native libraries, you can read the article Native Interoperability. The technology used for accessing native structs and functions is called P/Invoke. Use namespace System.Runtime.InteropServices to import shared libraries and define the corresponding native methods. From Dynamsoft Barcode Reader 4.x to 5.x, the API definitions changed a lot.

For Dynamsoft Barcode Reader 5.x:

        [DllImport("DynamsoftBarcodeReader")]
        public static extern IntPtr DBR_CreateInstance();

        [DllImport("DynamsoftBarcodeReader")]
        public static extern void DBR_DestroyInstance(IntPtr hBarcode);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_InitLicenseEx(IntPtr hBarcode, string license);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_DecodeFileEx(IntPtr hBarcode, string filename, ref IntPtr pBarcodeResultArray);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_SetBarcodeFormats(IntPtr hBarcode, int iFormat);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_SetMaxBarcodesNumPerPage(IntPtr hBarcode, int iMaxCount);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_FreeBarcodeResults(ref IntPtr pBarcodeResultArray);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern void DBR_SetBarcodeTextEncoding(IntPtr hBarcode, BarcodeTextEncoding emEncoding);

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct BarcodeResult
        {
            public int emBarcodeFormat;
            public string pBarcodeData;
            public int iBarcodeDataLength;
            public int iLeft;
            public int iTop;
            public int iWidth;
            public int iHeight;
            public int iX1;
            public int iY1;
            public int iX2;
            public int iY2;
            public int iX3;
            public int iY3;
            public int iX4;
            public int iY4;
            public int iPageNum;
            public IntPtr pBarcodeText;
            public int iAngle;
            public int iModuleSize;
            public int bIsUnrecognized;
            public string pBarcodeFormatString;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct BarcodeResultArray
        {
            public int iBarcodeCount;
            public IntPtr ppBarcodes;
        }

For Dynamsoft Barcode Reader 4.x:

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_InitLicense(string license);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_DecodeFile(string filename, IntPtr opt, ref IntPtr pBarcodeResultArray);

        [DllImport("DynamsoftBarcodeReader")]
        public static extern int DBR_FreeBarcodeResults(ref IntPtr pBarcodeResultArray);

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct BarcodeResult
        {
            public Int64 llFormat;
            public string pBarcodeData;
            public int iBarcodeDataLength;
            public int iLeft;
            public int iTop;
            public int iWidth;
            public int iHeight;
            public int iX1;
            public int iY1;
            public int iX2;
            public int iY2;
            public int iX3;
            public int iY3;
            public int iX4;
            public int iY4;
            public int iPageNum;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct BarcodeResultArray
        {
            public int iBarcodeCount;
            public IntPtr ppBarcodes;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct ReaderOptions
        {
            public int iMaxBarcodesNumPerPage;
            public long llBarcodeFormat;
        }

To use these APIs correctly, you have to check operating system in runtime and set a valid license:

            if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                iOS = BarcodeManager.OS_WIN;
                license = "t0260NQAAALGw+aCAePXdOS3p1xkqT5hesExKVpEe7NiIhkdlUz/Jvx8km3ItI0ykUcmeP67BYVlJ2PDW++bjSYmDLmyMgOmmvc0mdvhlSy500kqnLoBAL+TybcdAP42b5p5WehK9Gsmweqi+ydK6B0KaUNQMDJZ1DrnhDXZ209pfpJoVybPk/CMcDKXaF2oRLKEOYVscXTF6mbiWUnMP5lj4OdTvFa0eVRcE0q9BckiqYgUZLK4L6DVgRXWRL5nRPtvEtd+qZe6psu0JZ7HEPhsbodfAVH2G436z1QahLGJXdQCoQv8UQ/quGQP2wCWemfueeKJ4Y6WsvEvmkUpizbTOE3Njjaw=";
            }
            else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                iOS = BarcodeManager.OS_LINUX;
                license = "30771C7C2299A4271A84011B981A3901";
            }
            else if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            {
                iOS = BarcodeManager.OS_MAC;
                license = "30771C7C2299A427B5765EB4250FC51B";
            }

Invoking barcode APIs is not a big deal. The key point is memory management – how to convert managed structure to an unmanaged pointer and vice versa.

You need to pass a managed structure to unmanaged pointer when using Dynamsoft Barcode 4.x:

LinuxMacBarcodeManager.ReaderOptions ro = new LinuxMacBarcodeManager.ReaderOptions();
ro.llBarcodeFormat = iFormat;
ro.iMaxBarcodesNumPerPage = iMaxCount;

// Copy the struct to unmanaged memory.
IntPtr opt = Marshal.AllocHGlobal(Marshal.SizeOf(ro));
Marshal.StructureToPtr(ro, opt, false);

// Read barcodes
int ret = LinuxMacBarcodeManager.DBR_DecodeFile(filename, opt, ref pBarcodeResultArray);

To get the final results, use Marshal.PtrToStructure:

// Print barcode results
if (pBarcodeResultArray != IntPtr.Zero)
{
    LinuxMacBarcodeManager.BarcodeResultArray results = (LinuxMacBarcodeManager.BarcodeResultArray)Marshal.PtrToStructure(pBarcodeResultArray, typeof(LinuxMacBarcodeManager.BarcodeResultArray));
    int count = results.iBarcodeCount;
    IntPtr[] barcodes = new IntPtr[count];

    Marshal.Copy(results.ppBarcodes, barcodes, 0, count);

    for (int i = 0; i < count; i++)
    {
        LinuxMacBarcodeManager.BarcodeResult result = (LinuxMacBarcodeManager.BarcodeResult)Marshal.PtrToStructure(barcodes[i], typeof(LinuxMacBarcodeManager.BarcodeResult));
        Console.WriteLine("Value: " + result.pBarcodeData);
        Console.WriteLine("Format: " + LinuxMacBarcodeManager.GetFormatStr(result.llFormat));
        Console.WriteLine("-----------------------------");
    }

    // Release memory of barcode results
    LinuxMacBarcodeManager.DBR_FreeBarcodeResults(ref pBarcodeResultArray);

}

That’s it. Try the sample code on Windows, Linux, and macOS.

dotnet restore
dotnet run

.NET Core bin
.NET Core barcode reader

Source Code

https://github.com/dynamsoft-dbr/dotnet-core-barcode

The post .NET Core Barcode Reader for Windows, Linux & macOS appeared first on Code Pool.

How to Use Dynamsoft JavaScript Barcode SDK

$
0
0

If you always stay tuned to Dynamsoft Barcode SDK, you should have noticed that starting with version 5.1, the SDK includes a JavaScript library which is similar to Dynamic Web TWAIN. The article aims to help developers get familiar with the relevant JavaScript Barcode APIs and build web barcode reader apps quickly.

How does Dynamsoft JavaScript Barcode SDK Work

Dynamsoft JavaScript Barcode SDK is a part of Dynamsoft imaging and recognition modules. It does not run independently. See the following diagram:

Dynamsoft JavaScript imaging modules

 

The front-end library communicates with the back-end web service. One thing you have to know is that the service is cross-platform, though, only TWAIN JS module can work on Windows, Linux and macOS so far. The JavaScript Barcode SDK only works on Windows now.

Building Web Barcode Reader on Windows

Create an HTML page which contains an input field for loading image files, some check boxes for selecting barcode types, a button for reading barcodes, and a text area for displaying results.

Include dynamsoft.barcode.min.js:

<script type="text/javascript" src="http://www.dynamsoft.com/library/dbr/dynamsoft.barcode.min.js"></script>

Set a valid license:

dynamsoft.dbrEnv.productKey = "t0068NQAAAGesx+MAzzxDdPsKq7w2o/NatXjaIedwY/4h8b6dfEz+7OG8DZxgHoUfaHZC4xu+AoMxriB2L44DAKXJK25f0hg=";

Initialize the environment:

function onInitSuccess() {
    dbrObject = new dynamsoft.dbrEnv.BarcodeReader();
}

function onInitError(errCode, errMsg) {
    alert(errMsg);
}

dynamsoft.dbrEnv.init(onInitSuccess, onInitError);

Get checked types:

function getSelectedBarcodeTypes() {
    var vType = 0;
    var barcodeTypes = document.getElementsByName("BarcodeType");
    for (i = 0; i < barcodeTypes.length; i++) {
        if (barcodeTypes[i].checked == true)
            vType = vType | (barcodeTypes[i].value * 1);
    }

    return vType? vType : -1;
}

Scan barcodes:

function doReadBarcode() {
    dbrObject.barcodeFormats = getSelectedBarcodeTypes();
    var file = document.getElementById("fileToUpload").files[0];
    dbrObject.readBinaryAsync(file, "tmp.bmp", onBarcodeReadSuccess, onBarcodeReadFailure);
}

Display barcode results:

function onBarcodeReadSuccess(userData, result) {
    var count = result.getCount();
    var strMsg = "";
    if (count > 0) {
        for (var i = 0; i < count; i++) {
            strMsg += "<p>" + "Index: " + i + ". ";
            strMsg += "Barcode Type: " + result.get(i).formatString + ", ";
            strMsg += "Barcode Value: " + result.get(i).text + ".</p>";
        }
        document.getElementById('resultBox').innerHTML = strMsg;
    } else {
        alert("No barcode(s) found.");
    }
}

Open index.htm in Chrome:

JavaScript barcode reader

API Reference

http://www.dynamsoft.com/help/Barcode-Reader-JS/index.html

Source Code

https://github.com/dynamsoft-dbr/web

The post How to Use Dynamsoft JavaScript Barcode SDK appeared first on Code Pool.

Building Kotlin Barcode Reader on Windows

$
0
0

Kotlin, developed by JetBrain, is a statically typed programming language that compiles to Java code and JavaScript code. Recently, Google announced that Kotlin is a first-class language for writing Android apps. The big Android market will bring a promising future for Kotlin. If you never used Kotlin before and don’t want to fall behind, get started with the new programming language now. In this article, I want to share the experience of writing my first Kotlin app – a command line barcode reader.

Dev Tool and Barcode Library

  • IntelliJ IDEA Community is the recommended tool for developing Kotlin project.
  • Dynamsoft Barcode Reader SDK provides dynamsoft.barcode.jar for writing barcode reader app in Java. Since Kotlin is designed with Java interoperability, we can directly use the Java library in Kotlin project.

Kotlin: Hello World

Read official Kotlin tutorial, create an app.kt file to write a Kolin app quickly:

fun main(args: Array<String>) {
    println("Hello World")
}

Kotlin’s documentation provides a lot of new knowledge, and it’s hard to digest in a short time. Luckily, Java is easily convertible to Kotlin. Comparing to reading Kotlin documentation, I prefer to learn Kotlin by converting Java code. Here is the classic ‘Hello World’ program in Java:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Let’s paste it to app.kt to see what will happen in IntelliJ IDEA. The IDE will automatically convert it to Kotlin code:

object HelloWorld {

    @JvmStatic fun main(args: Array<String>) {
        println("Hello World")
    }

}

Press ‘Ctrl + Shift + F10’ to run the app:

kotlin build error

Something is wrong with the error message:

!!! JUnit version 3.8 or later expected

java.lang.ClassNotFoundException: junit.framework.ComparisonFailure.

The file name causes the issue! Changing app.kt to HelloWorld.kt will fix the problem.

Kotlin Barcode Reader

Press ‘Ctrl + Shift + Alt + S‘ to open project structure. Click Libraries to add com.dynamsoft.barcode.jar file.

 Kotlin barcode library

Dynamsoft Barcode Reader SDK already contains a Java sample. So just copy BarcodeReaderDemo.java from Dynamsoft\Barcode Reader 5.1\Samples\Desktop\Java to your Kotlin project.

On the menu bar, select Code > Convert Java File to Kotlin File:

java to kotlin

            // Read barcode
            val result = br.readFile(pszImageFile!!, lFormat, iMaxCount)

            if (result.errorCode != BarcodeReader.DBR_OK && result.errorCode != BarcodeReader.DBRERR_LICENSE_EXPIRED && result.errorCode != BarcodeReader.DBRERR_LICENSE_INVALID) {
                println(result.errorString)
                continue
            }

            // Output barcode result

            var pszTemp: String

            if (result.barcodes == null || result.barcodes.size == 0) {
                pszTemp = String.format(
                        "No barcode found. Total time spent: %.3f seconds.", (ullTimeEnd - ullTimeBegin).toFloat() / 1000)
                println(pszTemp)
            } else {
                pszTemp = String.format("Total barcode(s) found: %d. Total time spent: %.3f seconds.", result.barcodes.size, (ullTimeEnd - ullTimeBegin).toFloat() / 1000)
                println(pszTemp)

                iIndex = 0
                while (iIndex < result.barcodes.size) {
                    val barcode = result.barcodes[iIndex]

                    pszTemp = String.format("  Barcode %d:", iIndex + 1)
                    println(pszTemp)
                    pszTemp = String.format("    Page: %d", barcode.pageNumber)
                    println(pszTemp)
                    pszTemp = String.format("    Type: %s", barcode.formatString)
                    println(pszTemp)
                    pszTemp = "    Value: " + barcode.displayValue
                    println(pszTemp)


                    pszTemp = String.format("    Region: {Left: %d, Top: %d, Width: %d, Height: %d}",
                            barcode.boundingBox.x, barcode.boundingBox.y, barcode.boundingBox.width, barcode.boundingBox.height)

                    println(pszTemp)
                    println()
                    iIndex++
                }
            }

There is an error – Operator ‘!=’ cannot be applied to ‘Long’ and ‘Int’.

Kotlin long int

To fix it, add ‘L’ after 0:

if (lFormat != 0L)
    break

Now we can successfully run the Kotlin barcode app.

Source Code

https://github.com/dynamsoft-dbr/kotlin-windows

The post Building Kotlin Barcode Reader on Windows appeared first on Code Pool.

Mixing Kotlin and Java to Build Android Barcode Reader

$
0
0

Last week I made a warm up for Kotlin, getting started to learn tutorials and reference. Now it is time to take the next step. Since Kotlin is hundred percent compatible with Java, we can use both programming languages without barriers in one project. In this article, I want to share how to build an Android barcode reader using Kotlin code and Java code.

Prerequisites

A Simple Android Barcode Reader

Create a new Android project includes Kotlin support

Kotlin new Android project

Add an AAR file to Android project

There are two ways to add the dependency DynamsoftBarcodeReader.aar to your project.

Import the AAR file as a module

Create a new module to import *.aar file:

Kotlin import Android AAR

Then open project structure (Ctrl + Alt + Shift +S) to add module dependency.

Manually edit the build.gradle file

Open app/build.gradle to add following code:

allprojects {
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
}
dependencies {
    compile(name:'DynamsoftBarcodeReader', ext:'aar')
}

Create and initialize UI elements

Open default layout file res/activity_main.xml to add a Button and a TextView:

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/bt_read_barcode"/>
    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>

If you are familiar with Android, you should know that we can get the view references in function onCreate(). Here is the Java code:

private TextView mTextView;
private Button mButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mButton = (Button) findViewById(R.id.button);
    mTextView = (TextView)findViewById(R.id.text);
}

How to convert the Java code to Kotlin code? For beginners who have no idea how to write the code from scratch, just press ‘Ctrl + Alt + Shift +K’ to use the auto-conversion tool.

private var mTextView: TextView? = null
private var mButton: Button? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    mButton = findViewById(R.id.button) as Button
    mTextView = findViewById(R.id.text) as TextView
}

Not like Java, Kotlin uses ‘type ?’ to declare a nullable type. Now let’s add a click event. According to my experience, I wrote the Kotlin code as follows at the first time:

mButton.setOnClickListener // Error

I got the error message “smart cast to ‘Button’ is impossible, because ‘mButton’ is a mutable property that could have been changed by this time.”

To make the code work, I have to use the !! operator which returns a non-null value of mButton.

mButton!!.setOnClickListener // OK

Is it possible to make the syntax look like Java? We can declare late-initialized properties:

private lateinit var mTextView: TextView
private lateinit var mButton: Button

In this way, we can avoid null check when calling the method:

mButton.setOnClickListener // OK

Call barcode reading Activity

The barcode detection Activity, written in Java, is originally from the open source code of Dynamsoft Barcode Scanner. We just need to create an intent to start the barcode Activity and display the returned results:

mButton.setOnClickListener {
    val license: String = "AA721B9FAB21454427702FE780B56C50"
    val cameraIntent = Intent(baseContext, DBR::class.java)
    cameraIntent.action = DBR.ACTION_BARCODE
    cameraIntent.putExtra("license", license)

    // avoid calling other phonegap apps
    cameraIntent.`package` = baseContext.getPackageName()

    startActivityForResult(cameraIntent, REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (requestCode === REQUEST_CODE) {
        if (resultCode === Activity.RESULT_OK) {
            // https://kotlinlang.org/docs/reference/null-safety.html
            val result = data?.getStringExtra("SCAN_RESULT")
            val format = data?.getStringExtra("SCAN_RESULT_FORMAT")
            // https://stackoverflow.com/questions/33164886/android-textview-do-not-concatenate-text-displayed-with-settext
            mTextView.text = getString(R.string.barcode_result, result, format)
        } else if (resultCode === Activity.RESULT_CANCELED) {
            Toast.makeText(baseContext, "Cancelled", Toast.LENGTH_LONG).show()
        } else {
            Toast.makeText(baseContext, "Unexpected error", Toast.LENGTH_LONG).show()
        }
    }
}

Run the app

Kotlin Android barcode scan

Kotlin Android Barcode reader

Source Code

https://github.com/dynamsoft-dbr/kotlin-android

The post Mixing Kotlin and Java to Build Android Barcode Reader appeared first on Code Pool.

Viewing all 145 articles
Browse latest View live