使用 Camera2 拍一张 dng 图片 API
Taking a dng picture using the Camera2 API
我正在创建一个应用程序,它以 .dng 格式拍摄照片以便对其进行处理。我正在使用 camera2 API。我能够拍照并将它们保存到我的 phone 中,但格式为 .jpg。但是当我更改我的代码以使用 .dng 扩展名保存它们时,它编译,在我的 phone 上显示预览,但是当拍照时,我得到一个错误。我的代码中拍摄和保存图片的部分如下。
val reader = ImageReader.newInstance(1280, 720, ImageFormat.RAW_SENSOR, 1)
val outputSurfaces = ArrayList<Surface>(2)
outputSurfaces.add(reader.surface)
outputSurfaces.add(Surface(previewTextureView.surfaceTexture))
val captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureBuilder.addTarget(reader.surface)
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO)
val file = File("myPath/myImageName.dng")
var captureResult: CaptureResult? = null
还有我的听众:
val readerListener = object : ImageReader.OnImageAvailableListener {
override fun onImageAvailable(reader: ImageReader) {
var image: Image? = null
var output: OutputStream? = null
val dngCreator = DngCreator(cameraManager.getCameraCharacteristics("0"), captureResult)
try {
image = reader.acquireLatestImage()
output = FileOutputStream(file)
dngCreator.writeImage(output, image)
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} finally {
output?.close()
image?.close()
}
}
}
reader.setOnImageAvailableListener(readerListener, backgroundHandler)
val captureListener = object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
captureResult = result
super.onCaptureCompleted(session, request, result)
}
}
最后我捕获了会话:
cameraDevice.createCaptureSession(outputSurfaces, object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
try {
session.capture(captureBuilder.build(), captureListener, backgroundHandler)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun onConfigureFailed(session: CameraCaptureSession) {}
}, backgroundHandler)
当我将图像保存为 jpeg 时,出现了一个警告和一个以前没有的错误:
W/CameraDevice-JV-0: Stream configuration failed due to: createSurfaceFromGbp:1106: Camera 0: No supported stream configurations with format 0x20 defined, failed to create output stream
E/CameraCaptureSession: Session 1: Failed to create capture session; configuration failed
我为了保存 dng 文件所做的更改是:
- 我用
ImageFormat.RAW_SENSOR
替换了ImageFormat.JPEG
- 我将文件扩展名从 .jpg 更改为 .dng
- 我没有使用
dngCreator.writeImage(output, image)
,而是使用了 :
val buffer = image!!.planes[0].buffer
val bytes = ByteArray(buffer.capacity())
buffer.get(bytes)
output.write()
由于没有太多关于这个主题的信息,我不确定我的实现是否正确。
经过一些研究,我找到了一个实现,以便将使用 Camera2API 拍摄的图像保存在 .dng 文件中:
if (mImage.format == ImageFormat.RAW_SENSOR) {
val dngCreator = DngCreator(mCharacteristics, mCaptureResult)
var output: FileOutputStream? = null
try {
output = FileOutputStream(mFile)
dngCreator.writeImage(output, mImage)
} catch (e: IOException) {
e.printStackTrace()
} finally {
mImage.close()
closeOutput(output)
}
}
其中:
mCharacteristics
是 CameraCharacteristics
,即描述 CameraDevice
的属性
mCaptureResult
由 CameraDevice
在处理 CaptureRequest
后生成
mImage
是函数 dequeuAndSaveImage
中检索到的图像: image = reader.get()!!.acquireNextImage()
mFile
是保存图像的文件,例如:
mFile = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"RAW_" + generateTimestamp()+ ".dng"
也许它会对某些人有所帮助,但正如@Alex Cohn 所说,建议从官方样本开始github.com/googlesamples/android-Camera2Raw。它是用 Java 而不是 Kotlin 编写的,但如果需要的话,转换它并不难。
这有点旧 post 但是对于原始图像,您不能将分辨率设置为任意值。假设您的设备可以进行 raw_sensor 读取,则必须将其设置为传感器尺寸。你需要做这样的事情。
val largestRaw = Collections.max(Arrays.asList(*map.getOutputSizes(ImageFormat.RAW_SENSOR)), CompareSizesByArea())
rawImageReader = ImageReader.newInstance(largestRaw.width, largestRaw.height, ImageFormat.RAW_SENSOR, /*maxImages*/ 5).apply { setOnImageAvailableListener(onRawImageAvailableListener, backgroundHandler) }
不幸的是,在 kotlin 中我现在遇到了:
java.lang.IllegalArgumentException:缺少标记 AsShotNeutral (c628) 的元数据字段
上面列出的过时的 java Camera2Raw 示例确实有效。
我正在创建一个应用程序,它以 .dng 格式拍摄照片以便对其进行处理。我正在使用 camera2 API。我能够拍照并将它们保存到我的 phone 中,但格式为 .jpg。但是当我更改我的代码以使用 .dng 扩展名保存它们时,它编译,在我的 phone 上显示预览,但是当拍照时,我得到一个错误。我的代码中拍摄和保存图片的部分如下。
val reader = ImageReader.newInstance(1280, 720, ImageFormat.RAW_SENSOR, 1)
val outputSurfaces = ArrayList<Surface>(2)
outputSurfaces.add(reader.surface)
outputSurfaces.add(Surface(previewTextureView.surfaceTexture))
val captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureBuilder.addTarget(reader.surface)
captureBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO)
val file = File("myPath/myImageName.dng")
var captureResult: CaptureResult? = null
还有我的听众:
val readerListener = object : ImageReader.OnImageAvailableListener {
override fun onImageAvailable(reader: ImageReader) {
var image: Image? = null
var output: OutputStream? = null
val dngCreator = DngCreator(cameraManager.getCameraCharacteristics("0"), captureResult)
try {
image = reader.acquireLatestImage()
output = FileOutputStream(file)
dngCreator.writeImage(output, image)
} catch (e: FileNotFoundException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} finally {
output?.close()
image?.close()
}
}
}
reader.setOnImageAvailableListener(readerListener, backgroundHandler)
val captureListener = object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
captureResult = result
super.onCaptureCompleted(session, request, result)
}
}
最后我捕获了会话:
cameraDevice.createCaptureSession(outputSurfaces, object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
try {
session.capture(captureBuilder.build(), captureListener, backgroundHandler)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun onConfigureFailed(session: CameraCaptureSession) {}
}, backgroundHandler)
当我将图像保存为 jpeg 时,出现了一个警告和一个以前没有的错误:
W/CameraDevice-JV-0: Stream configuration failed due to: createSurfaceFromGbp:1106: Camera 0: No supported stream configurations with format 0x20 defined, failed to create output stream
E/CameraCaptureSession: Session 1: Failed to create capture session; configuration failed
我为了保存 dng 文件所做的更改是:
- 我用
ImageFormat.RAW_SENSOR
替换了 - 我将文件扩展名从 .jpg 更改为 .dng
- 我没有使用
dngCreator.writeImage(output, image)
,而是使用了 :
ImageFormat.JPEG
val buffer = image!!.planes[0].buffer
val bytes = ByteArray(buffer.capacity())
buffer.get(bytes)
output.write()
由于没有太多关于这个主题的信息,我不确定我的实现是否正确。
经过一些研究,我找到了一个实现,以便将使用 Camera2API 拍摄的图像保存在 .dng 文件中:
if (mImage.format == ImageFormat.RAW_SENSOR) {
val dngCreator = DngCreator(mCharacteristics, mCaptureResult)
var output: FileOutputStream? = null
try {
output = FileOutputStream(mFile)
dngCreator.writeImage(output, mImage)
} catch (e: IOException) {
e.printStackTrace()
} finally {
mImage.close()
closeOutput(output)
}
}
其中:
mCharacteristics
是CameraCharacteristics
,即描述CameraDevice
的属性
mCaptureResult
由CameraDevice
在处理CaptureRequest
后生成
mImage
是函数dequeuAndSaveImage
中检索到的图像:image = reader.get()!!.acquireNextImage()
mFile
是保存图像的文件,例如:
mFile = Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"RAW_" + generateTimestamp()+ ".dng"
也许它会对某些人有所帮助,但正如@Alex Cohn 所说,建议从官方样本开始github.com/googlesamples/android-Camera2Raw。它是用 Java 而不是 Kotlin 编写的,但如果需要的话,转换它并不难。
这有点旧 post 但是对于原始图像,您不能将分辨率设置为任意值。假设您的设备可以进行 raw_sensor 读取,则必须将其设置为传感器尺寸。你需要做这样的事情。
val largestRaw = Collections.max(Arrays.asList(*map.getOutputSizes(ImageFormat.RAW_SENSOR)), CompareSizesByArea())
rawImageReader = ImageReader.newInstance(largestRaw.width, largestRaw.height, ImageFormat.RAW_SENSOR, /*maxImages*/ 5).apply { setOnImageAvailableListener(onRawImageAvailableListener, backgroundHandler) }
不幸的是,在 kotlin 中我现在遇到了:
java.lang.IllegalArgumentException:缺少标记 AsShotNeutral (c628) 的元数据字段
上面列出的过时的 java Camera2Raw 示例确实有效。