@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 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&lt;<a href="#capturephotoresult">CapturePhotoResult</a>&gt;</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
- byte[] bytes = outputStream.toByteArray();
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
- String base64 = Base64.encodeToString(bytes, Base64.NO_WRAP);
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
- echo("Failed to close output stream: " + e.getMessage());
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":"AA2BA,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(): 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 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}"]}
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
- let photoSettings = AVCapturePhotoSettings()
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scr2em/capacitor-scanner",
3
- "version": "6.0.7",
3
+ "version": "6.0.8",
4
4
  "description": "scan codes",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",