我目前正在使用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实例的方式。
我甚至尝试将其转换为不同的格式,例如从NV21
到JPEG
和东西,但它没有成功。我在这里缺少什么?
这是我用来从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,因为数据位于单个平面中。
你有没有尝试过样本camera2应用程序,Camera2Basic?它的saves JPEGs代码与你的代码非常相似,应该可以正常工作。
您的其他相机设置代码可能有错误,而不是保存部分本身。因此,请查看示例是否有效,然后比较它对代码的作用。