FrameUtil

object FrameUtil

Utility class for interacting with Frame and FrameImage instances.

Samples

import android.graphics.ImageFormat
import android.hardware.Camera
import android.media.Image
import android.util.Size
import androidx.camera.core.ImageProxy
import com.miteksystems.misnap.controller.MiSnapController
import com.miteksystems.misnap.core.Frame
import com.miteksystems.misnap.core.FrameImage
import com.miteksystems.misnap.core.FrameUtil
fun main() { 
   //sampleStart 
   /**
 * This is a series of examples to demonstrate different ways of building a [Frame] instance that can
 * then be analyzed by the [MiSnapController] with the different MiSnap SDK sciences.
 *
 * @see [FrameImage] and [FrameImage.Plane] helper classes for the full list of properties that the
 * Camera2 and CameraX generated frames should be mapped to in order to build a [Frame].
 * @see [FrameUtil] for the full list of helper methods to create or manipulate [Frame] objects.
 */
private class FrameFromNativeCamera {
    /**
     * Convert a Camera API preview frame into a [Frame] object by mapping the Camera1 frame properties to
     * the corresponding MiSnap SDK frame properties. The Camera1 frame data can be mapped directly to
     * a [Frame] object without requiring extra format conversions.
     * NOTE: Camera1 does not calculate the rotation degrees of the frame, you must calculate it and
     *  use it while building a [Frame].
     *
     * @see [Camera.PreviewCallback] for more information about the data and format received from
     * the Camera1 API.
     */
    fun camera1toFrame(bytes: ByteArray, width: Int, height: Int, imageFormat: Int) =
        object : Frame {
            override val imageSize = Size(width, height)

            override val imageFormat = imageFormat

            // Use the actual rotation derived from the camera and the device orientations.
            override val rotationDegrees = 0

            override val imageBytes = bytes

            override fun close() {

            }
        }

    /**
     * Convert a Camera2 API preview frame into a [Frame] object by mapping the [Image] properties to
     * the corresponding MiSnap SDK frame properties. The [FrameUtil] helper methods are used since
     * the Camera2 output can't be directly converted into a [Frame] object.
     * NOTE: NOTE: Camera2 does not calculate the rotation degrees of the frame, you must calculate it and
     *  use it while building a [Frame].
     */
    fun camera2ToFrame(image: Image) = object : Frame {
        override val imageSize = Size(image.width, image.height)

        override val imageFormat =
            if (image.format == ImageFormat.YUV_420_888) ImageFormat.NV21 else image.format

        // Use the actual rotation derived from the camera and the device orientations.
        override val rotationDegrees = 0

        override val imageBytes =
            when (image.format) {
                ImageFormat.YUV_420_888 -> FrameUtil.yuv420ToNv21(imageToFrameImage(image))
                ImageFormat.JPEG -> FrameUtil.stripChannelPadding(
                    image.planes[0].buffer,
                    image.width,
                    image.height,
                    0,
                    1
                )
                else -> byteArrayOf()
            }

        override fun close() {
            image.close()
        }
    }

    /**
     * Convert a CameraX API preview frame into a [Frame] object by mapping the [ImageProxy] properties to
     * the corresponding MiSnap SDK frame properties. The [FrameUtil] helper methods are used since
     * the CameraX output can't be directly converted into a [Frame] object.
     */
    fun cameraxToFrame(imageProxy: ImageProxy) = object : Frame {
        override val imageSize = Size(imageProxy.width, imageProxy.height)

        override val imageFormat =
            if (imageProxy.format == ImageFormat.YUV_420_888) ImageFormat.NV21 else imageProxy.format

        override val rotationDegrees = imageProxy.imageInfo.rotationDegrees

        override val imageBytes =
            when (imageProxy.format) {
                ImageFormat.YUV_420_888 -> FrameUtil.yuv420ToNv21(imageProxyToFrameImage(imageProxy))
                ImageFormat.JPEG -> FrameUtil.stripChannelPadding(
                    imageProxy.planes[0].buffer,
                    imageProxy.width,
                    imageProxy.height,
                    0,
                    1
                )
                else -> byteArrayOf()
            }

        override fun close() {
            imageProxy.close()
        }
    }

    /**
     * Helper method to map the data from a Camera2 [Image] into a [FrameImage] to make the conversion
     * into a [Frame] easier.
     */
    private fun imageToFrameImage(image: Image) = object : FrameImage {
        override val format = image.format
        override val width = image.width
        override val height = image.height
        override val planes: Array<FrameImage.Plane> =
            image.planes.map { imagePlaneToFrameImagePlane(it) }.toTypedArray()
    }

    /**
     * Helper method to map the data from a Camera2 [Image.Plane] into a [FrameImage.Plane] to make
     * the conversion into a [Frame] easier.
     */
    private fun imagePlaneToFrameImagePlane(plane: Image.Plane) =
        object : FrameImage.Plane {
            override val byteBuffer = plane.buffer
            override val rowStride = plane.rowStride
            override val pixelStride = plane.pixelStride
        }

    /**
     * Helper method to map the data from a CameraX [ImageProxy] into a [FrameImage] to make the conversion
     * into a [Frame] easier.
     */
    private fun imageProxyToFrameImage(imageProxy: ImageProxy) = object : FrameImage {
        override val format = imageProxy.format
        override val width = imageProxy.width
        override val height = imageProxy.height
        override val planes: Array<FrameImage.Plane> =
            imageProxy.planes.map { planeProxyToFrameImagePlane(it) }.toTypedArray()
    }

    /**
     * Helper method to map the data from a CameraX [ImageProxy.PlaneProxy] into a [FrameImage.Plane] to make
     * the conversion into a [Frame] easier.
     */
    private fun planeProxyToFrameImagePlane(planeProxy: ImageProxy.PlaneProxy) =
        object : FrameImage.Plane {
            override val byteBuffer = planeProxy.buffer
            override val rowStride = planeProxy.rowStride
            override val pixelStride = planeProxy.pixelStride
        }
} 
   //sampleEnd
}

Functions

Link copied to clipboard
fun bitmapToJpg(bitmap: Bitmap, quality: Int): ByteArray
Link copied to clipboard
Link copied to clipboard
fun decodeJpgFrame(jpg: Frame, forceGray: Boolean = false): Frame?
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
fun rotateAndCompressJpgFrame(frame: Frame, rotationDegrees: Int, quality: Int, redactionRects: List<Rect> = emptyList()): ByteArray

Encodes a JPEG image using a Frame as source while adjusting the image for rotation, quality and redaction.

Link copied to clipboard
fun stripChannelPadding(channel: ByteBuffer, width: Int, height: Int, padding: Int, pixelStride: Int): ByteArray
fun stripChannelPadding(channel: ByteArray, width: Int, height: Int, padding: Int, pixelStride: Int, arrayOffset: Int, arraySize: Int): ByteArray
Link copied to clipboard

Properties

Link copied to clipboard
@get:JvmName(name = "isLibraryLoaded")
val libraryLoaded: Boolean