android - Android:从图像捕获中获取旧图像数据
问题描述
我有一个 android 应用程序,用于拍摄图像并通过 (W)Lan 将它们发送到远程 PC。
为此,我有两个功能来拍摄图像:
RAW 图像的一项功能:
fun takePhotoRAW(cmdDispatcher: CommandDispatcher) {
val rawImageList = ArrayList<Image>()
rawImageReader.setOnImageAvailableListener({ reader ->
rawImageList.add(reader.acquireLatestImage())
}, null)
val captureRequest = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
addTarget(rawImageReader.surface)
}
setSingleCaptureRequestSettings(captureRequest)
session.captureSingleRequest(captureRequest.build(), cameraExecutor, object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureStarted(session: CameraCaptureSession, request: CaptureRequest, timestamp: Long, frameNumber: Long) {
super.onCaptureStarted(session, request, timestamp, frameNumber)
CoroutineScope(Dispatchers.Main).launch {
logger.log("Capturing RAW image...")
}
}
override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
super.onCaptureCompleted(session, request, result)
var cnt = 0
while (rawImageList.size < 1) {
runBlocking {
delay(10)
}
if (cnt++ > 100) break
}
if (rawImageList.size > 0) {
val dngCreator = DngCreator(characteristics, result)
val stream = ByteArrayOutputStream()
dngCreator.writeImage(stream, rawImageList.first())
rawImageList.first().close()
rawImageList.clear()
logger.log("RAW Image Captured. Sending to client...")
CoroutineScope(Dispatchers.IO).launch {
cmdDispatcher.sendImageToClient(stream.toByteArray(), NetworkCommandTypeEnum.IMAGERAW)
}
} else {
logger.log("RAW Image Capture failed...")
CoroutineScope(Dispatchers.IO).launch {
cmdDispatcher.sendFailedCommand()
}
}
}
})
}
一个用于 JPEG 图像:
fun takePhotoJPEG(cmdDispatcher: CommandDispatcher) {
val jpegImageList = ArrayList<Image>()
jpegImageReader.setOnImageAvailableListener({ reader ->
jpegImageList.add(reader.acquireLatestImage())
}, null)
val captureRequest = camera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE).apply {
addTarget(jpegImageReader.surface)
}
setSingleCaptureRequestSettings(captureRequest)
session.captureSingleRequest(captureRequest.build(), cameraExecutor, object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureStarted(session: CameraCaptureSession, request: CaptureRequest, timestamp: Long, frameNumber: Long) {
super.onCaptureStarted(session, request, timestamp, frameNumber)
logger.log("Capturing JPEG image...")
}
override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
super.onCaptureCompleted(session, request, result)
var cnt = 0
while (jpegImageList.size < 1) {
runBlocking {
delay(10)
}
if (cnt++ > 100) break
}
if (jpegImageList.size > 0) {
val jpegbuffer = jpegImageList.first().planes[0].buffer
val bytes = ByteArray(jpegbuffer.remaining())
jpegbuffer.get(bytes, 0, jpegbuffer.remaining())
jpegImageList.first().close()
jpegImageList.clear()
logger.log("JPEG Image Captured. Sending to client...")
CoroutineScope(Dispatchers.IO).launch {
cmdDispatcher.sendImageToClient(bytes, NetworkCommandTypeEnum.IMAGEJPEG)
}
} else {
logger.log("JPEG Image Capture failed...")
CoroutineScope(Dispatchers.IO).launch {
cmdDispatcher.sendFailedCommand()
}
}
}
})
}
这些功能中的每一个都可以单独工作,但是由于某种原因,如果我按以下顺序拍摄图像:
- 生的
- JPEG
- 生的
第二张 RAW 图像包含与第一张相同的图像数据。此时我必须重新启动应用程序,以便能够再次拍摄不同的 RAW 图像。JPEG 图像仍然可以正常工作。
但是,如果我按此顺序拍摄图像:
- 生的
- 生的
- 生的
正如预期的那样,我得到了三个不同的 RAW 图像。不知何故,拍摄 JPEG 图像会扰乱原始图像的捕获......
编辑:(试图回答评论问题):
这两个函数的调用方法如下:
private fun takePhoto(type: String) {
when (type) {
"RAW" -> cameraManager.takePhotoRAW(this)
"JPEG" -> cameraManager.takePhotoJPEG(this)
else -> return
}
}
图像之间的最短时间基本上是图像通过网络发送到客户端所需的时间:客户端机器请求图像,一旦它收到图像,它就会请求下一个图像。但是,我也可以手动触发请求,调用这两个函数之间的时间似乎没有影响(测试从立即到 10+ 秒)。
解决方案
推荐阅读
- c# - 如何与 EF Core 建立关系 (0,N:1,1)?
- python - 首先根据长度对字符串元素列表进行排序,然后根据字母顺序对具有匹配长度的元素进行排序
- c# - 将键值对的 SQL 行序列化为 JSON 对象
- javascript - 反应原生不显示导入的标签
- algorithm - 计算到平面子集边缘的距离的有效方法(仅限整数坐标)
- java - 在输入正确的输入之前,如何不让用户继续前进?
- javascript - 通过单击按钮更改背景颜色
- android - 从数据库获取数据后如何匹配指纹
- tensorflow - 如何通过TensorFlow手动计算神经网络中多个中间梯度的最终梯度?
- javascript - 反应触发键盘事件