package com.example.smtias_capture
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 java.io.ByteArrayOutputStream
/**
* YUV_420_888 のプレーンデータを NV21 経由で JPEG に変換するユーティリティ.
*
* ライブプレビューのスナップショット保存に使用する(撮影本体の RAW とは独立).
* 回転・左右反転にも対応する.
*/
internal object YuvJpegConverter {
/**
* YUV_420_888 のプレーン群を JPEG バイト列に変換する.
*
* [rotation] は時計回りの度数,[mirror] が true なら左右反転を適用する.
*/
fun convert(
width: Int,
height: Int,
yPlane: ByteArray,
uPlane: ByteArray,
vPlane: ByteArray,
yRowStride: Int,
uvRowStride: Int,
uvPixelStride: Int,
rotation: Int,
mirror: Boolean,
quality: Int,
): ByteArray {
// YUV_420_888 → NV21 変換
val nv21 = ByteArray(width * height * 3 / 2)
// Y プレーンをコピー
for (row in 0 until height) {
System.arraycopy(yPlane, row * yRowStride, nv21, row * width, width)
}
// UV プレーンを NV21 形式(VUVU...)にインターリーブ
val uvOffset = width * height
for (row in 0 until height / 2) {
for (col in 0 until width / 2) {
val uvIndex = row * uvRowStride + col * uvPixelStride
nv21[uvOffset + row * width + col * 2] = vPlane[uvIndex]
nv21[uvOffset + row * width + col * 2 + 1] = uPlane[uvIndex]
}
}
// NV21 → JPEG
val yuvImage = YuvImage(nv21, ImageFormat.NV21, width, height, null)
val jpegStream = ByteArrayOutputStream()
yuvImage.compressToJpeg(Rect(0, 0, width, height), quality, jpegStream)
// 回転・反転が必要な場合
return if (rotation != 0 || mirror) {
val bitmap = BitmapFactory.decodeByteArray(jpegStream.toByteArray(), 0, jpegStream.size())
val matrix = Matrix()
if (rotation != 0) matrix.postRotate(rotation.toFloat())
if (mirror) matrix.postScale(-1f, 1f)
val transformed = Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
bitmap.recycle()
val outStream = ByteArrayOutputStream()
transformed.compress(Bitmap.CompressFormat.JPEG, quality, outStream)
transformed.recycle()
outStream.toByteArray()
} else {
jpegStream.toByteArray()
}
}
}