Build a React Native Vision Camera Frame Processor Plugin to Scan Barcodes for iOS

In the previous article, we’ve created a React Native Vision Camera frame processor plugin for Dynamsoft Barcode Reader (DBR). Let’s continue to create the frame processor plugin for iOS.

Building the React Native Vision Camera Frame Processor Plugin of Barcode Reader for iOS

Import DBR

We need to import the DBR framework first

  1. Open vision-camera-dynamsoft-barcode-reader.podspec and add the following lines:

     s.libraries = 'c++'
     s.dependency 'DynamsoftBarcodeReader', '= 9.0.0'
    
  2. Update pods

     cd example/ios
     pod install
    

Add Camera Permission

We also need to add the following to Info.plist for camera permission:

<key>NSCameraUsageDescription</key>
<string>For barcode scanning</string>
<key>NSMicrophoneUsageDescription</key>
<string>For barcode scanning</string>

Implement the iOS Part of the Plugin

  1. Go to ios, remove VisionCameraDynamsoftBarcodeReader.swift and VisionCameraDynamsoftBarcodeReader.m

  2. Create a new file named VisionCameraDBRPlugin.swift with the following content:

     import Foundation
    
     @objc(VisionCameraDBRPlugin)
     public class VisionCameraDBRPlugin: NSObject, FrameProcessorPluginBase {
         @objc
         public static func callback(_ frame: Frame!, withArgs args: [Any]!) -> Any! {
             // code goes here
             return []
         }
     }
    
  3. Add the following content to VisionCameraDynamsoftBarcodeReader-Bridging-Header.h

     #import <VisionCamera/FrameProcessorPlugin.h>
     #import <VisionCamera/Frame.h>
    
  4. Create a new Objective-C file with the same name as the Swift file with the following content:

     #import <Foundation/Foundation.h>
     #import <VisionCamera/FrameProcessorPlugin.h>
    
     @interface VISION_EXPORT_SWIFT_FRAME_PROCESSOR(decode, VisionCameraDBRPlugin)
    
     @end
    
  5. Create a new BarcodeReaderInitializer.swift to initialize Dynamsoft Barcode Reader:

     public class BarcodeReaderInitializer: NSObject, DBRLicenseVerificationListener {
            
         func configurationDBR(license:String) -> DynamsoftBarcodeReader {
             var dbr:DynamsoftBarcodeReader
             DynamsoftBarcodeReader.initLicense(license, verificationDelegate: self)
             dbr = DynamsoftBarcodeReader.init()
             return dbr
         }
            
         public func dbrLicenseVerificationCallback(_ isSuccess: Bool, error: Error?) {
             let err = error as NSError?
             if(err != nil){
                 print("Server DBR license verify failed")
             }
         }
     }
    
  6. Use the Initializer to create an instance of Dynamsoft Barcode Reader if the plugin is called:

     private static var barcodeReader:DynamsoftBarcodeReader! = nil
     public static func callback(_ frame: Frame!, withArgs args: [Any]!) -> Any! {
         let config = getConfig(withArgs: args)
         if barcodeReader == nil {
             initDBR(config: config)
         }
         return []
     }
    
     static func initDBR(config: [String:String]!) {
         var license = "";
         license = config?["license"] ?? "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="
         let initializer = BarcodeReaderInitializer();
         barcodeReader = initializer.configurationDBR(license: license)
     }
        
     static func getConfig(withArgs args: [Any]!) -> [String:String]!{
         if args.count>0 {
             let config = args[0] as? [String: String]
             return config
         }
         return nil
     }
    
  7. Decode the image using Dynamsoft Barcode Reader and return the result

     private static let context = CIContext(options: nil)
     @objc
     public static func callback(_ frame: Frame!, withArgs args: [Any]!) -> Any! {
         let config = getConfig(withArgs: args)
         if barcodeReader == nil {
             initDBR(config: config)
         }
         guard let imageBuffer = CMSampleBufferGetImageBuffer(frame.buffer) else {
           print("Failed to get CVPixelBuffer!")
           return nil
         }
         let ciImage = CIImage(cvPixelBuffer: imageBuffer)
    
         guard let cgImage = context.createCGImage(ciImage, from: ciImage.extent) else {
           print("Failed to create CGImage!")
           return nil
         }
         var returned_results: [Any] = []
         let image = UIImage(cgImage: cgImage)
         // code goes here
         let results = try? barcodeReader.decodeImage(image)
         let count = results?.count ?? 0
         if count > 0 {
             for index in 0..<count {
                 let tr = results![index]
                 returned_results.append(wrapResult(result: tr))
             }
             print("Found barcodes")
         }
         return returned_results
     }
    
     static func wrapResult(result: iTextResult) -> Any {
         var map: [String: Any] = [:]
            
         map["barcodeText"] = result.barcodeText
         map["barcodeFormat"] = result.barcodeFormatString
            
         let points = result.localizationResult?.resultPoints as! [CGPoint]
         map["x1"] = points[0].x
         map["x2"] = points[1].x
         map["x3"] = points[2].x
         map["x4"] = points[3].x
         map["y1"] = points[0].y
         map["y2"] = points[1].y
         map["y3"] = points[2].y
         map["y4"] = points[3].y
            
         return map
     }
    

The iOS implementation of the React Native Vision Camera plugin is now completed. You can test the project following the previous article’s guide.

Source Code

You can check out the source code for more details.

https://github.com/xulihang/vision-camera-dynamsoft-barcode-reader