📜 ⬆️ ⬇️

Generate and scan QR / BAR codes


The article provides a brief example of how to integrate a generator and / or scanner of QR codes (or bar codes) into your application, and thus facilitate the task of transferring short amounts of information from a device to a device.

QR codes have replaced outdated barcodes (hereinafter instead of 'Bar code') and are entering our life more and more tightly, they are used in dozens of different solutions, from sending links to the site to complex authorization and shopping systems.

You can find out in detail what a QR code is in detail from the article. Read QR code

To complete the task, we need 2 libraries from two projects:

Scanning QR codes

Libraries from ZBar bar code reader will be used for scanning, so let's go:
  1. Add to project zbar.jar
  2. Add libiconv.so and libzbarjni.so libraries to the native project, which are responsible for analyzing and recognizing images from the camera in real
    of time.
  3. We load native libraries into memory
    static { System.loadLibrary("iconv"); } 
  4. We initialize the scanner
     scanner = new ImageScanner(); scanner.setConfig(0, Config.X_DENSITY, 3); //       scanner.setConfig(0, Config.Y_DENSITY, 3); 
  5. Then we transfer to the scanner each new frame from camera preview
     PreviewCallback previewCb = new PreviewCallback() { public void onPreviewFrame(byte[] data, Camera camera) { String lastScannedCode; codeImage.setData(data); int result = scanner.scanImage(codeImage); if (result != 0) { SymbolSet syms = scanner.getResults(); for (Symbol sym : syms) { lastScannedCode = sym.getData(); } } } } 
  6. As a result, in the lastScannedCode we get the recognized code.
    There is one feature here, result = scanner.scanImage (codeImage) sometimes returns the correct result, even when there is no QR code in front of the camera. That is, the camera sometimes recognizes something even in the usual blurred picture. Therefore, I recommend to introduce an additional check for the size of the read code or for compliance with the expected format.


We generate QR codes

In this case, the resources of the ZXing library will already be involved.
Input parameters encodeAsBitmap : text or code for encoding, the standard in which we encode, the size of the image at the output.
 Bitmap barcode_bitmap = encodeAsBitmap(text, BarcodeFormat.QR_CODE, 200, 200); targetImageView.setImageBitmap(barcode_bitmap); private static Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int img_width, int img_height) throws WriterException { String contentsToEncode = contents; if (contentsToEncode == null) { return null; } Map<EncodeHintType, Object> hints = null; String encoding = guessAppropriateEncoding(contentsToEncode); if (encoding != null) { hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class); hints.put(EncodeHintType.CHARACTER_SET, encoding); } MultiFormatWriter writer = new MultiFormatWriter(); BitMatrix result; try { result = writer.encode(contentsToEncode, format, img_width, img_height, hints); } catch (IllegalArgumentException iae) { // Unsupported format return null; } int width = result.getWidth(); int height = result.getHeight(); int[] pixels = new int[width * height]; for (int y = 0; y < height; y++) { int offset = y * width; for (int x = 0; x < width; x++) { pixels[offset + x] = result.get(x, y) ? BLACK : WHITE; } } Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; } 

What about Barcodes?

The scanner understands all kinds of bar codes without any modifications, out of the box .
')
The generator is modified not simply, but very simply:
in the encodeAsBitmap function, we send in the format field instead of BarcodeFormat.QR_CODE, something like BarcodeFormat.CODE_128, which will correspond to the Code 128 standard barcode

A couple of tips for last

Keep in mind that working with the camera may have its own characteristics on different platforms.

Noticed that the method
 public void onPreviewFrame(byte[] data, Camera camera) { codeImage.setData(data); .... } 
constantly losing memory (there is Memory Leak) due to the fact that the frame buffer is constantly being created and cleared at each new preview frame from the camera.
In order to avoid this, it is possible to use CallbackBuffer to allocate a static buffer under the preview frames.
It really helps to get rid of memory leaks and even increases the frame rate of the preview image from the camera.
But! , I found a phone model that didn’t want to work with the preview buffer in any way and not the fact that they wouldn’t be found yet, so I left a more reliable method in the example.

Barcode generation has limitations according to the selected standard: maximum size in bytes, allowed media, etc.
Examine the features of linear shtrikodov , in order to ensure the compatibility of the bar codes displayed by you with store scanners

For those who are going to use .so libraries in projects using the Gradle system build, the steps are as follows: create the iconv.jar jar file with the following structure:
  • lib /
  • lib / x86
  • lib / armeabi
  • lib / armeabi-v7a

and add dependencies to its section
compile files ('libs / iconv.jar')
Or, a more universal option, that would not describe all the JAR files separately:
 dependencies { compile fileTree(dir: 'lib', include: '*.jar') } 


UPD. Filled source on github
What happened at the output of the project (Generator and Scanner in one bottle):

Source: https://habr.com/ru/post/213291/


All Articles