?, screenSize: Size): Boolean {
+ if (points != null) {
+ val shortSide = min(distance(points[0], points[1]), distance(points[0], points[3]))
+ val largeSide = max(distance(points[0], points[1]), distance(points[0], points[3]))
+ val screenShortSide = min(screenSize.width, screenSize.height).toFloat()
+ val screenLargeSide = max(screenSize.width, screenSize.height).toFloat()
+
+ if (shortSide > 0.75 * screenShortSide || largeSide > 0.75 * screenLargeSide) {
+ return true
+ }
+ }
+ return false
+ }
+
+ private fun distance(pointA: Point, pointB: Point): Float {
+ return sqrt( (pointA.x - pointB.x).toFloat().pow(2) + (pointA.y - pointB.y).toFloat().pow(2))
+ }
+
/**
* Conversion from screen rotation to JPEG orientation.
*/
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSource.java b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSource.java
index 5edf376..14e4786 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSource.java
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSource.java
@@ -18,7 +18,6 @@
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
-
import com.google.android.gms.common.images.Size;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.Frame;
@@ -330,15 +329,8 @@ public DocumentCameraSource start() throws IOException {
mCamera = createCamera();
- // SurfaceTexture was introduced in Honeycomb (11), so if we are running and
- // old version of Android. fall back to use SurfaceView.
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- mDummySurfaceTexture = new SurfaceTexture(DUMMY_TEXTURE_NAME);
- mCamera.setPreviewTexture(mDummySurfaceTexture);
- } else {
- mDummySurfaceView = new SurfaceView(mContext);
- mCamera.setPreviewDisplay(mDummySurfaceView.getHolder());
- }
+ mDummySurfaceTexture = new SurfaceTexture(DUMMY_TEXTURE_NAME);
+ mCamera.setPreviewTexture(mDummySurfaceTexture);
mCamera.startPreview();
mProcessingThread = new Thread(mFrameProcessor);
@@ -348,15 +340,8 @@ public DocumentCameraSource start() throws IOException {
return this;
}
- /**
- * Opens the camera and starts sending preview frames to the underlying detector. The supplied
- * surface holder is used for the preview so frames can be displayed to the user.
- *
- * @param surfaceHolder the surface holder to use for the preview frames
- * @throws IOException if the supplied surface holder could not be used as the preview display
- */
@RequiresPermission(Manifest.permission.CAMERA)
- public DocumentCameraSource start(SurfaceHolder surfaceHolder) throws IOException {
+ public DocumentCameraSource start(SurfaceHolder surfaceHolder, DocumentCameraSourcePreview preview) throws IOException {
synchronized (mCameraLock) {
if (mCamera != null) {
return this;
@@ -371,9 +356,15 @@ public DocumentCameraSource start(SurfaceHolder surfaceHolder) throws IOExceptio
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
+ if (preview != null) {
+ preview.requestLayout();
+ }
+
mProcessingThread = new Thread(mFrameProcessor);
mFrameProcessor.setActive(true);
mProcessingThread.start();
+
+
}
return this;
}
@@ -382,7 +373,7 @@ public DocumentCameraSource start(SurfaceHolder surfaceHolder) throws IOExceptio
* Closes the camera and stops sending frames to the underlying frame detector.
*
* This camera source may be restarted again by calling {@link #start()} or
- * {@link #start(SurfaceHolder)}.
+ * {@link #start(SurfaceHolder, DocumentCameraSourcePreview)}.
*
* Call {@link #release()} instead to completely shut down this camera source and release the
* resources of the underlying detector.
@@ -409,17 +400,7 @@ public void stop() {
mCamera.stopPreview();
mCamera.setPreviewCallbackWithBuffer(null);
try {
- // We want to be compatible back to Gingerbread, but SurfaceTexture
- // wasn't introduced until Honeycomb. Since the interface cannot use a SurfaceTexture, if the
- // developer wants to display a preview we must use a SurfaceHolder. If the developer doesn't
- // want to display a preview we use a SurfaceTexture if we are running at least Honeycomb.
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- mCamera.setPreviewTexture(null);
-
- } else {
- mCamera.setPreviewDisplay(null);
- }
+ mCamera.setPreviewTexture(null);
} catch (Exception e) {
Log.e(TAG, "Failed to clear camera preview: " + e);
}
@@ -479,7 +460,7 @@ public int doZoom(float scale) {
/**
* Initiates taking a picture, which happens asynchronously. The camera source should have been
- * activated previously with {@link #start()} or {@link #start(SurfaceHolder)}. The camera
+ * activated previously with {@link #start()} or {@link #start(SurfaceHolder, DocumentCameraSourcePreview)}. The camera
* preview is suspended while the picture is being taken, but will resume once picture taking is
* done.
*
@@ -584,7 +565,7 @@ public boolean setFlashMode(@FlashMode String mode) {
/**
* Starts camera auto-focus and registers a callback function to run when
* the camera is focused. This method is only valid when preview is active
- * (between {@link #start()} or {@link #start(SurfaceHolder)} and before {@link #stop()} or {@link #release()}).
+ * (between {@link #start()} or {@link #start(SurfaceHolder, DocumentCameraSourcePreview)} and before {@link #stop()} or {@link #release()}).
*
* Callers should check
* {@link #getFocusMode()} to determine if
@@ -794,6 +775,8 @@ private Camera createCamera() {
camera.setParameters(parameters);
+
+
// Four frame buffers are needed for working with the camera:
//
// one for the frame that is currently being executed upon in doing detection
@@ -825,6 +808,41 @@ private static int getIdForRequestedCamera(int facing) {
return -1;
}
+// private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
+// List validPreviewSizes = generateValidPreviewSizeList(camera);
+// // The method for selecting the best size is to minimize the sum of the differences between
+// // the desired values and the actual values for width and height. This is certainly not the
+// // only way to select the best size, but it provides a decent tradeoff between using the
+// // closest aspect ratio vs. using the closest pixel area.
+// SizePair selectedPair = null;
+// int maxArea = Integer.MIN_VALUE;
+// int maxPict = Integer.MIN_VALUE;
+// int area = Integer.MIN_VALUE;
+// for (SizePair sizePair : validPreviewSizes) {
+// Size size_pict = sizePair.pictureSize();
+// int newArea = size_pict.getWidth()*size_pict.getHeight();
+// if (newArea > maxPict) {
+// maxPict = newArea;
+// maxArea = Integer.MIN_VALUE;
+// Size size = sizePair.previewSize();
+// area = size.getWidth()*size.getHeight();
+// if (maxArea < area) {
+// selectedPair = sizePair;
+// maxArea = area;
+// }
+// }
+// else if (newArea == maxPict) {
+// Size size = sizePair.previewSize();
+// area = size.getWidth()*size.getHeight();
+// if (maxArea < area) {
+// selectedPair = sizePair;
+// maxArea = area;
+// }
+// }
+// }
+// return selectedPair;
+// }
+
/**
* Selects the most suitable preview and picture size, given the desired width and height.
*
@@ -838,9 +856,11 @@ private static int getIdForRequestedCamera(int facing) {
* @param desiredHeight the desired height of the camera preview frames
* @return the selected preview and picture size pair
*/
- /*private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
+ private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
List validPreviewSizes = generateValidPreviewSizeList(camera);
-
+ long expectedSize = desiredWidth*desiredHeight;
+ int desiredShortSide = Math.min(desiredHeight, desiredWidth);
+ int desiredLongSide = Math.max(desiredHeight, desiredWidth);
// The method for selecting the best size is to minimize the sum of the differences between
// the desired values and the actual values for width and height. This is certainly not the
// only way to select the best size, but it provides a decent tradeoff between using the
@@ -849,52 +869,57 @@ private static int getIdForRequestedCamera(int facing) {
int minDiff = Integer.MAX_VALUE;
for (SizePair sizePair : validPreviewSizes) {
Size size = sizePair.previewSize();
- int diff = Math.abs(size.getWidth() - desiredWidth) +
- Math.abs(size.getHeight() - desiredHeight);
- if (diff < minDiff) {
+
+
+ int currentShortSide = Math.min(size.getWidth(), size.getHeight());
+ int currentLongSide = Math.max(size.getWidth(), size.getHeight());
+ float change = Math.min(Math.min((float) desiredShortSide / currentShortSide, (float) desiredLongSide / currentLongSide), 2f);
+ currentLongSide *= change;
+ currentShortSide *= change;
+
+
+ int diff = Math.abs(currentShortSide - desiredShortSide) +
+ Math.abs(currentLongSide - desiredLongSide);
+ if ((!(currentLongSide > desiredLongSide) && !(currentShortSide > desiredShortSide)) && diff < minDiff && (sizePair.pictureSize().getWidth()*sizePair.pictureSize().getHeight() >= expectedSize * 0.6f)) {
selectedPair = sizePair;
minDiff = diff;
}
}
- return selectedPair;
- }*/
-
- private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
- List validPreviewSizes = generateValidPreviewSizeList(camera);
- // The method for selecting the best size is to minimize the sum of the differences between
- // the desired values and the actual values for width and height. This is certainly not the
- // only way to select the best size, but it provides a decent tradeoff between using the
- // closest aspect ratio vs. using the closest pixel area.
- SizePair selectedPair = null;
- int maxArea = Integer.MIN_VALUE;
- int maxPict = Integer.MIN_VALUE;
- int area = Integer.MIN_VALUE;
- for (SizePair sizePair : validPreviewSizes) {
- Size size_pict = sizePair.pictureSize();
- int newArea = size_pict.getWidth()*size_pict.getHeight();
- if (newArea > maxPict) {
- maxPict = newArea;
- maxArea = Integer.MIN_VALUE;
- Size size = sizePair.previewSize();
- area = size.getWidth()*size.getHeight();
- if (maxArea < area) {
- selectedPair = sizePair;
- maxArea = area;
- }
- }
- else if (newArea == maxPict) {
- Size size = sizePair.previewSize();
- area = size.getWidth()*size.getHeight();
- if (maxArea < area) {
- selectedPair = sizePair;
- maxArea = area;
- }
- }
+ if (selectedPair != null) {
+ return selectedPair;
+ } else if (validPreviewSizes.size() > 0){
+ return validPreviewSizes.get(0);
+ } else {
+ return null;
}
- return selectedPair;
}
+// private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
+// List validPreviewSizes = generateValidPreviewSizeList(camera);
+//
+// int desiredSize = desiredHeight * desiredWidth;
+// float sizeRatio = 0.6f;
+//
+// SizePair selectedPair = null;
+//
+// do {
+// float desiredRatio = (float) Math.max(desiredWidth, desiredHeight) / Math.min(desiredWidth, desiredHeight);
+// float minDiff = Integer.MAX_VALUE;
+// for (SizePair sizePair : validPreviewSizes) {
+// Size size = sizePair.previewSize();
+// float diff = Math.abs((float) Math.max(size.getWidth(), size.getHeight()) / Math.min(size.getWidth(), size.getHeight()) - desiredRatio);
+// if (diff < minDiff && size.getWidth()*size.getHeight() > desiredSize*sizeRatio) {
+// selectedPair = sizePair;
+// minDiff = diff;
+// }
+// }
+// sizeRatio -= 0.1f;
+// } while (selectedPair == null);
+//
+// return selectedPair;
+// }
+
/**
* Stores a preview size and a corresponding same-aspect-ratio picture size. To avoid distorted
* preview images on some devices, the picture size must be set to a size that is the same
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSourcePreview.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSourcePreview.kt
index 054208c..493c97a 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSourcePreview.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCameraSourcePreview.kt
@@ -15,6 +15,7 @@
*/
package com.acuant.acuantcamera.camera.document.cameraone
+
import android.Manifest
import android.content.Context
import android.content.res.Configuration
@@ -25,14 +26,14 @@ import android.util.Log
import android.view.SurfaceHolder
import android.view.SurfaceView
import android.view.ViewGroup
+import android.widget.RelativeLayout
import com.acuant.acuantcamera.R
-import com.acuant.acuantcamera.camera.mrz.cameraone.DocumentCameraSourcePreview
-
-
import java.io.IOException
class DocumentCameraSourcePreview(private val mContext: Context, attrs: AttributeSet?) : ViewGroup(mContext, attrs) {
var mSurfaceView: SurfaceView
+ var pointXOffset: Int = 0
+ var pointYOffset: Int = 0
private var mStartRequested: Boolean = false
private var mSurfaceAvailable: Boolean = false
private var documentCameraSource: DocumentCameraSource? = null
@@ -55,7 +56,11 @@ class DocumentCameraSourcePreview(private val mContext: Context, attrs: Attribut
mStartRequested = false
mSurfaceAvailable = false
+ val previewParams = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
+ RelativeLayout.LayoutParams.MATCH_PARENT)
+ previewParams.addRule(RelativeLayout.CENTER_IN_PARENT)
mSurfaceView = SurfaceView(mContext)
+ mSurfaceView.layoutParams = previewParams
mSurfaceView.holder.addCallback(SurfaceCallback())
addView(mSurfaceView)
}
@@ -92,7 +97,7 @@ class DocumentCameraSourcePreview(private val mContext: Context, attrs: Attribut
@Throws(IOException::class, SecurityException::class)
private fun startIfReady() {
if (mStartRequested && mSurfaceAvailable) {
- documentCameraSource!!.start(mSurfaceView.holder)
+ documentCameraSource!!.start(mSurfaceView.holder, this)
mStartRequested = false
}
}
@@ -124,48 +129,64 @@ class DocumentCameraSourcePreview(private val mContext: Context, attrs: Attribut
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {}
+
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
- var width = 320
- var height = 240
+
+ val viewWidth = right - left
+ val viewHeight = bottom - top
+
+ var previewWidth = viewWidth
+ var previewHeight = viewHeight
if (documentCameraSource != null) {
- val size = documentCameraSource!!.previewSize
+ val size = documentCameraSource?.previewSize
if (size != null) {
- width = size.width
- height = size.height
+ previewWidth = size.width
+ previewHeight = size.height
}
}
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode) {
- val tmp = width
-
- width = height
- height = tmp
+ val tmp = previewWidth
+ previewWidth = previewHeight
+ previewHeight = tmp
+ }
+ val childWidth: Int
+ val childHeight: Int
+ val childXOffset: Int
+ val childYOffset: Int
+ val widthRatio = viewWidth.toFloat() / previewWidth.toFloat()
+ val heightRatio = viewHeight.toFloat() / previewHeight.toFloat()
+
+ if (widthRatio < heightRatio) {
+ childWidth = viewWidth
+ childHeight = (previewHeight.toFloat() * widthRatio).toInt()
+ } else {
+ childWidth = (previewWidth.toFloat() * heightRatio).toInt()
+ childHeight = viewHeight
}
- val layoutWidth = right - left
- val layoutHeight = bottom - top
+ childXOffset = (childWidth - viewWidth) / 2
+ childYOffset = (childHeight - viewHeight) / 2
- // Computes height and width for potentially doing fit width.
- var childWidth = layoutWidth
- var childHeight = (layoutWidth.toFloat() / width.toFloat() * height).toInt()
-
- if (childHeight < layoutHeight) {
- childHeight = layoutHeight
- childWidth = (layoutHeight.toFloat() / height.toFloat() * width).toInt()
- }
+ pointXOffset = childXOffset
+ pointYOffset = childYOffset
for (i in 0 until childCount) {
- getChildAt(i).layout(0, 0, childWidth, layoutHeight)
+ getChildAt(i).layout(
+ -1 * childXOffset, -1 * childYOffset,
+ childWidth - childXOffset, childHeight - childYOffset)
+ getChildAt(i).requestLayout()
}
try {
startIfReady()
- } catch (e: Exception) {
+ } catch (e: IOException) {
e.printStackTrace()
+ } catch (se: SecurityException) {
+ se.printStackTrace()
}
-
}
companion object {
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCaptureActivity.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCaptureActivity.kt
index 9354674..a8c6af5 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCaptureActivity.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/DocumentCaptureActivity.kt
@@ -8,38 +8,38 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
-import android.graphics.Color
-import android.graphics.Point
-import android.hardware.Camera
-import android.os.Bundle
-import android.util.Log
-import android.util.Size
-import android.widget.LinearLayout
-import android.widget.RelativeLayout
-import android.widget.TextView
-
-import java.io.IOException
-
import android.content.res.Configuration.ORIENTATION_LANDSCAPE
import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.graphics.Bitmap
import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.graphics.Point
import android.graphics.drawable.Drawable
+import android.hardware.Camera
+import android.os.Bundle
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
+import android.util.DisplayMetrics
+import android.util.Log
+import android.util.Size
import android.view.*
+import android.widget.RelativeLayout
+import android.widget.TextView
import com.acuant.acuantcamera.R
+import com.acuant.acuantcamera.camera.AcuantBaseCameraFragment.CameraState
import com.acuant.acuantcamera.camera.AcuantCameraActivity
import com.acuant.acuantcamera.camera.AcuantCameraOptions
-import com.acuant.acuantcamera.constant.*
-import java.io.ByteArrayOutputStream
-import com.acuant.acuantcamera.overlay.DocRectangleView
-import com.acuant.acuantcamera.camera.AcuantBaseCameraFragment.CameraState
import com.acuant.acuantcamera.camera.document.AcuantDocCameraFragment
+import com.acuant.acuantcamera.constant.ACUANT_EXTRA_CAMERA_OPTIONS
+import com.acuant.acuantcamera.constant.ACUANT_EXTRA_IMAGE_URL
+import com.acuant.acuantcamera.constant.ACUANT_EXTRA_PDF417_BARCODE
import com.acuant.acuantcamera.detector.ImageSaver
+import com.acuant.acuantcamera.overlay.DocRectangleView
+import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileOutputStream
+import java.io.IOException
import java.util.*
import kotlin.math.pow
import kotlin.math.roundToInt
@@ -90,35 +90,19 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
supportActionBar?.title = ""
supportActionBar?.hide()
- parent = RelativeLayout(this)
- parent.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
- parent.keepScreenOn = true
-
- setContentView(parent)
- mPreview = DocumentCameraSourcePreview(this, null)
- parent.addView(mPreview)
capturingTextDrawable = this.getDrawable(R.drawable.camera_text_config_capturing)
defaultTextDrawable = this.getDrawable(R.drawable.camera_text_config_default)
holdTextDrawable = this.getDrawable(R.drawable.camera_text_config_hold)
- val vfvp = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT)
- rectangleView = DocRectangleView(this, null)
- rectangleView.layoutParams = vfvp
- parent.addView(rectangleView)
-
- // UI Customization
- val tvlp = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT)
- tvlp.addRule(RelativeLayout.CENTER_IN_PARENT)
- instructionView = TextView(this)
-
- instructionView.setPadding(60, 15, 60, 15)
- instructionView.gravity = Gravity.CENTER
- instructionView.rotation = 90.0f
- instructionView.layoutParams = tvlp
+ setContentView(R.layout.activity_acu_document_camera)
+
+ parent = findViewById(R.id.cam1_doc_parent)
+ mPreview = findViewById(R.id.cam1_doc_preview)
+ rectangleView = findViewById(R.id.cam1_doc_rect)
+ instructionView = findViewById(R.id.cam1_doc_text)
+
setTextFromState(CameraState.Align)
- parent.addView(instructionView, tvlp)
// Check for the camera permission before accessing the camera. If the
// permission is not granted yet, request permission.
@@ -244,10 +228,15 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
// Creates and starts the camera. Note that this uses a higher resolution in comparison
// to other detection examples to enable the barcode detector to detect small barcodes
// at long distances.
+ val displayMetrics = DisplayMetrics()
+ windowManager.defaultDisplay.getMetrics(displayMetrics)
+ val height: Int = displayMetrics.heightPixels
+ val width: Int = displayMetrics.widthPixels
+
documentDetector = createDocumentDetector()
var builder: DocumentCameraSource.Builder = DocumentCameraSource.Builder(applicationContext, documentDetector)
.setFacing(DocumentCameraSource.CAMERA_FACING_BACK)
- .setRequestedPreviewSize(1600, 1200)
+ .setRequestedPreviewSize(width, height)
.setRequestedFps(60.0f)
builder = builder.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)
@@ -257,28 +246,49 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
.build()
}
-
-
- private fun isDocumentInPreviewFrame(points: Array): Boolean {
- points.apply {
- this.forEach { p ->
- if (p.x < 0 || (mPreview!!.mSurfaceView.width - p.y) < 0 || p.x > displaySize.y || (mPreview!!.mSurfaceView.width - p.y) > displaySize.x) {
+ private fun isDocumentInPreviewFrame(points: Array, frameSize: Size): Boolean {
+ val minOffset = 0.01f
+ if (mPreview != null) {
+ val scaleX = mPreview!!.mSurfaceView.width / frameSize.height.toFloat()
+ val scaleY = mPreview!!.mSurfaceView.height / frameSize.width.toFloat()
+
+ val startY = frameSize.height * minOffset * scaleY//textureView.width
+ val startX = frameSize.width * minOffset * scaleX //textureView.height.toFloat() / 2 - previewSize.width.toFloat() / 2
+ val endY = frameSize.height * (1 - minOffset) * scaleY//textureView.width
+ val endX = frameSize.width * (1 - minOffset) * scaleX//textureView.height
+
+// Log.d("WTF", "start: $startX,$startY\tend: $endX,$endY")
+// if (previewSize.width.toFloat()/displaySize.y < previewSize.height.toFloat()/displaySize.x) {
+// endX = (previewSize.width * displaySize.x/previewSize.height.toFloat()).toInt()
+// } else {
+// endY = (previewSize.height * displaySize.y/previewSize.width.toFloat()).toInt()
+// }
+// Log.d("WTF", "start: $startX,$startY\tend: $endX,$endY")
+
+ for (point in points) {
+ if (point.x < startX || point.y < startY || point.x > endX || point.y > endY) {
return false
}
}
+
+ return true
}
- return true
+
+ return false
}
private fun scalePoints(points: Array, frameSize: Size): Array {
val scaledPoints = points.copyOf()
- val scaleX = mPreview!!.mSurfaceView.width / frameSize.height.toFloat()
- val scaleY = mPreview!!.mSurfaceView.height / frameSize.width.toFloat()
-
- scaledPoints.apply {
- this.forEach { p ->
- p.x = (p.x * scaleY).toInt()
- p.y = (p.y * scaleX).toInt()
+ if (mPreview != null) {
+ val scaleX = mPreview!!.mSurfaceView.width / frameSize.height.toFloat()
+ val scaleY = mPreview!!.mSurfaceView.height / frameSize.width.toFloat()
+ rectangleView.setWidth(mPreview!!.mSurfaceView.width.toFloat())
+
+ scaledPoints.forEach {
+ it.x = (it.x * scaleY).toInt()
+ it.y = (it.y * scaleX).toInt()
+ it.y += mPreview?.pointXOffset ?: 0
+ it.x -= mPreview?.pointYOffset ?: 0
}
}
@@ -313,13 +323,12 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
var points = it.point
val frameSize = it.frameSize!!
var feedback = it.feedback
- rectangleView.setWidth(mPreview!!.mSurfaceView.width.toFloat())
if (points != null && points.size == 4) {
points = scalePoints(points, frameSize)
points = fixPoints(points)
- if (!isDocumentInPreviewFrame(points)) {
+ if (!isDocumentInPreviewFrame(points, frameSize)) {
feedback = DocumentFeedback.NotInFrame
}
}
@@ -498,7 +507,7 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
*/
@Throws(SecurityException::class)
private fun startCameraSource() {
- if (documentCameraSource != null) {
+ if (documentCameraSource != null && mPreview != null) {
try {
mPreview!!.start(documentCameraSource)
} catch (e: IOException) {
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/LiveDocumentProcessor.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/LiveDocumentProcessor.kt
index da69f61..f1a5d16 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/LiveDocumentProcessor.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/document/cameraone/LiveDocumentProcessor.kt
@@ -4,7 +4,9 @@ import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
+import android.util.Log
import android.util.Size
+import com.acuant.acuantcamera.camera.document.AcuantDocCameraFragment
import com.acuant.acuantimagepreparation.AcuantImagePreparation
import com.acuant.acuantimagepreparation.model.CroppingData
@@ -43,7 +45,7 @@ class LiveDocumentProcessor : DocumentGraphicTracker.BarcodeUpdateListener {
val hasLowStorage = context.registerReceiver(null, lowstorageFilter) != null
if (hasLowStorage) {
-
+ Log.d("Live Doc Processor", "Received low storage warning")
}
}
provideFeedback()
@@ -81,11 +83,11 @@ class LiveDocumentProcessor : DocumentGraphicTracker.BarcodeUpdateListener {
val startTime = System.currentTimeMillis()
val acuantImage = AcuantImagePreparation.detect(data)
val elapsed = System.currentTimeMillis() - startTime
- var feedback: AcuantDocumentFeedback? = null
+ var feedback: AcuantDocumentFeedback?
- feedback = if (acuantImage?.points == null || acuantImage.dpi < 20) {
+ feedback = if (acuantImage.points == null || acuantImage.dpi < 20) {
AcuantDocumentFeedback(DocumentFeedback.NoDocument, null, frameSize, null, elapsed)
- } else if ((!acuantImage.isPassport && acuantImage.dpi < (SMALL_DOC_DPI_SCALE_VALUE * frame!!.width)) || (acuantImage.isPassport && acuantImage.dpi < (LARGE_DOC_DPI_SCALE_VALUE * frame!!.width))) {
+ } else if (!AcuantDocCameraFragment.isAcceptableDistance(acuantImage.points, frameSize)) {
AcuantDocumentFeedback(DocumentFeedback.SmallDocument, acuantImage.points, frameSize, null, elapsed)
} else if (!acuantImage.isCorrectAspectRatio) {
AcuantDocumentFeedback(DocumentFeedback.BadDocument, acuantImage.points, frameSize, null, elapsed)
@@ -109,17 +111,7 @@ class LiveDocumentProcessor : DocumentGraphicTracker.BarcodeUpdateListener {
thread!!.start()
}
- /**
- * Target DPI for preview size 1920x1080 = 350
- * SMALL_DOC_DPI_SCALE_VALUE = target_dpi/preview_size_width
- */
- private val SMALL_DOC_DPI_SCALE_VALUE = .18229
-
- /**
- * Target DPI for preview size 1920x1080 = 225
- * LARGE_DOC_DPI_SCALE_VALUE = target_dpi/preview_size_width
- */
- private val LARGE_DOC_DPI_SCALE_VALUE = .11719
+
override fun onBarcodeDetected(barcode: Barcode?) {
if(barcode?.rawValue != null){
feedbackListener?.let { it(AcuantDocumentFeedback(DocumentFeedback.Barcode, null, null, barcode.rawValue)) }
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt
index 25c3473..470574b 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/AcuantMrzCameraFragment.kt
@@ -46,10 +46,13 @@ class AcuantMrzCameraFragment : AcuantBaseCameraFragment(), ActivityCompat.OnReq
val scaledPointY = textureView.height.toFloat() / previewSize.width.toFloat()
val scaledPointX = textureView.width.toFloat() / previewSize.height.toFloat()
rectangleView.setWidth(textureView.width.toFloat())
+
points.apply {
this.forEach {
it.x = (it.x * scaledPointY).toInt()
it.y = (it.y * scaledPointX).toInt()
+ it.y -= pointYOffset
+ it.x += pointXOffset
}
}
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/AcuantDocumentFeedback.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/AcuantMrzFeedback.kt
similarity index 83%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/AcuantDocumentFeedback.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/AcuantMrzFeedback.kt
index b8b1be4..18a2c44 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/AcuantDocumentFeedback.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/AcuantMrzFeedback.kt
@@ -3,12 +3,12 @@ package com.acuant.acuantcamera.camera.mrz.cameraone
import android.graphics.Point
import android.util.Size
-data class AcuantDocumentFeedback(val feedback: DocumentFeedback, val point: Array?, val frameSize: Size?, val barcode: String? = null) {
+data class AcuantMrzFeedback(val feedback: MrzFeedback, val point: Array?, val frameSize: Size?, val barcode: String? = null) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
- other as AcuantDocumentFeedback
+ other as AcuantMrzFeedback
if (feedback != other.feedback) return false
if (point != null) {
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/LiveDocumentProcessor.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/LiveMrzProcessor.kt
similarity index 74%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/LiveDocumentProcessor.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/LiveMrzProcessor.kt
index b16e848..88eb9d6 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/LiveDocumentProcessor.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/LiveMrzProcessor.kt
@@ -2,15 +2,16 @@ package com.acuant.acuantcamera.camera.mrz.cameraone
import android.content.Context
import android.graphics.Bitmap
+import android.util.Log
import com.acuant.acuantcamera.detector.ocr.AcuantOcrDetector
import com.google.android.gms.vision.MultiProcessor
import com.google.android.gms.vision.barcode.Barcode
import com.google.android.gms.vision.barcode.BarcodeDetector
-class LiveDocumentProcessor : DocumentGraphicTracker.BarcodeUpdateListener {
+class LiveMrzProcessor : MrzGraphicTracker.BarcodeUpdateListener {
private var finishedCapturing = false
- private var documentDetector: DocumentDetector? = null
+ private var mrzDetector: MrzDetector? = null
private var ocrDetector: AcuantOcrDetector? = null
var frame: Bitmap? = null
@@ -18,31 +19,32 @@ class LiveDocumentProcessor : DocumentGraphicTracker.BarcodeUpdateListener {
ocrDetector = detector
}
- fun getDetector(context: Context): DocumentDetector {
+ fun getDetector(context: Context): MrzDetector {
val barcodeDetectorDelagte = BarcodeDetector.Builder(context).setBarcodeFormats(Barcode.PDF417).build()
- val barcodeFactory = DocumentTrackerFactory(this)
+ val barcodeFactory = MrzTrackerFactory(this)
val processor = MultiProcessor.Builder(barcodeFactory).build()
- documentDetector = DocumentDetector(barcodeDetectorDelagte)
- documentDetector!!.setProcessor(processor)
+ mrzDetector = MrzDetector(barcodeDetectorDelagte)
+ mrzDetector!!.setProcessor(processor)
provideFeedback()
- return documentDetector as DocumentDetector
+ return mrzDetector as MrzDetector
}
fun stop(){
finishedCapturing = true
thread?.join()
- documentDetector?.release()
+ mrzDetector?.release()
thread = null
- documentDetector = null
+ mrzDetector = null
// thread = null
}
private var thread : Thread? = null
private fun provideFeedback() {
- if(ocrDetector == null) {
+ if (ocrDetector == null) {
+ Log.e("ocrDetector", "OCR detector can not be null")
//TODO: return error
}
thread = Thread(object : Runnable {
@@ -52,7 +54,7 @@ class LiveDocumentProcessor : DocumentGraphicTracker.BarcodeUpdateListener {
while (flag) {
if (!processing) {
processing = true
- frame = documentDetector?.frame
+ frame = mrzDetector?.frame
if (frame != null) {
ocrDetector?.detect(frame)
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCameraSource.java b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCameraSource.java
similarity index 92%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCameraSource.java
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCameraSource.java
index 0bb9bf4..2ff2cf8 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCameraSource.java
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCameraSource.java
@@ -56,7 +56,7 @@
*
*/
@SuppressWarnings("deprecation")
-public class DocumentCameraSource {
+public class MrzCameraSource {
@SuppressLint("InlinedApi")
static final int CAMERA_FACING_BACK = CameraInfo.CAMERA_FACING_BACK;
@SuppressLint("InlinedApi")
@@ -157,7 +157,7 @@ public class DocumentCameraSource {
*/
public static class Builder {
private final Detector> mDetector;
- private DocumentCameraSource documentCameraSource = new DocumentCameraSource();
+ private MrzCameraSource mrzCameraSource = new MrzCameraSource();
/**
* Creates a camera source builder with the supplied context and detector. Camera preview
@@ -172,7 +172,7 @@ public Builder(Context context, Detector> detector) {
}
mDetector = detector;
- documentCameraSource.mContext = context;
+ mrzCameraSource.mContext = context;
}
/**
@@ -183,19 +183,19 @@ public Builder setRequestedFps(float fps) {
if (fps <= 0) {
throw new IllegalArgumentException("Invalid fps: " + fps);
}
- documentCameraSource.mRequestedFps = fps;
+ mrzCameraSource.mRequestedFps = fps;
return this;
}
public Builder setFocusMode(@FocusMode String mode) {
- documentCameraSource.mFocusMode = mode;
+ mrzCameraSource.mFocusMode = mode;
return this;
}
public Builder setFlashMode(@FlashMode String mode) {
- documentCameraSource.mFlashMode = mode;
+ mrzCameraSource.mFlashMode = mode;
return this;
}
@@ -213,8 +213,8 @@ public Builder setRequestedPreviewSize(int width, int height) {
if ((width <= 0) || (width > MAX) || (height <= 0) || (height > MAX)) {
throw new IllegalArgumentException("Invalid preview size: " + width + "x" + height);
}
- documentCameraSource.mRequestedPreviewWidth = width;
- documentCameraSource.mRequestedPreviewHeight = height;
+ mrzCameraSource.mRequestedPreviewWidth = width;
+ mrzCameraSource.mRequestedPreviewHeight = height;
return this;
}
@@ -226,16 +226,16 @@ public Builder setFacing(int facing) {
if ((facing != CAMERA_FACING_BACK) && (facing != CAMERA_FACING_FRONT)) {
throw new IllegalArgumentException("Invalid camera: " + facing);
}
- documentCameraSource.mFacing = facing;
+ mrzCameraSource.mFacing = facing;
return this;
}
/**
* Creates an instance of the camera source.
*/
- public DocumentCameraSource build() {
- documentCameraSource.mFrameProcessor = documentCameraSource.new FrameProcessingRunnable(mDetector);
- return documentCameraSource;
+ public MrzCameraSource build() {
+ mrzCameraSource.mFrameProcessor = mrzCameraSource.new FrameProcessingRunnable(mDetector);
+ return mrzCameraSource;
}
}
@@ -324,7 +324,7 @@ public void release() {
* @throws IOException if the camera's preview texture or display could not be initialized
*/
@RequiresPermission(Manifest.permission.CAMERA)
- public DocumentCameraSource start() throws IOException {
+ public MrzCameraSource start() throws IOException {
synchronized (mCameraLock) {
if (mCamera != null) {
return this;
@@ -358,7 +358,7 @@ public DocumentCameraSource start() throws IOException {
* @throws IOException if the supplied surface holder could not be used as the preview display
*/
@RequiresPermission(Manifest.permission.CAMERA)
- public DocumentCameraSource start(SurfaceHolder surfaceHolder) throws IOException {
+ public MrzCameraSource start(SurfaceHolder surfaceHolder, MrzCameraSourcePreview preview) throws IOException {
synchronized (mCameraLock) {
if (mCamera != null) {
return this;
@@ -373,6 +373,10 @@ public DocumentCameraSource start(SurfaceHolder surfaceHolder) throws IOExceptio
mCamera.setPreviewDisplay(surfaceHolder);
mCamera.startPreview();
+ if (preview != null) {
+ preview.requestLayout();
+ }
+
mProcessingThread = new Thread(mFrameProcessor);
mFrameProcessor.setActive(true);
mProcessingThread.start();
@@ -384,7 +388,7 @@ public DocumentCameraSource start(SurfaceHolder surfaceHolder) throws IOExceptio
* Closes the camera and stops sending frames to the underlying frame detector.
*
* This camera source may be restarted again by calling {@link #start()} or
- * {@link #start(SurfaceHolder)}.
+ * {@link #start(SurfaceHolder, MrzCameraSourcePreview)}.
*
* Call {@link #release()} instead to completely shut down this camera source and release the
* resources of the underlying detector.
@@ -481,7 +485,7 @@ public int doZoom(float scale) {
/**
* Initiates taking a picture, which happens asynchronously. The camera source should have been
- * activated previously with {@link #start()} or {@link #start(SurfaceHolder)}. The camera
+ * activated previously with {@link #start()} or {@link #start(SurfaceHolder, MrzCameraSourcePreview)}. The camera
* preview is suspended while the picture is being taken, but will resume once picture taking is
* done.
*
@@ -586,7 +590,7 @@ public boolean setFlashMode(@FlashMode String mode) {
/**
* Starts camera auto-focus and registers a callback function to run when
* the camera is focused. This method is only valid when preview is active
- * (between {@link #start()} or {@link #start(SurfaceHolder)} and before {@link #stop()} or {@link #release()}).
+ * (between {@link #start()} or {@link #start(SurfaceHolder, MrzCameraSourcePreview)} and before {@link #stop()} or {@link #release()}).
*
* Callers should check
* {@link #getFocusMode()} to determine if
@@ -663,7 +667,7 @@ public boolean setAutoFocusMoveCallback(@Nullable AutoFocusMoveCallback cb) {
/**
* Only allow creation via the builder class.
*/
- private DocumentCameraSource() {
+ private MrzCameraSource() {
}
/**
@@ -827,6 +831,41 @@ private static int getIdForRequestedCamera(int facing) {
return -1;
}
+// private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
+// List validPreviewSizes = generateValidPreviewSizeList(camera);
+// // The method for selecting the best size is to minimize the sum of the differences between
+// // the desired values and the actual values for width and height. This is certainly not the
+// // only way to select the best size, but it provides a decent tradeoff between using the
+// // closest aspect ratio vs. using the closest pixel area.
+// SizePair selectedPair = null;
+// int maxArea = Integer.MIN_VALUE;
+// int maxPict = Integer.MIN_VALUE;
+// int area = Integer.MIN_VALUE;
+// for (SizePair sizePair : validPreviewSizes) {
+// Size size_pict = sizePair.pictureSize();
+// int newArea = size_pict.getWidth()*size_pict.getHeight();
+// if (newArea > maxPict) {
+// maxPict = newArea;
+// maxArea = Integer.MIN_VALUE;
+// Size size = sizePair.previewSize();
+// area = size.getWidth()*size.getHeight();
+// if (maxArea < area) {
+// selectedPair = sizePair;
+// maxArea = area;
+// }
+// }
+// else if (newArea == maxPict) {
+// Size size = sizePair.previewSize();
+// area = size.getWidth()*size.getHeight();
+// if (maxArea < area) {
+// selectedPair = sizePair;
+// maxArea = area;
+// }
+// }
+// }
+// return selectedPair;
+// }
+
/**
* Selects the most suitable preview and picture size, given the desired width and height.
*
@@ -840,9 +879,11 @@ private static int getIdForRequestedCamera(int facing) {
* @param desiredHeight the desired height of the camera preview frames
* @return the selected preview and picture size pair
*/
- /*private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
+ private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
List validPreviewSizes = generateValidPreviewSizeList(camera);
-
+ long expectedSize = desiredWidth*desiredHeight;
+ int desiredShortSide = Math.min(desiredHeight, desiredWidth);
+ int desiredLongSide = Math.max(desiredHeight, desiredWidth);
// The method for selecting the best size is to minimize the sum of the differences between
// the desired values and the actual values for width and height. This is certainly not the
// only way to select the best size, but it provides a decent tradeoff between using the
@@ -851,52 +892,33 @@ private static int getIdForRequestedCamera(int facing) {
int minDiff = Integer.MAX_VALUE;
for (SizePair sizePair : validPreviewSizes) {
Size size = sizePair.previewSize();
- int diff = Math.abs(size.getWidth() - desiredWidth) +
- Math.abs(size.getHeight() - desiredHeight);
- if (diff < minDiff) {
+
+
+ int currentShortSide = Math.min(size.getWidth(), size.getHeight());
+ int currentLongSide = Math.max(size.getWidth(), size.getHeight());
+ float change = Math.min(Math.min((float) desiredShortSide / currentShortSide, (float) desiredLongSide / currentLongSide), 2f);
+ currentLongSide *= change;
+ currentShortSide *= change;
+
+
+ int diff = Math.abs(currentShortSide - desiredShortSide) +
+ Math.abs(currentLongSide - desiredLongSide);
+ if ((!(currentLongSide > desiredLongSide) && !(currentShortSide > desiredShortSide)) && diff < minDiff && (sizePair.pictureSize().getWidth()*sizePair.pictureSize().getHeight() >= expectedSize * 0.6f)) {
selectedPair = sizePair;
minDiff = diff;
}
}
- return selectedPair;
- }*/
-
- private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
- List validPreviewSizes = generateValidPreviewSizeList(camera);
- // The method for selecting the best size is to minimize the sum of the differences between
- // the desired values and the actual values for width and height. This is certainly not the
- // only way to select the best size, but it provides a decent tradeoff between using the
- // closest aspect ratio vs. using the closest pixel area.
- SizePair selectedPair = null;
- int maxArea = Integer.MIN_VALUE;
- int maxPict = Integer.MIN_VALUE;
- int area = Integer.MIN_VALUE;
- for (SizePair sizePair : validPreviewSizes) {
- Size size_pict = sizePair.pictureSize();
- int newArea = size_pict.getWidth()*size_pict.getHeight();
- if (newArea > maxPict) {
- maxPict = newArea;
- maxArea = Integer.MIN_VALUE;
- Size size = sizePair.previewSize();
- area = size.getWidth()*size.getHeight();
- if (maxArea < area) {
- selectedPair = sizePair;
- maxArea = area;
- }
- }
- else if (newArea == maxPict) {
- Size size = sizePair.previewSize();
- area = size.getWidth()*size.getHeight();
- if (maxArea < area) {
- selectedPair = sizePair;
- maxArea = area;
- }
- }
+ if (selectedPair != null) {
+ return selectedPair;
+ } else if (validPreviewSizes.size() > 0){
+ return validPreviewSizes.get(0);
+ } else {
+ return null;
}
- return selectedPair;
}
+
/**
* Stores a preview size and a corresponding same-aspect-ratio picture size. To avoid distorted
* preview images on some devices, the picture size must be set to a size that is the same
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCameraSourcePreview.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCameraSourcePreview.kt
similarity index 65%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCameraSourcePreview.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCameraSourcePreview.kt
index 56bd376..2402c16 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCameraSourcePreview.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCameraSourcePreview.kt
@@ -30,11 +30,13 @@ import com.acuant.acuantcamera.R
import java.io.IOException
-class DocumentCameraSourcePreview(private val mContext: Context, attrs: AttributeSet?) : ViewGroup(mContext, attrs) {
+class MrzCameraSourcePreview(private val mContext: Context, attrs: AttributeSet?) : ViewGroup(mContext, attrs) {
var mSurfaceView: SurfaceView
+ var pointXOffset: Int = 0
+ var pointYOffset: Int = 0
private var mStartRequested: Boolean = false
private var mSurfaceAvailable: Boolean = false
- private var documentCameraSource: DocumentCameraSource? = null
+ private var mrzCameraSource: MrzCameraSource? = null
private val isPortraitMode: Boolean
get() {
@@ -61,29 +63,29 @@ class DocumentCameraSourcePreview(private val mContext: Context, attrs: Attribut
@RequiresPermission(Manifest.permission.CAMERA)
@Throws(IOException::class, SecurityException::class)
- fun start(documentCameraSource: DocumentCameraSource?) {
- if (documentCameraSource == null) {
+ fun start(mrzCameraSource: MrzCameraSource?) {
+ if (mrzCameraSource == null) {
stop()
}
- this.documentCameraSource = documentCameraSource
+ this.mrzCameraSource = mrzCameraSource
- if (this.documentCameraSource != null) {
+ if (this.mrzCameraSource != null) {
mStartRequested = true
startIfReady()
}
}
fun stop() {
- if (documentCameraSource != null) {
- documentCameraSource!!.stop()
+ if (mrzCameraSource != null) {
+ mrzCameraSource!!.stop()
}
}
fun release() {
- if (documentCameraSource != null) {
- documentCameraSource!!.release()
- documentCameraSource = null
+ if (mrzCameraSource != null) {
+ mrzCameraSource!!.release()
+ mrzCameraSource = null
}
}
@@ -91,7 +93,7 @@ class DocumentCameraSourcePreview(private val mContext: Context, attrs: Attribut
@Throws(IOException::class, SecurityException::class)
private fun startIfReady() {
if (mStartRequested && mSurfaceAvailable) {
- documentCameraSource!!.start(mSurfaceView.holder)
+ mrzCameraSource!!.start(mSurfaceView.holder, this)
mStartRequested = false
}
}
@@ -124,46 +126,60 @@ class DocumentCameraSourcePreview(private val mContext: Context, attrs: Attribut
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
- var width = 320
- var height = 240
- if (documentCameraSource != null) {
- val size = documentCameraSource!!.previewSize
+
+ val viewWidth = right - left
+ val viewHeight = bottom - top
+
+ var previewWidth = viewWidth
+ var previewHeight = viewHeight
+ if (mrzCameraSource != null) {
+ val size = mrzCameraSource?.previewSize
if (size != null) {
- width = size.width
- height = size.height
+ previewWidth = size.width
+ previewHeight = size.height
}
}
// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
if (isPortraitMode) {
- val tmp = width
-
- width = height
- height = tmp
+ val tmp = previewWidth
+ previewWidth = previewHeight
+ previewHeight = tmp
}
- val layoutWidth = right - left
- val layoutHeight = bottom - top
-
- // Computes height and width for potentially doing fit width.
- var childWidth = layoutWidth
- var childHeight = (layoutWidth.toFloat() / width.toFloat() * height).toInt()
-
- if (childHeight < layoutHeight) {
- childHeight = layoutHeight
- childWidth = (layoutHeight.toFloat() / height.toFloat() * width).toInt()
+ val childWidth: Int
+ val childHeight: Int
+ val childXOffset: Int
+ val childYOffset: Int
+ val widthRatio = viewWidth.toFloat() / previewWidth.toFloat()
+ val heightRatio = viewHeight.toFloat() / previewHeight.toFloat()
+
+ if (widthRatio < heightRatio) {
+ childWidth = viewWidth
+ childHeight = (previewHeight.toFloat() * widthRatio).toInt()
+ } else {
+ childWidth = (previewWidth.toFloat() * heightRatio).toInt()
+ childHeight = viewHeight
}
+ childXOffset = (childWidth - viewWidth) / 2
+ childYOffset = (childHeight - viewHeight) / 2
+
+ pointXOffset = childXOffset
+ pointYOffset = childYOffset
for (i in 0 until childCount) {
- getChildAt(i).layout(0, 0, childWidth, layoutHeight)
+ getChildAt(i).layout(
+ -1 * childXOffset, -1 * childYOffset,
+ childWidth - childXOffset, childHeight - childYOffset)
+ getChildAt(i).requestLayout()
}
-
try {
startIfReady()
- } catch (e: Exception) {
+ } catch (e: IOException) {
e.printStackTrace()
+ } catch (se: SecurityException) {
+ se.printStackTrace()
}
-
}
companion object {
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCaptureActivity.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCaptureActivity.kt
similarity index 85%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCaptureActivity.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCaptureActivity.kt
index 6d90c3e..3215453 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentCaptureActivity.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzCaptureActivity.kt
@@ -14,13 +14,10 @@ import android.hardware.Camera
import android.media.AudioManager
import android.os.Bundle
import android.util.Log
-import android.view.Gravity
import android.view.OrientationEventListener
import android.view.View
import android.view.Window
import android.view.WindowManager
-import android.widget.LinearLayout
-import android.widget.RelativeLayout
import android.widget.TextView
import com.google.android.gms.common.ConnectionResult
@@ -30,12 +27,12 @@ import java.io.IOException
import android.content.res.Configuration.ORIENTATION_LANDSCAPE
import android.content.res.Configuration.ORIENTATION_PORTRAIT
-import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Handler
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
+import android.util.DisplayMetrics
import android.widget.ImageView
import com.acuant.acuantcamera.R
import com.acuant.acuantcamera.camera.*
@@ -60,15 +57,15 @@ import kotlin.math.sqrt
* rear facing camera. During detection overlay graphics are drawn to indicate the position,
* size, and ID of each barcode.
*/
-class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.PictureCallback, DocumentCameraSource.ShutterCallback, AcuantOcrDetectorHandler {
+class MrzCaptureActivity : AppCompatActivity(), MrzCameraSource.PictureCallback, MrzCameraSource.ShutterCallback, AcuantOcrDetectorHandler {
- private var documentCameraSource: DocumentCameraSource? = null
- private var mPreview: DocumentCameraSourcePreview? = null
+ private var mrzCameraSource: MrzCameraSource? = null
+ private var mPreview: MrzCameraSourcePreview? = null
private var waitTime = 2
private var autoCapture = false
- private lateinit var documentProcessor: LiveDocumentProcessor
+ private lateinit var mrzProcessor: LiveMrzProcessor
private var permissionNotGranted = false
- private var documentDetector: DocumentDetector? = null
+ private var mrzDetector: MrzDetector? = null
private lateinit var instructionView: TextView
private lateinit var imageView: ImageView
@@ -76,7 +73,6 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
private var capturedbarcodeString: String? = null
private lateinit var rectangleView: MrzRectangleView
- private lateinit var tvlp: RelativeLayout.LayoutParams
private var capturingTextDrawable: Drawable? = null
private var defaultTextDrawable: Drawable? = null
@@ -92,13 +88,16 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
runOnUiThread {
if (points != null) {
if (points.size == 4) {
- val scaledPointY = mPreview!!.mSurfaceView.height.toFloat() / (documentDetector?.frame?.width?.toFloat() ?: mPreview!!.mSurfaceView.height.toFloat())
- val scaledPointX = mPreview!!.mSurfaceView.width.toFloat() / (documentDetector?.frame?.height?.toFloat() ?: mPreview!!.mSurfaceView.width.toFloat())
+ val scaledPointY = mPreview!!.mSurfaceView.height.toFloat() / (mrzDetector?.frame?.width?.toFloat() ?: mPreview!!.mSurfaceView.height.toFloat())
+ val scaledPointX = mPreview!!.mSurfaceView.width.toFloat() / (mrzDetector?.frame?.height?.toFloat() ?: mPreview!!.mSurfaceView.width.toFloat())
rectangleView.setWidth(mPreview!!.mSurfaceView.width.toFloat())
+
points.apply {
this.forEach {
it.x = (it.x * scaledPointY).toInt()
it.y = (it.y * scaledPointX).toInt()
+ it.y += mPreview?.pointXOffset ?: 0
+ it.x -= mPreview?.pointYOffset ?: 0
}
}
@@ -222,49 +221,20 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
supportActionBar?.title = ""
supportActionBar?.hide()
- val parent = RelativeLayout(this)
- parent.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
- parent.keepScreenOn = true
-
- setContentView(parent)
- mPreview = DocumentCameraSourcePreview(this, null)
- parent.addView(mPreview)
capturingTextDrawable = this.getDrawable(R.drawable.camera_text_config_capturing)
defaultTextDrawable = this.getDrawable(R.drawable.camera_text_config_default)
- val vfvp = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT)
- rectangleView = MrzRectangleView(this, null)
- rectangleView.layoutParams = vfvp
- parent.addView(rectangleView)
+ setContentView(R.layout.activity_acu_mrz_camera)
- setOptions(options)
+ mPreview = findViewById(R.id.cam1_mrz_preview)
+ rectangleView = findViewById(R.id.cam1_mrz_rect)
+ instructionView = findViewById(R.id.cam1_mrz_text)
+ imageView = findViewById(R.id.cam1_mrz_image)
- // UI Customization
- tvlp = RelativeLayout.LayoutParams(resources.getDimension(R.dimen.cam_error_width).toInt(), resources.getDimension(R.dimen.cam_mrz_height).toInt())
- tvlp.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
- instructionView = TextView(this)
-
- instructionView.setPadding(60, 15, 60, 15)
- instructionView.gravity = Gravity.CENTER
- instructionView.rotation = 90.0f
- instructionView.layoutParams = tvlp
- instructionView.typeface = Typeface.MONOSPACE
- instructionView.id = R.id.acu_display_text
-
- val tvlp2 = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
- RelativeLayout.LayoutParams.WRAP_CONTENT)
- tvlp2.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE)
- imageView = ImageView(this)
- imageView.rotation = 90.0f
- imageView.setImageResource(R.drawable.camera_overlay)
- imageView.layoutParams = tvlp2
- imageView.id = R.id.acu_help_image
+ setOptions(options)
setTextFromState(this, AcuantBaseCameraFragment.CameraState.Align, instructionView, imageView)
- parent.addView(instructionView, tvlp)
- parent.addView(imageView, tvlp2)
// Check for the camera permission before accessing the camera. If the
// permission is not granted yet, request permission.
@@ -345,24 +315,29 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
// Creates and starts the camera. Note that this uses a higher resolution in comparison
// to other detection examples to enable the barcode detector to detect small barcodes
// at long distances.
- documentDetector = createDocumentDetector()
- var builder: DocumentCameraSource.Builder = DocumentCameraSource.Builder(applicationContext, documentDetector)
- .setFacing(DocumentCameraSource.CAMERA_FACING_BACK)
- .setRequestedPreviewSize(1600, 1200)
+ val displayMetrics = DisplayMetrics()
+ windowManager.defaultDisplay.getMetrics(displayMetrics)
+ val height: Int = displayMetrics.heightPixels
+ val width: Int = displayMetrics.widthPixels
+
+ mrzDetector = createDocumentDetector()
+ var builder: MrzCameraSource.Builder = MrzCameraSource.Builder(applicationContext, mrzDetector)
+ .setFacing(MrzCameraSource.CAMERA_FACING_BACK)
+ .setRequestedPreviewSize(width, height)
.setRequestedFps(60.0f)
// make sure that auto focus is an available option
builder = builder.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)
- documentCameraSource = builder
+ mrzCameraSource = builder
.setFlashMode(if (useFlash) Camera.Parameters.FLASH_MODE_TORCH else Camera.Parameters.FLASH_MODE_OFF)
.build()
}
- private fun createDocumentDetector(): DocumentDetector {
- documentProcessor = LiveDocumentProcessor()
- documentProcessor.setOcrDetector(AcuantOcrDetector(this, this))
- return documentProcessor.getDetector(applicationContext)
+ private fun createDocumentDetector(): MrzDetector {
+ mrzProcessor = LiveMrzProcessor()
+ mrzProcessor.setOcrDetector(AcuantOcrDetector(this, this))
+ return mrzProcessor.getDetector(applicationContext)
}
@@ -398,7 +373,7 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
override fun onDestroy() {
super.onDestroy()
if (!permissionNotGranted) {
- documentProcessor.stop()
+ mrzProcessor.stop()
}
if (mPreview != null) {
mPreview!!.release()
@@ -466,19 +441,19 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
dlg.show()
}
- if (documentCameraSource != null) {
+ if (mrzCameraSource != null) {
try {
- mPreview!!.start(documentCameraSource)
+ mPreview!!.start(mrzCameraSource)
} catch (e: IOException) {
Log.e(TAG, "Unable to start camera source.", e)
- documentCameraSource!!.release()
- documentCameraSource = null
+ mrzCameraSource!!.release()
+ mrzCameraSource = null
}
}
}
override fun onBackPressed() {
- this@DocumentCaptureActivity.finish()
+ this@MrzCaptureActivity.finish()
}
private fun onChanged(@Suppress("UNUSED_PARAMETER") lastOrientation: Int, curOrientation: Int) {
@@ -507,7 +482,7 @@ class DocumentCaptureActivity : AppCompatActivity(), DocumentCameraSource.Pictur
Thread(Runnable {
val mgr = getSystemService(Context.AUDIO_SERVICE) as AudioManager
mgr.setStreamMute(AudioManager.STREAM_SYSTEM, false)
- this@DocumentCaptureActivity.runOnUiThread {
+ this@MrzCaptureActivity.runOnUiThread {
val result = Intent()
val file = File(this.getExternalFilesDir(null), "${UUID.randomUUID()}.jpg")
saveFile(file, data)
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentDetector.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzDetector.kt
similarity index 94%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentDetector.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzDetector.kt
index c298baa..35fad70 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentDetector.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzDetector.kt
@@ -14,7 +14,7 @@ import com.google.android.gms.vision.barcode.Barcode
import java.io.ByteArrayOutputStream
-class DocumentDetector(private val mDelegate: Detector) : Detector() {
+class MrzDetector(private val mDelegate: Detector) : Detector() {
var frame: Bitmap? = null
private set
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentFeedback.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzFeedback.kt
similarity index 82%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentFeedback.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzFeedback.kt
index 0a87fcd..495f1b2 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentFeedback.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzFeedback.kt
@@ -1,6 +1,6 @@
package com.acuant.acuantcamera.camera.mrz.cameraone
-enum class DocumentFeedback {
+enum class MrzFeedback {
NoDocument,
SmallDocument,
BadDocument,
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentGraphicTracker.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzGraphicTracker.kt
similarity index 95%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentGraphicTracker.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzGraphicTracker.kt
index f21134a..8e2f871 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentGraphicTracker.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzGraphicTracker.kt
@@ -26,7 +26,7 @@ import com.google.android.gms.vision.barcode.Barcode
* to an overlay, update the graphics as the item changes, and remove the graphics when the item
* goes away.
*/
-internal class DocumentGraphicTracker(private val mBarcodeUpdateListener: BarcodeUpdateListener) : Tracker() {
+internal class MrzGraphicTracker(private val mBarcodeUpdateListener: BarcodeUpdateListener) : Tracker() {
/**
* Consume the item instance detected from an Activity or Fragment level by implementing the
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentTrackerFactory.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzTrackerFactory.kt
similarity index 85%
rename from acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentTrackerFactory.kt
rename to acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzTrackerFactory.kt
index b66750d..01cce28 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/DocumentTrackerFactory.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/camera/mrz/cameraone/MrzTrackerFactory.kt
@@ -24,10 +24,10 @@ import com.google.android.gms.vision.barcode.Barcode
* Factory for creating a tracker and associated graphic to be associated with a new barcode. The
* multi-processor uses this factory to create barcode trackers as needed -- one for each barcode.
*/
-internal class DocumentTrackerFactory(private val listener: DocumentGraphicTracker.BarcodeUpdateListener) : MultiProcessor.Factory {
+internal class MrzTrackerFactory(private val listener: MrzGraphicTracker.BarcodeUpdateListener) : MultiProcessor.Factory {
override fun create(barcode: Barcode): Tracker {
- return DocumentGraphicTracker(listener)
+ return MrzGraphicTracker(listener)
}
}
diff --git a/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/AutoFitTextureView.kt b/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/AutoFitTextureView.kt
index 9dbc678..ece4676 100644
--- a/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/AutoFitTextureView.kt
+++ b/acuantcamera/src/main/java/com/acuant/acuantcamera/helper/AutoFitTextureView.kt
@@ -3,7 +3,6 @@ package com.acuant.acuantcamera.helper
import android.content.Context
import android.util.AttributeSet
import android.view.TextureView
-import android.view.View
/**
* A [TextureView] that can be adjusted to a specified aspect ratio.
@@ -14,10 +13,9 @@ class AutoFitTextureView @JvmOverloads constructor(
defStyle: Int = 0
) : TextureView(context, attrs, defStyle) {
- private var ratioWidth = 0
- private var ratioHeight = 0
- private var maxWidth = 0
- private var maxHeight = 0
+ private var mRatioWidth = 0
+ private var mRatioHeight = 0
+
/**
* Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
* calculated from the parameters. Note that the actual sizes of parameters don't matter, that
@@ -27,38 +25,24 @@ class AutoFitTextureView @JvmOverloads constructor(
* @param height Relative vertical size
*/
fun setAspectRatio(width: Int, height: Int) {
- if (width < 0 || height < 0) {
- throw IllegalArgumentException("Size cannot be negative.")
- }
- ratioWidth = width
- ratioHeight = height
+ require(!(width < 0 || height < 0)) { "Size cannot be negative." }
+ mRatioWidth = width
+ mRatioHeight = height
requestLayout()
}
- fun setMax(width: Int, height: Int) {
- if (width < 0 || height < 0) {
- throw IllegalArgumentException("Size cannot be negative.")
- }
- maxWidth = width
- maxHeight = height
- }
-
-
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
- val width = View.MeasureSpec.getSize(widthMeasureSpec)
- val height = View.MeasureSpec.getSize(heightMeasureSpec)
- if (ratioWidth == 0 || ratioHeight == 0) {
+ val width = MeasureSpec.getSize(widthMeasureSpec)
+ val height = MeasureSpec.getSize(heightMeasureSpec)
+ if (0 == mRatioWidth || 0 == mRatioHeight) {
setMeasuredDimension(width, height)
- }
- else {
- if((height * ratioWidth / ratioHeight) <= maxWidth ){
- setMeasuredDimension(width, (width * ratioHeight/ratioWidth.toFloat()).toInt())
- }
- else{
- setMeasuredDimension((height * ratioWidth / ratioHeight.toFloat()).toInt(), height)
+ } else {
+ if (width/mRatioWidth.toFloat() < height/mRatioHeight.toFloat()) {
+ setMeasuredDimension(width, (mRatioHeight * width/mRatioWidth.toFloat()).toInt())
+ } else {
+ setMeasuredDimension((mRatioWidth * height/mRatioHeight.toFloat()).toInt(), height)
}
}
}
-
}
diff --git a/acuantcamera/src/main/res/layout/activity_acu_document_camera.xml b/acuantcamera/src/main/res/layout/activity_acu_document_camera.xml
new file mode 100644
index 0000000..5db4937
--- /dev/null
+++ b/acuantcamera/src/main/res/layout/activity_acu_document_camera.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/acuantcamera/src/main/res/layout/activity_acu_mrz_camera.xml b/acuantcamera/src/main/res/layout/activity_acu_mrz_camera.xml
new file mode 100644
index 0000000..c0668b4
--- /dev/null
+++ b/acuantcamera/src/main/res/layout/activity_acu_mrz_camera.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/acuantcamera/src/main/res/layout/fragment_camera2_basic.xml b/acuantcamera/src/main/res/layout/fragment_camera2_basic.xml
index 3e06a4c..97a60a7 100644
--- a/acuantcamera/src/main/res/layout/fragment_camera2_basic.xml
+++ b/acuantcamera/src/main/res/layout/fragment_camera2_basic.xml
@@ -1,4 +1,5 @@
-