@scr2em/capacitor-scanner 6.0.33 → 6.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -246,31 +246,24 @@ public class CapacitorScannerPlugin: CAPPlugin, CAPBridgedPlugin, AVCaptureMetad
246
246
  AVVideoCompressionPropertiesKey: [AVVideoQualityKey: qualityNumber]])
247
247
 
248
248
  let maxPrioritization = photoOutput.maxPhotoQualityPrioritization
249
- // Compare the raw values to determine which prioritization to use
250
- if maxPrioritization.rawValue >= AVCapturePhotoOutput.QualityPrioritization.balanced.rawValue {
251
- // Device supports .balanced prioritization
249
+ if maxPrioritization.rawValue >= AVCapturePhotoOutput.QualityPrioritization.quality.rawValue {
250
+ photoSettings.photoQualityPrioritization = .quality
251
+ } else if maxPrioritization.rawValue >= AVCapturePhotoOutput.QualityPrioritization.balanced.rawValue {
252
252
  photoSettings.photoQualityPrioritization = .balanced
253
253
  } else {
254
- // Use the lowest prioritization (.speed)
255
254
  photoSettings.photoQualityPrioritization = .speed
256
255
  }
257
256
 
257
+ // Enable high-resolution capture for sharper photos
258
+ photoSettings.isHighResolutionPhotoEnabled = true
259
+
258
260
  } else {
259
261
  print("JPEG codec not supported for photo capture. Using default settings.")
260
262
  // photoSettings remains the default initialized one
261
263
  }
262
264
 
263
265
  self.capturePhotoCall = call
264
-
265
- // If business card detection is enabled, wait for 1 second before capturing
266
- if self.enabledDetectionTypes.contains("businessCard") {
267
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) {
268
- photoOutput.capturePhoto(with: photoSettings, delegate: self)
269
- }
270
- } else {
271
- // Otherwise capture immediately
272
- photoOutput.capturePhoto(with: photoSettings, delegate: self)
273
- }
266
+ photoOutput.capturePhoto(with: photoSettings, delegate: self)
274
267
  }
275
268
 
276
269
  public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
@@ -297,37 +290,22 @@ public class CapacitorScannerPlugin: CAPPlugin, CAPBridgedPlugin, AVCaptureMetad
297
290
  if self.enabledDetectionTypes.contains("businessCard"),
298
291
  isRectangleCurrentlyDetected,
299
292
  let detectedRect = self.rectangleDetector?.lastDetectedRectangle {
300
- // If we have a snapshot from the detection, use it directly
301
- if let snapshot = detectedRect.snapshot {
302
- if let croppedImage = self.cropImage(snapshot, toRectangle: detectedRect.observation) {
303
- guard let croppedImageData = croppedImage.jpegData(compressionQuality: 0.9) else {
304
- self.capturePhotoCall?.reject("Unable to convert cropped image to data")
305
- return
306
- }
307
- let base64String = croppedImageData.base64EncodedString()
308
- self.capturePhotoCall?.resolve(["imageBase64": "data:image/jpeg;base64, \(base64String)"])
309
- } else {
310
- let base64String = imageData.base64EncodedString()
311
- self.capturePhotoCall?.resolve(["imageBase64": "data:image/jpeg;base64, \(base64String)"])
312
- }
313
- } else {
314
- // Use the captured photo if no snapshot available
315
- guard let image = UIImage(data: imageData) else {
316
- self.capturePhotoCall?.reject("Unable to create image from data")
317
- return
318
- }
293
+ // Always use the high-resolution captured photo for cropping (not the video frame snapshot)
294
+ guard let image = UIImage(data: imageData) else {
295
+ self.capturePhotoCall?.reject("Unable to create image from data")
296
+ return
297
+ }
319
298
 
320
- if let croppedImage = self.cropImage(image, toRectangle: detectedRect.observation) {
321
- guard let croppedImageData = croppedImage.jpegData(compressionQuality: 0.9) else {
322
- self.capturePhotoCall?.reject("Unable to convert cropped image to data")
323
- return
324
- }
325
- let base64String = croppedImageData.base64EncodedString()
326
- self.capturePhotoCall?.resolve(["imageBase64": "data:image/jpeg;base64, \(base64String)"])
327
- } else {
328
- let base64String = imageData.base64EncodedString()
329
- self.capturePhotoCall?.resolve(["imageBase64": "data:image/jpeg;base64, \(base64String)"])
299
+ if let croppedImage = self.cropImage(image, toRectangle: detectedRect) {
300
+ guard let croppedImageData = croppedImage.jpegData(compressionQuality: 0.9) else {
301
+ self.capturePhotoCall?.reject("Unable to convert cropped image to data")
302
+ return
330
303
  }
304
+ let base64String = croppedImageData.base64EncodedString()
305
+ self.capturePhotoCall?.resolve(["imageBase64": "data:image/jpeg;base64, \(base64String)"])
306
+ } else {
307
+ let base64String = imageData.base64EncodedString()
308
+ self.capturePhotoCall?.resolve(["imageBase64": "data:image/jpeg;base64, \(base64String)"])
331
309
  }
332
310
  } else {
333
311
  // No rectangle detected, return original image
@@ -540,6 +518,8 @@ public class CapacitorScannerPlugin: CAPPlugin, CAPBridgedPlugin, AVCaptureMetad
540
518
  self.photoOutput = photoOutput
541
519
  if captureSession.canAddOutput(photoOutput) {
542
520
  captureSession.addOutput(photoOutput)
521
+ photoOutput.maxPhotoQualityPrioritization = .quality
522
+ photoOutput.isHighResolutionCaptureEnabled = true
543
523
  } else {
544
524
  call.reject("Unable to add photo output to capture session")
545
525
  return
@@ -1066,7 +1046,6 @@ extension CapacitorScannerPlugin: AVCaptureVideoDataOutputSampleBufferDelegate {
1066
1046
  if !isThrottled,
1067
1047
  self.enabledDetectionTypes.contains("businessCard"),
1068
1048
  let detector = self.rectangleDetector {
1069
- detector.updatePixelBuffer(pixelBuffer)
1070
1049
  requests.append(detector.visionRequest)
1071
1050
  }
1072
1051
 
@@ -18,14 +18,6 @@ struct RectangleCorners {
18
18
  /// Handles rectangle/business card detection using Vision framework
19
19
  class RectangleDetector {
20
20
 
21
- // MARK: - Types
22
-
23
- /// Stores detected rectangle with optional snapshot for cropping
24
- struct DetectedRectangle {
25
- let observation: VNRectangleObservation
26
- let snapshot: UIImage?
27
- }
28
-
29
21
  // MARK: - Configuration
30
22
 
31
23
  private let confidenceThreshold: Float = 0.8
@@ -38,10 +30,8 @@ class RectangleDetector {
38
30
 
39
31
  // MARK: - State
40
32
 
41
- private(set) var lastDetectedRectangle: DetectedRectangle?
33
+ private(set) var lastDetectedRectangle: VNRectangleObservation?
42
34
  private(set) var lastDetectionTime: Date?
43
- private var currentPixelBuffer: CVPixelBuffer?
44
- private let ciContext = CIContext(options: nil)
45
35
 
46
36
  // Stability tracking
47
37
  private var previousCorners: RectangleCorners?
@@ -100,11 +90,6 @@ class RectangleDetector {
100
90
  emitIntervalSeconds = max(0, seconds)
101
91
  }
102
92
 
103
- /// Update the current pixel buffer for snapshot capture
104
- func updatePixelBuffer(_ pixelBuffer: CVPixelBuffer) {
105
- self.currentPixelBuffer = pixelBuffer
106
- }
107
-
108
93
  /// Check for detection timeout and update overlay
109
94
  func checkTimeout() {
110
95
  smoother?.checkTimeout()
@@ -120,7 +105,6 @@ class RectangleDetector {
120
105
  func reset() {
121
106
  lastDetectedRectangle = nil
122
107
  lastDetectionTime = nil
123
- currentPixelBuffer = nil
124
108
  previousCorners = nil
125
109
  stabilityStartTime = nil
126
110
  lastEmitTime = nil
@@ -157,8 +141,8 @@ class RectangleDetector {
157
141
  return
158
142
  }
159
143
 
160
- // Store rectangle with snapshot for cropping
161
- captureSnapshot(for: bestCandidate)
144
+ // Store rectangle observation for cropping
145
+ lastDetectedRectangle = bestCandidate
162
146
 
163
147
  // Update detection time
164
148
  lastDetectionTime = Date()
@@ -287,34 +271,4 @@ class RectangleDetector {
287
271
  }
288
272
  }
289
273
 
290
- private func captureSnapshot(for observation: VNRectangleObservation) {
291
- guard let pixelBuffer = currentPixelBuffer else {
292
- lastDetectedRectangle = DetectedRectangle(observation: observation, snapshot: nil)
293
- return
294
- }
295
-
296
- let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
297
-
298
- guard let cgImage = ciContext.createCGImage(ciImage, from: ciImage.extent) else {
299
- lastDetectedRectangle = DetectedRectangle(observation: observation, snapshot: nil)
300
- return
301
- }
302
-
303
- // Create UIImage with correct orientation
304
- let deviceOrientation = UIDevice.current.orientation
305
- let uiOrientation: UIImage.Orientation
306
- switch deviceOrientation {
307
- case .landscapeLeft:
308
- uiOrientation = .right
309
- case .landscapeRight:
310
- uiOrientation = .left
311
- case .portraitUpsideDown:
312
- uiOrientation = .down
313
- default:
314
- uiOrientation = .up
315
- }
316
-
317
- let snapshot = UIImage(cgImage: cgImage, scale: 1.0, orientation: uiOrientation)
318
- lastDetectedRectangle = DetectedRectangle(observation: observation, snapshot: snapshot)
319
- }
320
274
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scr2em/capacitor-scanner",
3
- "version": "6.0.33",
3
+ "version": "6.0.34",
4
4
  "description": "scan codes",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -29,23 +29,6 @@
29
29
  "plugin",
30
30
  "native"
31
31
  ],
32
- "scripts": {
33
- "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
34
- "verify:ios": "xcodebuild -scheme CapacitorScanner -destination generic/platform=iOS",
35
- "verify:android": "cd android && ./gradlew clean build test && cd ..",
36
- "verify:web": "npm run build",
37
- "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
38
- "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
39
- "eslint": "eslint . --ext ts",
40
- "prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
41
- "swiftlint": "node-swiftlint",
42
- "docgen": "docgen --api CapacitorScannerPlugin --output-readme README.md --output-json dist/docs.json",
43
- "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
44
- "clean": "rimraf ./dist",
45
- "watch": "tsc --watch",
46
- "prepublishOnly": "npm run build",
47
- "prepare": "npm run build"
48
- },
49
32
  "devDependencies": {
50
33
  "@capacitor/android": "6.0.0",
51
34
  "@capacitor/cli": "6.0.0",
@@ -78,5 +61,20 @@
78
61
  "android": {
79
62
  "src": "android"
80
63
  }
64
+ },
65
+ "scripts": {
66
+ "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
67
+ "verify:ios": "xcodebuild -scheme CapacitorScanner -destination generic/platform=iOS",
68
+ "verify:android": "cd android && ./gradlew clean build test && cd ..",
69
+ "verify:web": "npm run build",
70
+ "lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
71
+ "fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
72
+ "eslint": "eslint . --ext ts",
73
+ "prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
74
+ "swiftlint": "node-swiftlint",
75
+ "docgen": "docgen --api CapacitorScannerPlugin --output-readme README.md --output-json dist/docs.json",
76
+ "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
77
+ "clean": "rimraf ./dist",
78
+ "watch": "tsc --watch"
81
79
  }
82
80
  }