Сохранение изображения с камеры Android2 в формат PNG без потерь
Я пытаюсь сохранить изображения 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())
}
}
}
2 ответа
Вы хотите захватить данные в формате YUV_420_888; это то, с чего начинается компрессор JPEG в любом случае.
Вы должны будете преобразовать это в Растровое изображение RGB самостоятельно, для этого нет удобного метода.
RAW_SENSOR действительно сложно. Спецификации говорят нам, что параметры базовой мозаики Байера могут быть получены из CameraDevice
, но нет публичного API для преобразования в Bitmap
,
Во всяком случае, нет смысла запрашивать этот сложный формат, если ваша цель - преобразовать его в 8-битное для каждого канала растровое изображение.
Кроме того, ARGB_8888
Растровое изображение для захваченного изображения может быть огромным и приводить к нехватке памяти, если вы недостаточно осторожны.