3

我正在尝试将 android.hardware.camera2 图像保存为无损格式。

我已经使用 scrounged 代码使其适用于 JPEG(有损)和 DMG(原始,但巨大且难以使用):

private fun save(image: Image, captureResult: TotalCaptureResult) {
    val fileWithoutExtension = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "myimage_${System.currentTimeMillis()}")
    val file: File = when (image.format) {
        ImageFormat.JPEG -> {
            val buffer = image.planes[0].buffer
            val bytes = ByteArray(buffer.remaining())
            buffer.get(bytes)
            val file = File("$fileWithoutExtension.jpg")
            file.writeBytes(bytes)
            file
        }
        ImageFormat.RAW_SENSOR -> {
            val dngCreator = DngCreator(mode.characteristics, captureResult)
            val file = File("$fileWithoutExtension.dmg")
            FileOutputStream(file).use { os ->
                dngCreator.writeImage(os, image)
            }
            file
        }
        else -> TODO("Unsupported image format: ${image.format}")
    }
    Log.i(TAG, "Wrote image:${file.canonicalPath} ${file.length() / 1024}k")
    image.close() // necessary when taking a few shots
}

但我坚持的是将 RAW_SENSOR 部分替换为可以保存为更合理 PNG 的内容。是吗

  1. 一个坏主意,因为 RAW_SENSOR 与普通图像格式如此不同,以至于我必须经历太多痛苦才能转换它?
  2. 一个坏主意,因为我应该设置上游捕捉来捕捉更合理的东西,比如 FLEX_RGB_888?
  3. 一个好主意,因为下面的代码中有一些愚蠢的错误?(与Buffer not large enough for pixels at android.graphics.Bitmap.copyPixelsFromBuffer(Bitmap.java:593)

我的尝试:

fun writeRawImageToPng(image: Image, pngFile: File) {
    Bitmap.createBitmap(image.width, image.height, Bitmap.Config.ARGB_8888).let { latestBitmap->
        latestBitmap.copyPixelsFromBuffer(image.planes[0].buffer!!)
        ByteArrayOutputStream().use { baos ->
            latestBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos)
            pngFile.writeBytes(baos.toByteArray())
        }
    }
}
4

2 回答 2

2

您要捕获 YUV_420_888 格式的数据;无论如何,这就是 JPEG 压缩器的开始。

但是,您必须自己将其转换为 RGB 位图 - 没有方便的方法。

于 2018-02-15T22:36:30.623 回答
2

RAW_SENSOR真的很难。规范告诉我们,可以从 中检索底层拜耳马赛克的参数CameraDevice,但没有公共 API 可以将其转换为Bitmap.

无论如何,如果您的目标是将其转换为每通道 8 位的位图,那么请求这种棘手的格式没有任何好处。

此外,ARGB_8888捕获图像的位图可能会很大,如果您不够小心,可能会导致内存不足。

于 2018-02-15T19:47:03.253 回答