CameraX is using the wide angle camera - android

I've set up the CameraX to use the the back facing camera requireLensFacing(CameraSelector.LENS_FACING_BACK), but testing on a phone with multiple cameras, it uses the wide angle one. How can I let it use the regular camera instead?
https://developer.android.com/training/camerax
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
val preview = Preview.Builder()
.setTargetResolution(Size(binding.preview.width, binding.preview.height))
.build()
val imageAnalysis = ImageAnalysis.Builder()
.setTargetResolution(Size(binding.preview.width, binding.preview.height))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
.also {
it.setAnalyzer(cameraExecutor, analyzer)
}
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(viewLifecycleOwner, cameraSelector, preview, imageAnalysis).also { camera ->
camera.cameraControl.setZoomRatio(2F)
preview.setSurfaceProvider(binding.preview.createSurfaceProvider(camera.cameraInfo))
}

Related

Preview is stretched on CameraX PreviewView

i am exciting to use CameraX on my app.,
my reference from google officialy CameraX on github,
but something wrong., please help me.,
this my code to set aspect ratio
private fun aspectRatio(width: Int, height: Int): Int {
val previewRatio = max(width, height).toDouble() / min(width, height)
if (abs(previewRatio - RATIO_4_3_VALUE) <= abs(previewRatio - RATIO_16_9_VALUE)) {
return AspectRatio.RATIO_4_3
}
return AspectRatio.RATIO_16_9
}
And this my preview code
#SuppressLint("UnsafeExperimentalUsageError")private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
viewFinder=binding.surfaceView
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
Log.d(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
Log.d(TAG, "Preview aspect ratio: $screenAspectRatio")
Size(metrics.widthPixels, metrics.heightPixels)
val rotation = viewFinder.display.rotation
// Preview
val preview = Preview.Builder()
.setTargetRotation(rotation)
.setTargetAspectRatio(screenAspectRatio)
.build()
imageCapture = if (flashStatus) {
ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.setTargetRotation(rotationimage)
.setTargetAspectRatio(screenAspectRatio)
.build()
} else {
ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.setTargetRotation(rotationimage)
.build()
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
// Unbind use cases before rebinding
cameraProvider.unbindAll()
viewFinder.scaleType=PreviewView.ScaleType.FILL_CENTER
try {
// Bind use cases to camera
val cam = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture)
if (!flashStatus) {
if (cam.cameraInfo.hasFlashUnit()) {
cam.cameraControl.enableTorch(true)
}
} else {
cam.cameraControl.enableTorch(false)
}
// Attach the viewfinder's surface provider to preview use case
preview.setSurfaceProvider(viewFinder.surfaceProvider)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
and this output preview
output preview is stretched
what is wrong on my code?
thank you for your help me folks.,
UPDATE
when my device on dark mode, the preview is normal.
preview normal on dark mode
how to fixed in normal mode??

ImageCapture doesn't care about zoomRatio on Camera

I'm willing to implement zoom feature in my app with CameraX API. I followed this medium post to implement pinch to zoom and it works.
The problem is when I retrieve the captured image in onCaptureSuccess callback, The image is not zoomed.
Here is the code I use to implement zoom on Camera in onCreate():
//ZOOM
val listener = object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
override fun onScale(detector: ScaleGestureDetector): Boolean {
val zoomRatio = camera?.cameraInfo?.zoomState?.value?.zoomRatio ?: 0f
val scale = zoomRatio * detector.scaleFactor
camera?.cameraControl?.setZoomRatio(scale)
return true
}
}
scaleDetector = ScaleGestureDetector(context, listener)
And in method "bindCameraUseCases()" :
previewCamera.setOnTouchListener { _, event ->
scaleDetector.onTouchEvent(event)
}
The full method if needed :
/** Declare and bind preview, capture and analysis use cases */
fun bindCameraUseCases() {
// Get screen metrics used to setup camera for full screen resolution
val metrics = DisplayMetrics().also { previewCamera.display.getRealMetrics(it) }
Log.d(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
val rotation = previewCamera.display.rotation
// Bind the CameraProvider to the LifeCycleOwner
val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
cameraProviderFuture.addListener(Runnable {
// CameraProvider
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
preview = Preview.Builder()
.setTargetRotation(rotation)
.build()
previewCamera.preferredImplementationMode =
PreviewView.ImplementationMode.TEXTURE_VIEW // when setting to TEXTURE_VIEW, preview doesnt take full screen on back pressed
previewCamera.setOnTouchListener { _, event ->
scaleDetector.onTouchEvent(event)
}
// Default PreviewSurfaceProvider
preview?.setSurfaceProvider(previewCamera.createSurfaceProvider(camera?.cameraInfo))
val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
// ImageCapture
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation)
.build()
// ImageAnalysis
imageAnalyzer = ImageAnalysis.Builder()
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation)
.build()
cameraProvider.unbindAll()
try {
camera = cameraProvider.bindToLifecycle(
this as LifecycleOwner, cameraSelector, preview, imageCapture, imageAnalyzer
)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, mainExecutor)
}
As I mentionned, zoom is working but then in onCaptureSucess, ImageProxy is not zoomed.
override fun onCaptureSuccess(image: ImageProxy) {
image.use { image ->
savedBitmap = image.imageProxyToBitmap()
///...
}
}
Here is the extension function to retrieve bitmap from imageProxy :
fun ImageProxy.imageProxyToBitmap(): Bitmap {
val buffer = this.planes[0].buffer
buffer.rewind()
val bytes = ByteArray(buffer.capacity())
buffer.get(bytes)
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
val matrix = Matrix()
matrix.postRotate(90f)
return Bitmap.createBitmap(bitmap, 0, 0,bitmap.width,bitmap.height, matrix, true)
}
Here are my dependencies :
// CameraX core library
def camerax_version = "1.0.0-beta02"
implementation "androidx.camera:camera-core:$camerax_version"
// CameraX Camera2 extensions
implementation "androidx.camera:camera-camera2:$camerax_version"
// CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:$camerax_version"
// CameraX View class
implementation "androidx.camera:camera-view:1.0.0-alpha09"
Thank you for your help 🙏
not sure why this happens but we are unable to reproduce the issue.
In my test, ImageCapture always captures the image with zoom applied.
Currently I suspect this could a device issue. It could be helpful if you can provide the device name. It will also be helpful if you can verify it on other devices.

CameraX preview not showing anything when front camera is selected

I am trying to use CameraX library to capture image using front camera. But when the camera is launched, preview is showing nothing but black screen. Here is the configurations:
val previewConfig = PreviewConfig.Builder().apply {
setTargetResolution(Size(640, 480))
setLensFacing(CameraX.LensFacing.FRONT)
}.build()
preview = Preview(previewConfig)
preview.setOnPreviewOutputUpdateListener {
val parent = viewFinder.parent as ViewGroup
parent.removeView(viewFinder)
parent.addView(viewFinder, 0)
viewFinder.surfaceTexture = it.surfaceTexture
updateTransform()
}
val imageCaptureConfig = ImageCaptureConfig.Builder()
.apply {
setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
}.build()
imageCapture = ImageCapture(imageCaptureConfig)
val analyzerConfig = ImageAnalysisConfig.Builder().apply {
setImageReaderMode(
ImageAnalysis.ImageReaderMode.ACQUIRE_LATEST_IMAGE)
}.build()
analyzerUseCase = ImageAnalysis(analyzerConfig).apply {
setAnalyzer(executor, LuminosityAnalyzer())
}
CameraX.bindToLifecycle(this, preview, imageCapture)
But it's working well with setLensFacing(CameraX.LensFacing.BACK). Also if i remove ImageCapture object from bindToLifeCyle method, i can see a preview with the front facing camera.
CameraX.bindToLifecycle(this, preview, /*imageCapture*/)
Please advise.
You also need to set setLensFacing to front for imageCaptureConfig.
I was also facing the same issue , but your question solved my issue :p

CameraX chooses low resolution for given aspect ratio

I want to get the best quality for square aspect ratio and setup the next preview and capture configs for CameraX.
val SQUARE_ASPECT_RATIO = Rational(1, 1)
val previewConfig = PreviewConfig.Builder().apply {
setTargetAspectRatio(SQUARE_ASPECT_RATIO)
setTargetRotation(viewFinder.display.rotation)
}.build()
preview = Preview(previewConfig)
val imageCaptureConfig = ImageCaptureConfig.Builder().apply {
setCaptureMode(ImageCapture.CaptureMode.MAX_QUALITY)
setTargetAspectRatio(SQUARE_ASPECT_RATIO)
setTargetRotation(viewFinder.display.rotation)
}.build()
imageCapture = ImageCapture(imageCaptureConfig)
CameraX.bindToLifecycle(this, preview, imageCapture)
CameraX chooses 352x288px resolution, so result image resolution equals 288x288px.
From documentation it should be the highest resolution available for current device, but it is not.
Tested on emulator and Google Pixel 3.

How does CameraX library can turn ON/OFF the torch?

I am developing a feature with the possibility of switching the torch into ON/OFF states. Some days ago, we saw a new library from Google in io2019. I came up with an idea, why not use it.
After some time, I don't see any possibilities to use the only torch from the library.
Even in the official documentation, I wasn't able to find any good pieces of information for me, what's more, the sample app from their also don't have to handle my case.
Do you have something in mind what is easy to implement or perhaps you know how to do it with CameraX?
I am worried about using camera or camera2 because the amount of code to be paste is terrible.
Links:
[1] https://developer.android.com/training/camerax
[2] https://proandroiddev.com/android-camerax-preview-analyze-capture-1b3f403a9395
[3] https://github.com/android/camera/tree/master/CameraXBasic
[4] https://github.com/android/camera/tree/master/CameraXBasic
CameraX is an Android Jetpack library that was built with the intent to make camera development easier.
androidx.camera:camera-core:1.0.0-alpha10
You can check is torch available or not with this:
val camera = cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, preview, imageAnalyzer)
camera.cameraInfo.hasFlashUnit()
And you can enable torch with:
camera.cameraControl.enableTorch(true)
2021 syntax.
Turn on torch on Android, using Java.
Your typical camera preview code (such as from the google example) generally ends like this:
cameraProvider.bindToLifecycle((LifecycleOwner)this,
cameraSelector, imageAnalysis, preview);
to turn on/off the torch...
Camera cam = cameraProvider.bindToLifecycle((LifecycleOwner)this,
cameraSelector, imageAnalysis, preview);
if ( cam.getCameraInfo().hasFlashUnit() ) {
cam.getCameraControl().enableTorch(true); // or false
}
and that's it!
2022 Syntax
imageCapture = ImageCapture.Builder()
.setFlashMode(ImageCapture.FLASH_MODE_ON)
.build()
val camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture, imageAnalyzer)
if (camera.cameraInfo.hasFlashUnit()) {
camera.cameraControl.enableTorch(true)
}
This is one way you can do it (Kotlin). If there is a better way please let me know. Following code assumes you have already established the availability of flash on the device.
Declare a flashMode var
private var flashMode: Int = ImageCapture.FLASH_MODE_OFF
In updateCameraUI set a listener
controls.findViewById<ImageButton>(R.id.flash_button).setOnClickListener {
when (flashMode) {
ImageCapture.FLASH_MODE_OFF ->
flashMode = ImageCapture.FLASH_MODE_ON
ImageCapture.FLASH_MODE_ON ->
flashMode = ImageCapture.FLASH_MODE_AUTO
ImageCapture.FLASH_MODE_AUTO ->
flashMode = ImageCapture.FLASH_MODE_OFF
}
// Re-bind use cases to include changes
bindCameraUseCases()
}
In bindCameraUseCases set the flash mode
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
.setTargetAspectRatio(screenAspectRatio)
.setTargetResolution(screenSize)
.setTargetRotation(rotation)
.setFlashMode(flashMode)
.build()
I can't comment so I'm answering to expand on yevhen_69's answer.
Setting enabledTorch(true) didn't work for me either, however I found I had to set enableTorch(true) after the call to CameraX.bindToLifecycle
val previewConfig = PreviewConfig.Builder().apply {
setLensFacing(lensFacing)
// Any setup
setTargetRotation(viewFinder.display.rotation)
}.build()
val preview = Preview(previewConfig)
CameraX.bindToLifecycle(this, preview)
preview.enableTorch(true)
However on a side note, CameraX is still in Alpha so its advisable still to use Camera2 API.
// CameraX
def cameraXVersion = "1.0.0-beta07"
implementation "androidx.camera:camera-camera2:$cameraXVersion"
implementation "androidx.camera:camera-lifecycle:$cameraXVersion"
implementation "androidx.camera:camera-view:1.0.0-alpha14"
private fun initializeFlashButton() = with(binding) {
camera?.apply {
if (cameraInfo.hasFlashUnit()) {
flashButton.setOnClickListener {
flashButton.visibility = View.VISIBLE
cameraControl.enableTorch(cameraInfo.torchState.value == TorchState.OFF)
}
} else {
flashButton.visibility = View.GONE
}
cameraInfo.torchState.observe(viewLifecycleOwner) { torchState ->
if (torchState == TorchState.OFF) {
flashButton.setImageResource(R.drawable.ic_flash)
} else {
flashButton.setImageResource(R.drawable.ic_flash_active)
}
}
}
}
You need execute this method after initialize camera object
Use CameraControl as global variable and boolean for turn off and on.
lateinit var cameraControl: CameraControl
private var flashFlag: Boolean = true
Turn off and on by click listener.
flashFlag = !flashFlag
cameraControl.enableTorch(flashFlag)
In this function I have started the camera preview.
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener({
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(binding.cameraView.surfaceProvider)
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
val camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview
)
cameraControl = camera.cameraControl
cameraControl.enableTorch(flashFlag)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
val previewConfig = PreviewConfig.Builder().apply {
setLensFacing(lensFacing)
// Any setup
setTargetRotation(viewFinder.display.rotation)
}.build()
val preview = Preview(previewConfig)
preview.enableTorch(true)
androidx.camera:camera-core:1.0.0-alpha06
CameraX new release provide these features. CameraInfo added with check Flash Available and Sensor Rotation APIs, refer this link
try {
CameraInfo cameraInfo = CameraX.getCameraInfo(currentCameraLensFacing);
LiveData<Boolean> isFlashAvailable = cameraInfo.isFlashAvailable();
flashToggle.setVisibility(isFlashAvailable.getValue() ? View.VISIBLE : View.INVISIBLE);
} catch (CameraInfoUnavailableException e) {
Log.w(TAG, "Cannot get flash available information", e);
flashToggle.setVisibility(View.VISIBLE);
}
You can enable the torch on the Preview object.
https://developer.android.com/reference/androidx/camera/core/Preview.html#enableTorch(boolean)
And you can set the flash mode (on/off/auto) on the ImageCapture object or on the config builder associated.
https://developer.android.com/reference/androidx/camera/core/ImageCapture.html#setFlashMode(androidx.camera.core.FlashMode)
https://developer.android.com/reference/androidx/camera/core/ImageCaptureConfig.Builder.html#setFlashMode(androidx.camera.core.FlashMode)

Categories

Resources