casvanluijtelaar

implemented ios

@@ -2,6 +2,7 @@ import AVFoundation @@ -2,6 +2,7 @@ import AVFoundation
2 import Flutter 2 import Flutter
3 import MLKitVision 3 import MLKitVision
4 import MLKitBarcodeScanning 4 import MLKitBarcodeScanning
  5 +import UIKit
5 6
6 public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, FlutterTexture, AVCaptureVideoDataOutputSampleBufferDelegate { 7 public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, FlutterTexture, AVCaptureVideoDataOutputSampleBufferDelegate {
7 8
@@ -26,6 +27,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -26,6 +27,9 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
26 var analyzing: Bool = false 27 var analyzing: Bool = false
27 var position = AVCaptureDevice.Position.back 28 var position = AVCaptureDevice.Position.back
28 29
  30 + // optional frame to crop camera image before barcode detection
  31 + var scanWindow: CGRect?
  32 +
29 var scanner = BarcodeScanner.barcodeScanner() 33 var scanner = BarcodeScanner.barcodeScanner()
30 34
31 public static func register(with registrar: FlutterPluginRegistrar) { 35 public static func register(with registrar: FlutterPluginRegistrar) {
@@ -99,13 +103,22 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -99,13 +103,22 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
99 } 103 }
100 analyzing = true 104 analyzing = true
101 let buffer = CMSampleBufferGetImageBuffer(sampleBuffer) 105 let buffer = CMSampleBufferGetImageBuffer(sampleBuffer)
102 - let image = VisionImage(image: buffer!.image)  
103 - image.orientation = imageOrientation( 106 +
  107 + var image: VisionImage?
  108 +
  109 + if (scanWindow != nil) {
  110 + let cropped = cropSampleBuffer(imageBuffer: buffer!, cropRect: scanWindow!)
  111 + image = VisionImage(image: cropped)
  112 + } else {
  113 + image = VisionImage(image: buffer!.image)
  114 + }
  115 +
  116 + image!.orientation = imageOrientation(
104 deviceOrientation: UIDevice.current.orientation, 117 deviceOrientation: UIDevice.current.orientation,
105 defaultOrientation: .portrait 118 defaultOrientation: .portrait
106 ) 119 )
107 120
108 - scanner.process(image) { [self] barcodes, error in 121 + scanner.process(image!) { [self] barcodes, error in
109 if error == nil && barcodes != nil { 122 if error == nil && barcodes != nil {
110 for barcode in barcodes! { 123 for barcode in barcodes! {
111 let event: [String: Any?] = ["name": "barcode", "data": barcode.data] 124 let event: [String: Any?] = ["name": "barcode", "data": barcode.data]
@@ -119,6 +132,29 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -119,6 +132,29 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
119 // } 132 // }
120 } 133 }
121 134
  135 + public func cropSampleBuffer(imageBuffer: CVImageBuffer, cropRect: CGRect) -> UIImage {
  136 + CVPixelBufferLockBaseAddress(imageBuffer, .readOnly)
  137 +
  138 + let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer)!
  139 + let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer)
  140 + let cropX = Int(cropRect.minX)
  141 + let cropY = Int(cropRect.minY)
  142 + let cropWidth = Int(cropRect.width)
  143 + let cropHeight = Int(cropRect.height)
  144 + let colorSpace = CGColorSpaceCreateDeviceRGB()
  145 +
  146 + // calculate start position
  147 + let bytesPerPixel = 4
  148 + let startAddress = baseAddress + cropY * bytesPerRow + cropX * bytesPerPixel
  149 +
  150 + let context = CGContext(data: startAddress, width: cropWidth, height: cropHeight, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue)
  151 + CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly)
  152 +
  153 + // create image
  154 + let cgImage: CGImage = context!.makeImage()!
  155 + return UIImage(cgImage: cgImage)
  156 + }
  157 +
122 func imageOrientation( 158 func imageOrientation(
123 deviceOrientation: UIDeviceOrientation, 159 deviceOrientation: UIDeviceOrientation,
124 defaultOrientation: UIDeviceOrientation 160 defaultOrientation: UIDeviceOrientation
@@ -173,6 +209,15 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan @@ -173,6 +209,15 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan
173 let facing: Int = argReader.int(key: "facing") ?? 1 209 let facing: Int = argReader.int(key: "facing") ?? 1
174 let formats: Array = argReader.intArray(key: "formats") ?? [] 210 let formats: Array = argReader.intArray(key: "formats") ?? []
175 211
  212 + let scanWindowData: Array? = argReader.intArray(key: "scanWindow")
  213 + if(scanWindowData != nil) {
  214 + scanWindow = CGRect(
  215 + x: scanWindowData![0],
  216 + y: scanWindowData![1],
  217 + width: scanWindowData![2] - scanWindowData![0],
  218 + height: scanWindowData![3] - scanWindowData![1])
  219 + }
  220 +
176 let formatList: NSMutableArray = [] 221 let formatList: NSMutableArray = []
177 for index in formats { 222 for index in formats {
178 formatList.add(BarcodeFormat(rawValue: index)) 223 formatList.add(BarcodeFormat(rawValue: index))