我正在尝试将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文件上。这是因为:
- 它是一个坏主意,因为RAW_SENSOR与普通图像格式非常不同,我必须通过太多的痛苦进行转换。
- 它是一个坏主意,因为我应该将上游捕获设置为捕获更合理的内容,如FLEX_RGB_888。
- 它是一个好主意,因为以下代码中存在一些愚蠢的错误?(这个错误导致
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())
}
}
}