将android camera2图像保存为无损PNG

Posted

技术标签:

【中文标题】将android camera2图像保存为无损PNG【英文标题】:Saving an android camera2 image to lossless PNG 【发布时间】:2018-07-25 16:31:49 【问题描述】:

我正在尝试将 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() / 1024k")
    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())
        
    

【问题讨论】:

你找到解决办法了吗? @Vikalp nope 没有好的选择。 :( 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

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

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

【讨论】:

以上是关于将android camera2图像保存为无损PNG的主要内容,如果未能解决你的问题,请参考以下文章

在Android camera2下将YUV_420_888转换为位图的图像不正确

如何在android中保存从相机拍摄的图像

如何在保持分辨率的同时将2D float numpy数组无损保存到灰度图像中?

将图保存为高分辨率或无损图像,可以放大而不像素化

Xamarin android Camera2 - 在 18:9 纵横比设备上拉伸图像预览

尝试使用 Android Camera2 API 捕获图像时出错:CaptureRequest 包含未配置的输入/输出表面