@scr2em/capacitor-scanner 6.0.7 → 6.0.8
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 +12 -3
- package/android/src/main/java/com/leadliaion/capacitorscanner/CapacitorScannerPlugin.java +48 -4
- package/dist/docs.json +21 -3
- package/dist/esm/definitions.d.ts +9 -1
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/CapacitorScannerPlugin/CapacitorScannerPlugin.swift +18 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ npx cap sync
|
|
|
16
16
|
* [`startScanning(...)`](#startscanning)
|
|
17
17
|
* [`stopScanning()`](#stopscanning)
|
|
18
18
|
* [`openSettings()`](#opensettings)
|
|
19
|
-
* [`capturePhoto()`](#capturephoto)
|
|
19
|
+
* [`capturePhoto(...)`](#capturephoto)
|
|
20
20
|
* [`checkPermissions()`](#checkpermissions)
|
|
21
21
|
* [`requestPermissions()`](#requestpermissions)
|
|
22
22
|
* [`flipCamera()`](#flipcamera)
|
|
@@ -62,12 +62,16 @@ openSettings() => Promise<void>
|
|
|
62
62
|
--------------------
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
### capturePhoto()
|
|
65
|
+
### capturePhoto(...)
|
|
66
66
|
|
|
67
67
|
```typescript
|
|
68
|
-
capturePhoto() => Promise<CapturePhotoResult>
|
|
68
|
+
capturePhoto(options?: CapturePhotoOptions | undefined) => Promise<CapturePhotoResult>
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
+
| Param | Type |
|
|
72
|
+
| ------------- | ------------------------------------------------------------------- |
|
|
73
|
+
| **`options`** | <code><a href="#capturephotooptions">CapturePhotoOptions</a></code> |
|
|
74
|
+
|
|
71
75
|
**Returns:** <code>Promise<<a href="#capturephotoresult">CapturePhotoResult</a>></code>
|
|
72
76
|
|
|
73
77
|
--------------------
|
|
@@ -151,6 +155,11 @@ removeAllListeners() => Promise<void>
|
|
|
151
155
|
<code>{ imageBase64: string }</code>
|
|
152
156
|
|
|
153
157
|
|
|
158
|
+
#### CapturePhotoOptions
|
|
159
|
+
|
|
160
|
+
<code>{ /** * The desired quality of the captured image, expressed as a value between 0.0 (lowest quality, smallest file size) * and 1.0 (highest quality, largest file size). Defaults to 1.0. * This parameter directly influences the compression level of the resulting JPEG image. */ qualityRatio?: number; }</code>
|
|
161
|
+
|
|
162
|
+
|
|
154
163
|
#### PermissionsResult
|
|
155
164
|
|
|
156
165
|
<code>{ camera: 'prompt' | 'denied' | 'granted' }</code>
|
|
@@ -3,6 +3,8 @@ package com.leadliaion.capacitorscanner;
|
|
|
3
3
|
import android.Manifest;
|
|
4
4
|
import android.content.Intent;
|
|
5
5
|
import android.content.pm.PackageManager;
|
|
6
|
+
import android.graphics.Bitmap;
|
|
7
|
+
import android.graphics.BitmapFactory;
|
|
6
8
|
import android.graphics.Color;
|
|
7
9
|
import android.net.Uri;
|
|
8
10
|
import android.provider.Settings;
|
|
@@ -390,6 +392,12 @@ public class CapacitorScannerPlugin extends Plugin {
|
|
|
390
392
|
return;
|
|
391
393
|
}
|
|
392
394
|
|
|
395
|
+
// Ratio must be between 0 and 1, where 0 or 1 means no reduction.
|
|
396
|
+
Double qualityRatioObj = call.getDouble("qualityRatio", 1.0);
|
|
397
|
+
double qualityRatio = qualityRatioObj != null ? qualityRatioObj : 1.0;
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
// Temporary stream to receive the captured image data.
|
|
393
401
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
394
402
|
|
|
395
403
|
ImageCapture.OutputFileOptions outputOptions =
|
|
@@ -400,13 +408,45 @@ public class CapacitorScannerPlugin extends Plugin {
|
|
|
400
408
|
@Override
|
|
401
409
|
public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
|
|
402
410
|
try {
|
|
403
|
-
|
|
411
|
+
// Get the original image bytes.
|
|
412
|
+
byte[] originalBytes = outputStream.toByteArray();
|
|
413
|
+
int originalSize = originalBytes.length; // in bytes
|
|
414
|
+
|
|
415
|
+
// If qualityRatio is between 0 and 1 exclusively, perform quality reduction.
|
|
416
|
+
if (qualityRatio > 0 && qualityRatio < 1) {
|
|
417
|
+
// Calculate the target size in bytes.
|
|
418
|
+
int targetSize = (int) (originalSize * qualityRatio);
|
|
419
|
+
|
|
420
|
+
// Decode the captured image into a Bitmap.
|
|
421
|
+
Bitmap originalBitmap = BitmapFactory.decodeByteArray(originalBytes, 0, originalSize);
|
|
422
|
+
if (originalBitmap == null) {
|
|
423
|
+
call.reject("Failed to decode captured image.");
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
404
426
|
|
|
405
|
-
|
|
427
|
+
// Prepare a stream to hold the compressed bitmap.
|
|
428
|
+
ByteArrayOutputStream compressedStream = new ByteArrayOutputStream();
|
|
429
|
+
int quality = 100; // start with maximum quality (100)
|
|
406
430
|
|
|
431
|
+
// Iteratively compress the bitmap until it reaches the target file size.
|
|
432
|
+
do {
|
|
433
|
+
compressedStream.reset();
|
|
434
|
+
originalBitmap.compress(Bitmap.CompressFormat.JPEG, quality, compressedStream);
|
|
435
|
+
quality -= 5; // Lower the quality step by step.
|
|
436
|
+
} while (compressedStream.toByteArray().length > targetSize && quality > 10);
|
|
437
|
+
|
|
438
|
+
// Use the compressed image bytes.
|
|
439
|
+
originalBytes = compressedStream.toByteArray();
|
|
440
|
+
|
|
441
|
+
// Cleanup: recycle the bitmap and close the compressed stream.
|
|
442
|
+
originalBitmap.recycle();
|
|
443
|
+
compressedStream.close();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Convert the final image bytes to a Base64 string.
|
|
447
|
+
String base64 = Base64.encodeToString(originalBytes, Base64.NO_WRAP);
|
|
407
448
|
JSObject ret = new JSObject();
|
|
408
449
|
ret.put("imageBase64", "data:image/jpeg;base64," + base64);
|
|
409
|
-
|
|
410
450
|
call.resolve(ret);
|
|
411
451
|
} catch (Exception e) {
|
|
412
452
|
call.reject("Failed to process image: " + e.getMessage());
|
|
@@ -426,13 +466,17 @@ public class CapacitorScannerPlugin extends Plugin {
|
|
|
426
466
|
try {
|
|
427
467
|
outputStream.close();
|
|
428
468
|
} catch (IOException e) {
|
|
429
|
-
|
|
469
|
+
echo("Failed to close output stream: " + e.getMessage());
|
|
430
470
|
}
|
|
431
471
|
}
|
|
432
472
|
});
|
|
433
473
|
}
|
|
434
474
|
|
|
435
475
|
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
436
480
|
@PluginMethod
|
|
437
481
|
public void checkPermissions(PluginCall call) {
|
|
438
482
|
PermissionState cameraPermState = getPermissionState("camera");
|
package/dist/docs.json
CHANGED
|
@@ -45,13 +45,20 @@
|
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"name": "capturePhoto",
|
|
48
|
-
"signature": "() => Promise<CapturePhotoResult>",
|
|
49
|
-
"parameters": [
|
|
48
|
+
"signature": "(options?: CapturePhotoOptions | undefined) => Promise<CapturePhotoResult>",
|
|
49
|
+
"parameters": [
|
|
50
|
+
{
|
|
51
|
+
"name": "options",
|
|
52
|
+
"docs": "",
|
|
53
|
+
"type": "CapturePhotoOptions | undefined"
|
|
54
|
+
}
|
|
55
|
+
],
|
|
50
56
|
"returns": "Promise<CapturePhotoResult>",
|
|
51
57
|
"tags": [],
|
|
52
58
|
"docs": "",
|
|
53
59
|
"complexTypes": [
|
|
54
|
-
"CapturePhotoResult"
|
|
60
|
+
"CapturePhotoResult",
|
|
61
|
+
"CapturePhotoOptions"
|
|
55
62
|
],
|
|
56
63
|
"slug": "capturephoto"
|
|
57
64
|
},
|
|
@@ -237,6 +244,17 @@
|
|
|
237
244
|
}
|
|
238
245
|
]
|
|
239
246
|
},
|
|
247
|
+
{
|
|
248
|
+
"name": "CapturePhotoOptions",
|
|
249
|
+
"slug": "capturephotooptions",
|
|
250
|
+
"docs": "",
|
|
251
|
+
"types": [
|
|
252
|
+
{
|
|
253
|
+
"text": "{\n /**\n * The desired quality of the captured image, expressed as a value between 0.0 (lowest quality, smallest file size)\n * and 1.0 (highest quality, largest file size). Defaults to 1.0.\n * This parameter directly influences the compression level of the resulting JPEG image.\n */\n qualityRatio?: number;\n}",
|
|
254
|
+
"complexTypes": []
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
},
|
|
240
258
|
{
|
|
241
259
|
"name": "PermissionsResult",
|
|
242
260
|
"slug": "permissionsresult",
|
|
@@ -2,7 +2,7 @@ export interface CapacitorScannerPlugin {
|
|
|
2
2
|
startScanning(options?: ScannerOptions): Promise<void>;
|
|
3
3
|
stopScanning(): Promise<void>;
|
|
4
4
|
openSettings(): Promise<void>;
|
|
5
|
-
capturePhoto(): Promise<CapturePhotoResult>;
|
|
5
|
+
capturePhoto(options?: CapturePhotoOptions): Promise<CapturePhotoResult>;
|
|
6
6
|
checkPermissions(): Promise<PermissionsResult>;
|
|
7
7
|
requestPermissions(): Promise<PermissionsResult>;
|
|
8
8
|
flipCamera(): Promise<void>;
|
|
@@ -19,6 +19,14 @@ export declare type BarcodeScannedEvent = {
|
|
|
19
19
|
scannedCode: string;
|
|
20
20
|
format: string;
|
|
21
21
|
};
|
|
22
|
+
export declare type CapturePhotoOptions = {
|
|
23
|
+
/**
|
|
24
|
+
* The desired quality of the captured image, expressed as a value between 0.0 (lowest quality, smallest file size)
|
|
25
|
+
* and 1.0 (highest quality, largest file size). Defaults to 1.0.
|
|
26
|
+
* This parameter directly influences the compression level of the resulting JPEG image.
|
|
27
|
+
*/
|
|
28
|
+
qualityRatio?: number;
|
|
29
|
+
};
|
|
22
30
|
export declare type PermissionsResult = {
|
|
23
31
|
camera: 'prompt' | 'denied' | 'granted';
|
|
24
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAoCA,MAAM,CAAN,IAAY,aAYX;AAZD,WAAY,aAAa;IACvB,gCAAe,CAAA;IACf,mCAAkB,CAAA;IAClB,mCAAkB,CAAA;IAClB,qCAAoB,CAAA;IACpB,2CAA0B,CAAA;IAC1B,+BAAc,CAAA;IACd,iCAAgB,CAAA;IAChB,gCAAe,CAAA;IACf,mCAAkB,CAAA;IAClB,mCAAkB,CAAA;IAClB,+BAAc,CAAA;AAChB,CAAC,EAZW,aAAa,KAAb,aAAa,QAYxB","sourcesContent":["export interface CapacitorScannerPlugin {\n startScanning(options?: ScannerOptions): Promise<void>;\n stopScanning(): Promise<void>;\n openSettings(): Promise<void>;\n capturePhoto(options?: CapturePhotoOptions): Promise<CapturePhotoResult>;\n checkPermissions(): Promise<PermissionsResult>;\n requestPermissions(): Promise<PermissionsResult>;\n flipCamera(): Promise<void>;\n toggleFlash(): Promise<FlashResult>;\n addListener(event: 'barcodeScanned', listenerFunc: (result: BarcodeScannedEvent) => void): Promise<void>;\n removeAllListeners(): Promise<void>;\n}\n\nexport type ScannerOptions = {\n formats?: BarcodeFormat[];\n cameraDirection?: 'BACK' | 'FRONT';\n debounceTimeInMilli?: number\n};\n\nexport type BarcodeScannedEvent = { scannedCode: string; format: string };\n\nexport type CapturePhotoOptions = {\n /**\n * The desired quality of the captured image, expressed as a value between 0.0 (lowest quality, smallest file size)\n * and 1.0 (highest quality, largest file size). Defaults to 1.0.\n * This parameter directly influences the compression level of the resulting JPEG image.\n */\n qualityRatio?: number;\n};\n\nexport type PermissionsResult = { camera: 'prompt' | 'denied' | 'granted' };\n\nexport type CapturePhotoResult = { imageBase64: string };\n\nexport type FlashResult = { enabled: boolean };\n\nexport enum BarcodeFormat {\n Aztec = 'AZTEC',\n Code39 = 'CODE_39',\n Code93 = 'CODE_93',\n Code128 = 'CODE_128',\n DataMatrix = 'DATA_MATRIX',\n Ean8 = 'EAN_8',\n Ean13 = 'EAN_13',\n Itf14 = 'ITF14',\n Pdf417 = 'PDF_417',\n QrCode = 'QR_CODE',\n UpcE = 'UPC_E',\n}\n\ndeclare global {\n interface PluginRegistry {\n QRScanner: CapacitorScannerPlugin;\n }\n}"]}
|
|
@@ -56,7 +56,24 @@ public class CapacitorScannerPlugin: CAPPlugin, CAPBridgedPlugin, AVCaptureMetad
|
|
|
56
56
|
return
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
// Get quality ratio from options, default to 1.0, clamp between 0.0 and 1.0
|
|
60
|
+
let quality = call.getFloat("qualityRatio", 1.0)
|
|
61
|
+
let clampedQuality = max(0.0, min(1.0, quality))
|
|
62
|
+
let qualityNumber = NSNumber(value: clampedQuality) // Convert to NSNumber
|
|
63
|
+
|
|
64
|
+
var photoSettings = AVCapturePhotoSettings() // Initialize with default settings
|
|
65
|
+
|
|
66
|
+
// Check if JPEG is supported and apply compression settings if it is
|
|
67
|
+
if photoOutput.supportedPhotoCodecTypes(for: .jpg).contains(.jpeg) {
|
|
68
|
+
// Create settings specific for JPEG with quality
|
|
69
|
+
photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg, // Use the type directly
|
|
70
|
+
AVVideoCompressionPropertiesKey: [AVVideoQualityKey: qualityNumber]])
|
|
71
|
+
photoSettings.photoQualityPrioritization = .quality // Prioritize quality
|
|
72
|
+
} else {
|
|
73
|
+
print("JPEG codec not supported for photo capture. Using default settings.")
|
|
74
|
+
// photoSettings remains the default initialized one
|
|
75
|
+
}
|
|
76
|
+
|
|
60
77
|
self.capturePhotoCall = call
|
|
61
78
|
photoOutput.capturePhoto(with: photoSettings, delegate: self)
|
|
62
79
|
}
|