I was trying to get high resolution images with cameraX implementation. With below code I was able to see that for back camera of the device I tested an entry with resolution of 4000x3000.
@RequiresApi(Build.VERSION_CODES.M)
fun getPossibleOutputSizes(id: String) {
val cameraManager = context?.getSystemService(Context.CAMERA_SERVICE) as CameraManager
val sizes = cameraManager?.getCameraCharacteristics(id)?.get(SCALER_STREAM_CONFIGURATION_MAP)?.getHighResolutionOutputSizes(ImageFormat.JPEG)
if (sizes != null) {
println("got possible resolutions:")
println(sizes.joinToString("\n"))
}
}
Below is the code for setting up camera. This is a sample app I used to check the output resolution provided by cameraX takePhoto calls.
/** Declare and bind preview, capture and analysis use cases */
@SuppressLint("RestrictedApi", "ServiceCast", "UnsafeOptInUsageError")
private fun bindCameraUseCases() {
// Get screen metrics used to setup camera for full screen resolution
val metrics = windowManager.getCurrentWindowMetrics().bounds
Log.d(TAG, "Screen metrics: ${metrics.width()} x ${metrics.height()}")
val screenAspectRatio = aspectRatio(metrics.width(), metrics.height())
Log.d(TAG, "Preview aspect ratio: $screenAspectRatio")
val rotation = fragmentCameraBinding.viewFinder.display.rotation
// CameraProvider
val cameraProvider = cameraProvider
?: throw IllegalStateException("Camera initialization failed.")
// CameraSelector
var cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
selectExternalOrBestCamera(cameraProvider)?.let { returnedCameraSelector ->
cameraSelector = returnedCameraSelector
}
// Preview
preview = Preview.Builder()
// We request aspect ratio but no resolution
.setTargetAspectRatio(screenAspectRatio)//either RATIO_4_3 or RATIO_16_9
// Set initial target rotation
.setTargetRotation(rotation)
.build()
// ImageCapture
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_ZERO_SHUTTER_LAG)
// We request aspect ratio but no resolution to match preview config, but letting
// CameraX optimize for whatever specific resolution best fits our use cases
// Set initial target rotation, we will have to call this again if rotation changes
// during the lifecycle of this use case
//.setTargetAspectRatio(AspectRatio.RATIO_4_3)//tried both RATIO_4_3 and RATIO_16_9
.setTargetResolution(Size(3000, 4000))//tried 4000 * 3000 too..
.setTargetRotation(rotation)
//.setDefaultCaptureConfig(config)
.build()
// Must unbind the use-cases before rebinding them
cameraProvider.unbindAll()
try {
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture)
// Attach the viewfinder's surface provider to preview use case
preview?.setSurfaceProvider(fragmentCameraBinding.viewFinder.surfaceProvider)
observeCameraState(camera?.cameraInfo!!)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}
I tried to play around with the available configurations present in cameraX and was not able to get the high resolution output with same resolution I get in getPossibleOutputSizes
. This seems to be the case in all the devices I tested. But device camera was able to provide images in that resolution and so is camera2 based implementation.
Is this a limitation in cameraX or I have missed something?
Unfortunately, as of January 2023, using a high resolution that was returned by getHighResolutionOutputSizes
cannot be used together with CameraX. I do not know any workaround. Bug report and current status can be found here: https://issuetracker.google.com/issues/162121234
Current outlook is that the feature should come with CameraX 1.3 version.
Edit 20.04.23: With yesterday's release of Version 1.3.0-alpha06 , this should now be available: https://developer.android.com/jetpack/androidx/releases/camera#1.3.0-alpha06