Android:我们可以实际保存ImageReader acquireLatestImage()吗?

问题描述 投票:1回答:2

我目前正在使用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和东西,但它没有成功。我在这里缺少什么?

java android android-camera2
2个回答
0
投票

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

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上设置位图,但应该可以在compress上使用Bitmap方法将其保存到文件中。请注意,这仅适用于JPEG,因为数据位于单个平面中。


0
投票

你有没有尝试过样本camera2应用程序,Camera2Basic?它的saves JPEGs代码与你的代码非常相似,应该可以正常工作。

您的其他相机设置代码可能有错误,而不是保存部分本身。因此,请查看示例是否有效,然后比较它对代码的作用。

© www.soinside.com 2019 - 2024. All rights reserved.