Skip to content

Instantly share code, notes, and snippets.

@ryohji
Last active December 13, 2019 11:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryohji/7f124a7759eae1a70f48f63d4cb4f07a to your computer and use it in GitHub Desktop.
Save ryohji/7f124a7759eae1a70f48f63d4cb4f07a to your computer and use it in GitHub Desktop.
Convert `YUV_420_888` format image (from Android Camera2 API) into Jpeg ByteArray (can be used with BitmapFactory.decodeByteArray)
import android.graphics.ImageFormat.NV21
import android.graphics.Rect
import android.graphics.YuvImage
import android.media.Image
import java.io.ByteArrayOutputStream
object Converter {
fun jpegByteArrayFrom(yuv420_888: Image): ByteArray =
yuv420_888.nv21ByteArray
.let { YuvImage(it, NV21, yuv420_888.width, yuv420_888.height, null) }
.getJpegDataWithQuality(100)
private val Image.nv21ByteArray
get() = ByteArray(width * height * 3 / 2).also {
val vPlane = planes[2]
val y = planes[0].buffer.apply { rewind() }
val u = planes[1].buffer.apply { rewind() }
val v = vPlane.buffer.apply { rewind() }
y.get(it, 0, y.capacity()) // copy Y components
if (vPlane.pixelStride == 2) {
// Both of U and V are interleaved data, so copying V makes VU series but last U
v.get(it, y.capacity(), v.capacity())
it[it.size - 1] = u.get(u.capacity() - 1) // put last U
} else { // vPlane.pixelStride == 1
var offset = it.size - 1
var i = v.capacity()
while (i-- != 0) { // make VU interleaved data into ByteArray
it[offset - 0] = u[i]
it[offset - 1] = v[i]
offset -= 2
}
}
}
private fun YuvImage.getJpegDataWithQuality(quality: Int) =
ByteArrayOutputStream().also {
compressToJpeg(Rect(0, 0, width, height), quality, it)
}.toByteArray()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment