将一个Android camera2图像保存为无损PNG

3

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

我已经成功地使用一些代码片段将其保存为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())
        }
    }
}

你找到任何解决方案了吗? - Vikalp
@Vikalp 没有好的选择。:( - Benjamin H
2个回答

2
RAW_SENSOR”真的很困难。规格告诉我们,底层 Bayer Mosaic 的参数可以从“CameraDevice”中检索,但没有公共 API 将其转换为“Bitmap”。
无论如何,如果您的目标是将其转换为每通道 8 位的位图,则请求此复杂格式没有任何优势。
此外,捕获图像的“ARGB_8888”位图可能非常大,并且如果不够小心可能会导致内存不足。

2

您想捕获YUV_420_888格式的数据;不管怎样,这就是JPEG压缩器的起点。

然而,您必须自己将其转换为RGB位图 - 没有方便的方法可用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接