java - Android:我们真的可以保存 ImageReader 的 acquireLatestImage() 吗?

标签 java android android-camera2

我目前正在使用 Camera2 API,并创建了一个新的 ImageReader.OnImageAvailableListener 对象。当然,它必须实现 onImageAvailable(ImageReader reader) 方法。我唯一想要的,就是从这个读者那里获取最新的图像,并保存它,但不幸的是,我就是无法获取它。看了很多源码,访问了不同的StackOverflow topcis,都没有找到答案。我现在正处于那个时候,当我不得不问:这个 Image 对象真的可以作为图像文件保存到手机的存储空间中吗?方法如下:

@Override
public void onImageAvailable(ImageReader reader) {

    Image image = reader.acquireLatestImage();

    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
    buffer.rewind();
    byte[] bytes = new byte[buffer.capacity()];
    buffer.get(bytes);

    save(bytes);

    image.close();

}

save() 方法仅打开一个 FileOutputStream 并将字节写入其中,它正在运行。问题是,我只得到一张黑色图像,而且它的尺寸非常小。

图像的格式是 JPEG,这是我之前配置 ImageReader 实例的方式。

我什至尝试将其转换为不同的格式,例如从 NV21JPEG 等等,但没有成功。我在这里缺少什么?

最佳答案

这是我用来从 Image 中提取 Bitmap 的类。

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.Image
import java.io.IOException
import java.io.InputStream
import java.nio.ByteBuffer
import kotlin.experimental.and

class ImagePreprocessor {
    private var rgbFrameBitmap = Bitmap.createBitmap(IMAGE_WIDTH, IMAGE_HEIGHT,
            Bitmap.Config.ARGB_8888)

    fun preprocessImage(image: Image?): Bitmap? {
        if (image == null) {
            return null
        }

        check(rgbFrameBitmap!!.width ==  image.width, { "Invalid size width" })
        check(rgbFrameBitmap!!.height == image.height, { "Invalid size height" })

        if (rgbFrameBitmap != null) {
            val bb = image.planes[0].buffer
            rgbFrameBitmap = BitmapFactory.decodeStream(ByteBufferBackedInputStream(bb))
        }

        return rgbFrameBitmap
    }

    private class ByteBufferBackedInputStream(internal var buf: ByteBuffer) : InputStream() {

        @Throws(IOException::class)
        override fun read(): Int {
            return if (!buf.hasRemaining()) {
                -1
            } else (buf.get() and 0xFF.toByte()).toInt()
        }

        @Throws(IOException::class)
        override fun read(bytes: ByteArray, off: Int, len: Int): Int {
            var len = len
            if (!buf.hasRemaining()) {
                return -1
            }

            len = Math.min(len, buf.remaining())
            buf.get(bytes, off, len)
            return len
        }
    }
}

我用它直接在 ImageView 上设置位图,但应该可以在 Bitmap 上使用 compress 方法将其保存到文件。请注意,这仅适用于 JPEG,因为数据位于单个平面中。

关于java - Android:我们真的可以保存 ImageReader 的 acquireLatestImage() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54813010/

相关文章:

android - 使用Android的相机拍摄灰度照片2

android - 在没有预览的情况下录制时,尺寸不在有效设置中

java - 关于 JavaBean

android - 带有图像列表的 ListView 无法在自定义适配器中正常工作以进行多项选择

java - 循环内打印问题 : for

android - 如何强制 Android 应用程序重新加载与语言更改对应的 Activity 标题?

android - 新手 : gallery show only one image each time

三星设备上的 Android 相机 API 图像模糊

java - 我如何禁止 Jetty 中的特定 SSL 协议(protocol)?

java - 从 json 数组中删除 json 对象