From fa18fcea06370c1b5ee08f64b6f259b90cc34e8a Mon Sep 17 00:00:00 2001 From: VincentKobz Date: Wed, 29 May 2024 16:53:09 +0200 Subject: [PATCH] feat: Add function to move and resize the target rectangle on the camera preview --- docs/api/camera.md | 11 +++- .../sdk/camera/CameraScannerProvider.java | 10 ++++ .../sdk/camera/CameraBarcodeScanView.java | 14 +++++ .../sdk/camera/CameraBarcodeScanViewBase.java | 52 +++++++++++++++++++ .../scanner/sdk/camera/CameraProvider.java | 18 +++++++ 5 files changed, 104 insertions(+), 1 deletion(-) diff --git a/docs/api/camera.md b/docs/api/camera.md index 205590e6..9fa5c680 100644 --- a/docs/api/camera.md +++ b/docs/api/camera.md @@ -88,11 +88,20 @@ Pauses the camera's capture. Resumes the camera's capture. ::: -:::{methode} orientationChanged() -> void +:::{method} orientationChanged() -> void Notifies the view that the orientation of the device has changed by calling `setDisplayOrientation()` with the correct clockwise rotation of the camera preview, depending on the device's orientation. + +:::{method} setTargetPosition(float y) -> void + +Set the top target's vertical position on the preview (y coordinate). +::: + +:::{method} setTargetDimension(float width, float height) -> void + +Set the target's dimensions on the preview. ::: :::{method} getLatestSuccessfulScanJpeg() -> byte[] diff --git a/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java b/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java index 76f90342..7e74b145 100644 --- a/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java +++ b/enioka_scan/src/main/java/com/enioka/scanner/sdk/camera/CameraScannerProvider.java @@ -83,4 +83,14 @@ public interface CameraScannerProvider { * Mainly used for devices that are using CameraBarcodeScanViewV1 API. */ public void orientationChanged(View cameraView); + + /** + * Set the top position (in y axis) of the target rectangle. + */ + public void setTargetPosition(View cameraView, float y); + + /** + * Set the dimension of the target rectangle. + */ + public void setTargetDimension(View cameraView, float width, float height); } diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java index 728f2f8d..b19aa22e 100644 --- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java +++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanView.java @@ -201,6 +201,20 @@ public void orientationChanged() { this.proxiedView.orientationChanged(); } + /** + * Set the top position (in y axis) of the target rectangle. + */ + public void setTargetPosition(float y) { + this.proxiedView.setTargetPosition(y); + } + + /** + * Set the dimension of the target rectangle. + */ + public void setTargetDimension(float width, float height) { + this.proxiedView.setTargetDimension(width, height); + } + /** * Get the JPEG data of the image used in the latest successful scan. * diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java index e84a635f..040e37f1 100644 --- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java +++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraBarcodeScanViewBase.java @@ -318,6 +318,58 @@ protected void computeCropRectangle() { Log.i(TAG, "The preview surface view is at (top, left, bottom, right) " + camPreviewSurfaceView.getTop() + "," + camPreviewSurfaceView.getLeft() + " - " + camPreviewSurfaceView.getBottom() + "," + camPreviewSurfaceView.getRight()); } + /** + * Set the top position (in y axis) of the target rectangle. + * Automatically refreshes the autofocus zone. + */ + public void setTargetPosition(float y) { + float newTop = y; + float newBottom = y + cropRect.height(); + + if (newTop < 0 || newBottom > camPreviewSurfaceView.getHeight()) { + Log.i(TAG, "Targeting rectangle moved outside the preview surface, ignoring"); + return; + } + + cropRect.top = (int) newTop; + cropRect.bottom = (int) newBottom; + + final FrameLayout.LayoutParams prms = (LayoutParams) targetView.getLayoutParams(); + prms.topMargin = cropRect.top; + targetView.setLayoutParams(prms); + } + + /** + * Set the dimensions of the target rectangle. + */ + public void setTargetDimension(float width, float height) { + cropRect.left = (int) (camPreviewSurfaceView.getMeasuredWidth() / 2 - width / 2); + cropRect.right = (int) (camPreviewSurfaceView.getMeasuredWidth() / 2 + width / 2); + + int newTop = cropRect.top + cropRect.height() / 2 - (int) (height / 2); + + if (newTop < 0) { + newTop = 0; + } + + int newBottom = newTop + (int) height; + + if (newBottom > camPreviewSurfaceView.getHeight()) { + newBottom = camPreviewSurfaceView.getHeight(); + Log.i(TAG, "Dimension of targeting rectangle is too large, ignoring"); + } + + cropRect.top = newTop; + cropRect.bottom = newBottom; + + final FrameLayout.LayoutParams prms = (LayoutParams) targetView.getLayoutParams(); + prms.height = (int) height; + prms.width = (int) width; + prms.setMargins(cropRect.left, cropRect.top, 0, 0); + + targetView.setLayoutParams(prms); + } + /** * Adds the targeting view to layout. Must be called after computeCropRectangle was called. Separate from computeCropRectangle * because: we want to add this view last, in order to put it on top. (and we need to calculate the crop rectangle early). diff --git a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java index 3d27a4db..801b2ec4 100644 --- a/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java +++ b/enioka_scan_camera/src/main/java/com/enioka/scanner/sdk/camera/CameraProvider.java @@ -112,4 +112,22 @@ public void orientationChanged(View cameraView) { throw new IllegalArgumentException("cameraView must be an instance of CameraBarcodeScanView"); } } + + @Override + public void setTargetPosition(View cameraView, float y) { + if (cameraView instanceof CameraBarcodeScanView) { + ((CameraBarcodeScanView) cameraView).setTargetPosition(y); + } else { + throw new IllegalArgumentException("cameraView must be an instance of CameraBarcodeScanView"); + } + } + + @Override + public void setTargetDimension(View cameraView, float width, float height) { + if (cameraView instanceof CameraBarcodeScanView) { + ((CameraBarcodeScanView) cameraView).setTargetDimension(width, height); + } else { + throw new IllegalArgumentException("cameraView must be an instance of CameraBarcodeScanView"); + } + } }