I am experimenting with Googles CameraX sample app (CameraXBasic, can be found on Github) and would like to capture the image as a Bitmap to be able to make some modifications to the image before saving it. Does anyone have a suggestion on how to achieve this?
Please see below Google's original code to capture and save the image:
// Listener for button used to capture photo
controls.findViewById<ImageButton>(R.id.camera_capture_button).setOnClickListener {
// Get a stable reference of the modifiable image capture use case
imageCapture?.let { imageCapture ->
// Create output file to hold the image
val photoFile = createFile(outputDirectory, FILENAME, PHOTO_EXTENSION)
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile)
.build()
// Setup image capture listener which is triggered after photo has been taken
imageCapture.takePicture(
outputOptions, cameraExecutor, object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = output.savedUri ?: Uri.fromFile(photoFile)
Log.d(TAG, "Photo capture succeeded: $savedUri")
// We can only change the foreground Drawable using API level 23+ API
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Update the gallery thumbnail with latest picture taken
setGalleryThumbnail(savedUri)
}
// Implicit broadcasts will be ignored for devices running API level >= 24
// so if you only target API level 24+ you can remove this statement
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
requireActivity().sendBroadcast(
Intent(android.hardware.Camera.ACTION_NEW_PICTURE, savedUri)
)
}
// If the folder selected is an external media directory, this is
// unnecessary but otherwise other apps will not be able to access our
// images unless we scan them using [MediaScannerConnection]
val mimeType = MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(savedUri.toFile().extension)
MediaScannerConnection.scanFile(
context,
arrayOf(savedUri.toFile().absolutePath),
arrayOf(mimeType)
) { _, uri ->
Log.d(TAG, "Image capture scanned into media store: $uri")
}
}
})
}
// We can only change the foreground Drawable using API level 23+ API
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Display flash animation to indicate that photo was captured
container.postDelayed({
container.foreground = ColorDrawable(Color.WHITE)
container.postDelayed(
{ container.foreground = null }, ANIMATION_FAST_MILLIS)
}, ANIMATION_SLOW_MILLIS)
}
}
Thanks in advance for your help :)
To get an in-memory captured image, use ImageCapture. takePicture(executor, OnImageCapturedCallback) , if the image is successfully captured, onCaptureSuccess() is called with an ImageProxy that wraps the capture image. Make sure to close it before returning from the method.
image capture (image acquisition) The process of obtaining a digital image from a vision sensor, such as a camera. Usually this entails a hardware interface known as a frame grabber, which captures single frames of video, converts the analogue values to digital, and feeds the result into the computer memory.
The image capture use case is designed for capturing high-resolution, high-quality photos and provides auto-white-balance, auto-exposure, and auto-focus (3A) functionality, in addition to simple manual camera controls.
There is another callback OnImageCapturedCallback
available for takePicture
which return ImageProxy
in onCaptureSuccess
, You can get bitmap from that ImageProxy
object
imageCapture.takePicture(cameraExecutor, object :
ImageCapture.OnImageCapturedCallback() {
override fun onCaptureSuccess(image: ImageProxy) {
//get bitmap from image
val bitmap = imageProxyToBitmap(image)
super.onCaptureSuccess(image)
}
override fun onError(exception: ImageCaptureException) {
super.onError(exception)
}
})
/**
* convert image proxy to bitmap
* @param image
*/
private fun imageProxyToBitmap(image: ImageProxy): Bitmap {
val planeProxy = image.planes[0]
val buffer: ByteBuffer = planeProxy.buffer
val bytes = ByteArray(buffer.remaining())
buffer.get(bytes)
return BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With