改一个版
This commit is contained in:
@@ -1,63 +1,72 @@
|
||||
package com.example.studentfaceregistry
|
||||
|
||||
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 androidx.camera.core.ExperimentalGetImage
|
||||
import androidx.camera.core.ImageProxy
|
||||
import java.io.ByteArrayOutputStream
|
||||
import kotlin.math.min
|
||||
|
||||
@ExperimentalGetImage
|
||||
object ImageUtils {
|
||||
fun imageProxyToBitmap(imageProxy: ImageProxy): Bitmap {
|
||||
val image = imageProxy.image ?: error("ImageProxy does not contain an image.")
|
||||
val nv21 = yuv420ToNv21(image)
|
||||
val yuvImage = YuvImage(nv21, ImageFormat.NV21, image.width, image.height, null)
|
||||
val output = ByteArrayOutputStream()
|
||||
yuvImage.compressToJpeg(Rect(0, 0, image.width, image.height), 90, output)
|
||||
val bitmap = BitmapFactory.decodeByteArray(output.toByteArray(), 0, output.size())
|
||||
val bitmap = yuv420ToBitmap(image)
|
||||
if (imageProxy.imageInfo.rotationDegrees == 0) {
|
||||
return bitmap
|
||||
}
|
||||
val matrix = Matrix().apply {
|
||||
postRotate(imageProxy.imageInfo.rotationDegrees.toFloat())
|
||||
}
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
|
||||
}
|
||||
|
||||
private fun yuv420ToNv21(image: Image): ByteArray {
|
||||
private fun yuv420ToBitmap(image: Image): Bitmap {
|
||||
val width = image.width
|
||||
val height = image.height
|
||||
val ySize = width * height
|
||||
val chromaSize = width * height / 4
|
||||
val nv21 = ByteArray(ySize + chromaSize * 2)
|
||||
copyPlane(image.planes[0], width, height, nv21, 0, 1)
|
||||
copyPlane(image.planes[2], width / 2, height / 2, nv21, ySize, 2)
|
||||
copyPlane(image.planes[1], width / 2, height / 2, nv21, ySize + 1, 2)
|
||||
return nv21
|
||||
}
|
||||
val yPlane = image.planes[0]
|
||||
val uPlane = image.planes[1]
|
||||
val vPlane = image.planes[2]
|
||||
|
||||
private fun copyPlane(
|
||||
plane: Image.Plane,
|
||||
width: Int,
|
||||
height: Int,
|
||||
output: ByteArray,
|
||||
offset: Int,
|
||||
outputPixelStride: Int
|
||||
) {
|
||||
val buffer = plane.buffer
|
||||
val row = ByteArray(plane.rowStride)
|
||||
var outputIndex = offset
|
||||
for (rowIndex in 0 until height) {
|
||||
val bytesToRead = min(plane.rowStride, buffer.remaining())
|
||||
buffer.get(row, 0, bytesToRead)
|
||||
for (colIndex in 0 until width) {
|
||||
val inputIndex = colIndex * plane.pixelStride
|
||||
if (inputIndex < bytesToRead && outputIndex < output.size) {
|
||||
output[outputIndex] = row[inputIndex]
|
||||
}
|
||||
outputIndex += outputPixelStride
|
||||
val yBuffer = yPlane.buffer
|
||||
val uBuffer = uPlane.buffer
|
||||
val vBuffer = vPlane.buffer
|
||||
val pixels = IntArray(width * height)
|
||||
|
||||
val yRowStride = yPlane.rowStride
|
||||
val yPixelStride = yPlane.pixelStride
|
||||
val uRowStride = uPlane.rowStride
|
||||
val uPixelStride = uPlane.pixelStride
|
||||
val vRowStride = vPlane.rowStride
|
||||
val vPixelStride = vPlane.pixelStride
|
||||
|
||||
var pixelIndex = 0
|
||||
for (row in 0 until height) {
|
||||
val yRow = row * yRowStride
|
||||
val uvRow = (row shr 1) * uRowStride
|
||||
val vvRow = (row shr 1) * vRowStride
|
||||
for (col in 0 until width) {
|
||||
val y = (yBuffer.get(yRow + col * yPixelStride).toInt() and 0xFF) - 16
|
||||
val u = (uBuffer.get(uvRow + (col shr 1) * uPixelStride).toInt() and 0xFF) - 128
|
||||
val v = (vBuffer.get(vvRow + (col shr 1) * vPixelStride).toInt() and 0xFF) - 128
|
||||
|
||||
val y1192 = 1192 * y.coerceAtLeast(0)
|
||||
var r = y1192 + 1634 * v
|
||||
var g = y1192 - 833 * v - 400 * u
|
||||
var b = y1192 + 2066 * u
|
||||
|
||||
r = r.coerceIn(0, 262143)
|
||||
g = g.coerceIn(0, 262143)
|
||||
b = b.coerceIn(0, 262143)
|
||||
|
||||
pixels[pixelIndex++] = -0x1000000 or
|
||||
((r shl 6) and 0x00FF0000) or
|
||||
((g shr 2) and 0x0000FF00) or
|
||||
((b shr 10) and 0x000000FF)
|
||||
}
|
||||
}
|
||||
|
||||
return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
|
||||
setPixels(pixels, 0, width, 0, 0, width, height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user