Files
MrleeAdmin/frontend/app/uni_modules/mas-code-scan/utssdk/app-android/YuvFrames.kt
T

137 lines
4.6 KiB
Kotlin

package uts.sdk.modules.masCodeScan
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.ImageFormat
import android.graphics.Matrix
import android.graphics.Rect
import android.graphics.YuvImage
import android.media.Image
import java.io.ByteArrayOutputStream
object YuvFrames {
fun imageToBitmap(
image: Image,
width: Int,
height: Int,
cropRect: Rect,
rotationDegrees: Int
): Bitmap? {
return try {
val planes = image.planes
val yPlane = planes[0]
val uPlane = planes[1]
val vPlane = planes[2]
val yRowStride = yPlane.rowStride
val yPixelStride = yPlane.pixelStride
val uRowStride = uPlane.rowStride
val uPixelStride = uPlane.pixelStride
val vRowStride = vPlane.rowStride
val vPixelStride = vPlane.pixelStride
val nv21Size = width * height * 3 / 2
val nv21 = ByteArray(nv21Size)
var destOffset = 0
if (yPixelStride == 1) {
for (row in 0 until height) {
yPlane.buffer.position(row * yRowStride)
yPlane.buffer.get(nv21, destOffset, width)
destOffset += width
}
} else {
val yBuffer = yPlane.buffer
for (row in 0 until height) {
for (col in 0 until width) {
nv21[destOffset++] = yBuffer.get(row * yRowStride + col * yPixelStride)
}
}
}
var uvOffset = width * height
if (uPixelStride == 1 && vPixelStride == 1) {
for (row in 0 until height / 2) {
vPlane.buffer.position(row * vRowStride)
vPlane.buffer.get(nv21, uvOffset + row * width, width / 2)
}
for (row in 0 until height / 2) {
uPlane.buffer.position(row * uRowStride)
uPlane.buffer.get(nv21, uvOffset + width / 2 + row * width, width / 2)
}
} else {
val uBuffer = uPlane.buffer
val vBuffer = vPlane.buffer
for (row in 0 until height / 2) {
for (col in 0 until width / 2) {
val uvIndex = row * uRowStride + col * uPixelStride
nv21[uvOffset++] = vBuffer.get(uvIndex)
nv21[uvOffset++] = uBuffer.get(uvIndex)
}
}
}
val safeCropRect = Rect(cropRect).apply {
left = left.coerceIn(0, width)
top = top.coerceIn(0, height)
right = right.coerceIn(left, width)
bottom = bottom.coerceIn(top, height)
}
val jpegRect = if (safeCropRect.width() > 0 && safeCropRect.height() > 0) {
safeCropRect
} else {
Rect(0, 0, width, height)
}
val yuvImage = YuvImage(nv21, ImageFormat.NV21, width, height, null)
val baos = ByteArrayOutputStream()
yuvImage.compressToJpeg(jpegRect, 85, baos)
val jpegData = baos.toByteArray()
baos.close()
var bitmap = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.size)
if (bitmap != null && rotationDegrees != 0) {
val matrix = Matrix()
matrix.postRotate(rotationDegrees.toFloat())
val rotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
if (rotated != bitmap) {
bitmap.recycle()
}
bitmap = rotated
}
bitmap
} catch (_: Exception) {
null
}
}
fun rectToVisualSpace(
rect: Rect,
sourceWidth: Int,
sourceHeight: Int,
rotationDegrees: Int
): Rect {
return when (rotationDegrees) {
90 -> Rect(
sourceHeight - rect.bottom,
rect.left,
sourceHeight - rect.top,
rect.right
)
180 -> Rect(
sourceWidth - rect.right,
sourceHeight - rect.bottom,
sourceWidth - rect.left,
sourceHeight - rect.top
)
270 -> Rect(
rect.top,
sourceWidth - rect.right,
rect.bottom,
sourceWidth - rect.left
)
else -> Rect(rect)
}
}
}