capacitor-camera-view 2.0.1 → 2.1.0
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.
- package/README.md +19 -9
- package/android/build.gradle +8 -5
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraView.kt +217 -126
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/CameraViewPlugin.kt +70 -30
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/CameraResult.kt +47 -0
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/model/CameraSessionConfiguration.kt +11 -1
- package/android/src/main/java/com/michaelwolz/capacitorcameraview/utils.kt +94 -5
- package/dist/docs.json +81 -0
- package/dist/esm/definitions.d.ts +44 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +7 -1
- package/dist/esm/web.js +67 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +68 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +68 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CameraViewPlugin/CameraError.swift +97 -2
- package/ios/Sources/CameraViewPlugin/CameraEvents.swift +109 -0
- package/ios/Sources/CameraViewPlugin/CameraSessionConfiguration.swift +29 -2
- package/ios/Sources/CameraViewPlugin/CameraViewManager+BarcodeScan.swift +30 -41
- package/ios/Sources/CameraViewPlugin/CameraViewManager+PhotoCapture.swift +45 -13
- package/ios/Sources/CameraViewPlugin/CameraViewManager+VideoDataOutput.swift +4 -3
- package/ios/Sources/CameraViewPlugin/CameraViewManager.swift +193 -59
- package/ios/Sources/CameraViewPlugin/CameraViewPlugin.swift +83 -84
- package/ios/Sources/CameraViewPlugin/TempFileManager.swift +181 -0
- package/ios/Sources/CameraViewPlugin/Utils.swift +102 -0
- package/package.json +17 -17
|
@@ -5,39 +5,34 @@ extension CameraViewManager: AVCaptureMetadataOutputObjectsDelegate {
|
|
|
5
5
|
/// Set up metadata output for the capture session in case it's not configured yet
|
|
6
6
|
/// Make sure to call `captureSession.beginConfiguration` before calling this
|
|
7
7
|
///
|
|
8
|
+
/// - Parameter barcodeTypes: Optional array of specific barcode types to detect.
|
|
9
|
+
/// If nil, all supported types are detected (backwards compatible).
|
|
8
10
|
/// - Throws: An error if the output cannot be set.
|
|
9
|
-
internal func setupMetadataOutput() throws {
|
|
10
|
-
let
|
|
11
|
+
internal func setupMetadataOutput(barcodeTypes: [AVMetadataObject.ObjectType]? = nil) throws {
|
|
12
|
+
let requestedBarcodeTypes = barcodeTypes ?? ALL_SUPPORTED_BARCODE_TYPES
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
// Nothing todo, we already have an output
|
|
14
|
-
return
|
|
15
|
-
}
|
|
14
|
+
let metadataOutput: AVCaptureMetadataOutput
|
|
16
15
|
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
}
|
|
16
|
+
if let existingOutput = captureSession.outputs.first(where: { $0 is AVCaptureMetadataOutput }) as? AVCaptureMetadataOutput {
|
|
17
|
+
metadataOutput = existingOutput
|
|
18
|
+
} else {
|
|
19
|
+
let newOutput = AVCaptureMetadataOutput()
|
|
20
|
+
if !captureSession.canAddOutput(newOutput) {
|
|
21
|
+
throw CameraError.outputAdditionFailed
|
|
22
|
+
}
|
|
20
23
|
|
|
21
|
-
|
|
24
|
+
captureSession.addOutput(newOutput)
|
|
25
|
+
newOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
|
|
26
|
+
metadataOutput = newOutput
|
|
27
|
+
}
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
let supportedTypes = Set(metadataOutput.availableMetadataObjectTypes)
|
|
30
|
+
let resolvedTypes = requestedBarcodeTypes.filter { supportedTypes.contains($0) }
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
.code39,
|
|
30
|
-
.code39Mod43,
|
|
31
|
-
.code93,
|
|
32
|
-
.ean8,
|
|
33
|
-
.ean13,
|
|
34
|
-
.interleaved2of5,
|
|
35
|
-
.itf14,
|
|
36
|
-
.pdf417,
|
|
37
|
-
.aztec,
|
|
38
|
-
.dataMatrix,
|
|
39
|
-
.upce
|
|
40
|
-
]
|
|
32
|
+
if metadataOutput.metadataObjectTypes != resolvedTypes {
|
|
33
|
+
// Update the metadata output with the resolved types only if they differ from the current configuration
|
|
34
|
+
metadataOutput.metadataObjectTypes = resolvedTypes
|
|
35
|
+
}
|
|
41
36
|
}
|
|
42
37
|
|
|
43
38
|
/// Remove the metadata output if in case it is already configured, e.g. because
|
|
@@ -80,21 +75,15 @@ extension CameraViewManager: AVCaptureMetadataOutputObjectsDelegate {
|
|
|
80
75
|
return
|
|
81
76
|
}
|
|
82
77
|
|
|
83
|
-
let boundingRect
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
78
|
+
let boundingRect = BarcodeDetectedEvent.BoundingRect(
|
|
79
|
+
x: Double(transformedMetadataObject.bounds.origin.x),
|
|
80
|
+
y: Double(transformedMetadataObject.bounds.origin.y),
|
|
81
|
+
width: Double(transformedMetadataObject.bounds.width),
|
|
82
|
+
height: Double(transformedMetadataObject.bounds.height)
|
|
83
|
+
)
|
|
89
84
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
object: nil,
|
|
93
|
-
userInfo: [
|
|
94
|
-
"value": barcodeValue,
|
|
95
|
-
"type": barcodeType,
|
|
96
|
-
"boundingRect": boundingRect
|
|
97
|
-
]
|
|
85
|
+
eventEmitter.emitBarcodeDetected(
|
|
86
|
+
BarcodeDetectedEvent(value: barcodeValue, type: barcodeType, boundingRect: boundingRect)
|
|
98
87
|
)
|
|
99
88
|
}
|
|
100
89
|
}
|
|
@@ -13,19 +13,22 @@ extension CameraViewManager: AVCapturePhotoCaptureDelegate {
|
|
|
13
13
|
// use outputs for taking photos here we don't need a new one
|
|
14
14
|
return
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
// Balanced should be a good choice for most use cases
|
|
18
18
|
avPhotoOutput.maxPhotoQualityPrioritization = .balanced
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
if !captureSession.canAddOutput(avPhotoOutput) {
|
|
21
21
|
throw CameraError.outputAdditionFailed
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
captureSession.addOutput(avPhotoOutput)
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
/// Delegate method called when a photo has been captured via `AVCapturePhotoCaptureDelegate`
|
|
28
28
|
///
|
|
29
|
+
/// This method handles both the legacy UIImage-based callback and the optimized Data-based
|
|
30
|
+
/// callback to eliminate double JPEG encoding when possible.
|
|
31
|
+
///
|
|
29
32
|
/// - Parameters:
|
|
30
33
|
/// - output: The photo output that captured the photo.
|
|
31
34
|
/// - photo: The captured photo.
|
|
@@ -35,17 +38,46 @@ extension CameraViewManager: AVCapturePhotoCaptureDelegate {
|
|
|
35
38
|
didFinishProcessingPhoto photo: AVCapturePhoto,
|
|
36
39
|
error: Error?
|
|
37
40
|
) {
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
// Handle optimized Data-based callback first (avoids double encoding)
|
|
42
|
+
if let dataHandler = photoDataCaptureHandler {
|
|
43
|
+
photoDataCaptureHandler = nil
|
|
44
|
+
|
|
45
|
+
if let error = error {
|
|
46
|
+
dataHandler(nil, error)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
guard let data = photo.fileDataRepresentation() else {
|
|
51
|
+
dataHandler(nil, CameraError.photoOutputError)
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
dataHandler(data, nil)
|
|
40
56
|
return
|
|
41
57
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
58
|
+
|
|
59
|
+
// Handle legacy UIImage-based callback
|
|
60
|
+
if let imageHandler = photoCaptureHandler {
|
|
61
|
+
photoCaptureHandler = nil
|
|
62
|
+
|
|
63
|
+
if let error = error {
|
|
64
|
+
imageHandler(nil, error)
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
guard let data = photo.fileDataRepresentation() else {
|
|
69
|
+
imageHandler(nil, CameraError.photoOutputError)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
guard let image = UIImage(data: data) else {
|
|
74
|
+
imageHandler(nil, CameraError.photoOutputError)
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
imageHandler(image, nil)
|
|
46
79
|
}
|
|
47
|
-
|
|
48
|
-
photoCaptureHandler?(image, nil)
|
|
49
80
|
}
|
|
50
|
-
|
|
81
|
+
|
|
51
82
|
}
|
|
83
|
+
|
|
@@ -33,7 +33,8 @@ extension CameraViewManager: AVCaptureVideoDataOutputSampleBufferDelegate {
|
|
|
33
33
|
captureSession.addOutput(avVideoDataOutput)
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/// Capture a snapshot from the camera feed
|
|
36
|
+
/// Capture a snapshot from the camera feed using the shared Metal-backed CIContext.
|
|
37
|
+
/// Using a shared CIContext eliminates the ~80% CPU overhead of creating one per frame.
|
|
37
38
|
public func captureOutput(
|
|
38
39
|
_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer,
|
|
39
40
|
from connection: AVCaptureConnection
|
|
@@ -52,8 +53,8 @@ extension CameraViewManager: AVCaptureVideoDataOutputSampleBufferDelegate {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
let ciImage = CIImage(cvPixelBuffer: imageBuffer)
|
|
55
|
-
|
|
56
|
-
guard let cgImage =
|
|
56
|
+
// Use the shared Metal-backed CIContext for efficient rendering
|
|
57
|
+
guard let cgImage = CameraViewManager.sharedCIContext.createCGImage(ciImage, from: ciImage.extent) else {
|
|
57
58
|
completionHandler(nil, CameraError.frameCaptureError)
|
|
58
59
|
return
|
|
59
60
|
}
|