From 3618590d1eba898ee2442aa46e532637e345dcfb Mon Sep 17 00:00:00 2001 From: Ravneet Dhanjal Date: Wed, 3 Jul 2024 21:00:01 -0700 Subject: [PATCH] Add JPEG_R capture to extension sample camera app --- .../extensions/fragments/CameraFragment.kt | 45 ++++++++++++++++--- .../extensions/fragments/SelectorFragment.kt | 21 +++++++-- .../app/src/main/res/navigation/nav_graph.xml | 5 +++ 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/CameraFragment.kt b/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/CameraFragment.kt index 07d2ce26..7c396b45 100644 --- a/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/CameraFragment.kt +++ b/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/CameraFragment.kt @@ -469,7 +469,21 @@ class CameraFragment : Fragment(), TextureView.SurfaceTextureListener { extensionCharacteristics = cameraManager.getCameraExtensionCharacteristics(args.cameraId) characteristics = cameraManager.getCameraCharacteristics(args.cameraId) lensFacing = characteristics[CameraCharacteristics.LENS_FACING]!! - supportedExtensions.addAll(extensionCharacteristics.supportedExtensions) + + if (args.jpegR) { + for (extension in extensionCharacteristics.supportedExtensions) { + val jpegRSizes = extensionCharacteristics.getExtensionSupportedSizes( + extension, ImageFormat.JPEG_R + ) + + if (jpegRSizes.isNotEmpty()) { + supportedExtensions.add(extension) + } + } + } else { + supportedExtensions.addAll(extensionCharacteristics.supportedExtensions) + } + if (currentExtension == -1) { currentExtension = supportedExtensions[0] currentExtensionIdx = 0 @@ -651,6 +665,7 @@ class CameraFragment : Fragment(), TextureView.SurfaceTextureListener { previewSurface = createPreviewSurface(previewSize) stillImageReader = createStillImageReader() postviewImageReader = createPostviewImageReader() + isPostviewAvailable = postviewImageReader != null val outputConfig = ArrayList() outputConfig.add(OutputConfiguration(stillImageReader.surface)) @@ -722,14 +737,27 @@ class CameraFragment : Fragment(), TextureView.SurfaceTextureListener { * Creates the still image reader and sets up OnImageAvailableListener */ private fun createStillImageReader(): ImageReader { + var stillFormat: Int + var stillCaptureSize: Size + val yuvColorEncodingSystemSizes = extensionCharacteristics.getExtensionSupportedSizes( currentExtension, ImageFormat.YUV_420_888 ) val jpegSizes = extensionCharacteristics.getExtensionSupportedSizes( currentExtension, ImageFormat.JPEG ) - val stillFormat = if (jpegSizes.isEmpty()) ImageFormat.YUV_420_888 else ImageFormat.JPEG - val stillCaptureSize = if (jpegSizes.isEmpty()) yuvColorEncodingSystemSizes[0] else jpegSizes[0] + stillFormat = if (jpegSizes.isEmpty()) ImageFormat.YUV_420_888 else ImageFormat.JPEG + stillCaptureSize = if (jpegSizes.isEmpty()) yuvColorEncodingSystemSizes[0] else jpegSizes[0] + + if (Build.VERSION.SDK_INT >= 35) { + val jpegRSizes = extensionCharacteristics.getExtensionSupportedSizes( + currentExtension, ImageFormat.JPEG_R + ) + if (args.jpegR && jpegRSizes.isNotEmpty()) { + stillFormat = ImageFormat.JPEG_R + stillCaptureSize = jpegRSizes[0] + } + } val stillImageReader = ImageReader.newInstance( stillCaptureSize.width, stillCaptureSize.height, stillFormat, 1 @@ -742,7 +770,8 @@ class CameraFragment : Fragment(), TextureView.SurfaceTextureListener { hideCaptureProgressUI() val file = File( requireActivity().getExternalFilesDir(null), - if (image.format == ImageFormat.JPEG) "frame.jpg" else "frame.yuv" + if (image.format == ImageFormat.JPEG + || image.format == ImageFormat.JPEG_R) "frame.jpg" else "frame.yuv" ) output = FileOutputStream(file) output.write(getDataFromImage(image)) @@ -787,12 +816,14 @@ class CameraFragment : Fragment(), TextureView.SurfaceTextureListener { ) val postviewSize: Size val postviewFormat: Int - if (!jpegSupportedSizes.isEmpty()) { + if (jpegSupportedSizes.isNotEmpty()) { postviewSize = jpegSupportedSizes[0] postviewFormat = ImageFormat.JPEG - } else { + } else if (yuvSupportedSizes.isNotEmpty()){ postviewSize = yuvSupportedSizes[0] postviewFormat = ImageFormat.YUV_420_888 + } else { + return null } val postviewImageReader = ImageReader.newInstance(postviewSize.width, postviewSize.height, postviewFormat, 1) @@ -1235,7 +1266,7 @@ class CameraFragment : Fragment(), TextureView.SurfaceTextureListener { val planes = image.planes var buffer: ByteBuffer var offset = 0 - if (format == ImageFormat.JPEG) { + if (format == ImageFormat.JPEG || format == ImageFormat.JPEG_R) { buffer = planes[0].buffer data = ByteArray(buffer.limit()) buffer.rewind() diff --git a/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/SelectorFragment.kt b/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/SelectorFragment.kt index 694ee43b..61c45b25 100644 --- a/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/SelectorFragment.kt +++ b/Camera2Extensions/app/src/main/java/com/example/android/camera2/extensions/fragments/SelectorFragment.kt @@ -18,8 +18,10 @@ package com.example.android.camera2.extensions.fragments import android.annotation.SuppressLint import android.content.Context +import android.graphics.ImageFormat; import android.hardware.camera2.CameraCharacteristics import android.hardware.camera2.CameraManager +import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -61,7 +63,7 @@ class SelectorFragment : Fragment() { view.setOnClickListener { Navigation.findNavController(requireActivity(), R.id.fragment_container) .navigate(SelectorFragmentDirections.actionSelectorToCamera( - item.cameraId)) + item.cameraId, item.jpegR)) } } } @@ -71,7 +73,8 @@ class SelectorFragment : Fragment() { private data class CameraInfo( val name: String, - val cameraId: String) + val cameraId: String, + val jpegR: Boolean = false) /** Converts a lens orientation enum into a human-readable string */ private fun lensOrientationString(value: Int) = when (value) { @@ -99,9 +102,21 @@ class SelectorFragment : Fragment() { .REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE) && extensionCharacteristics.supportedExtensions.isNotEmpty()) { availableCameras.add(CameraInfo("$orientation ($id)", id)) + + if (Build.VERSION.SDK_INT >= 35) { + for (extension in extensionCharacteristics.supportedExtensions) { + val jpegRSizes = extensionCharacteristics.getExtensionSupportedSizes( + extension, ImageFormat.JPEG_R + ) + + if (jpegRSizes.isNotEmpty()) { + availableCameras.add(CameraInfo("$orientation ($id) JPEG_R", id, true)) + break // Exit the loop since we found a suitable extension + } + } + } } } - return availableCameras } } diff --git a/Camera2Extensions/app/src/main/res/navigation/nav_graph.xml b/Camera2Extensions/app/src/main/res/navigation/nav_graph.xml index 3e1eec0a..e9674d42 100644 --- a/Camera2Extensions/app/src/main/res/navigation/nav_graph.xml +++ b/Camera2Extensions/app/src/main/res/navigation/nav_graph.xml @@ -43,6 +43,11 @@ app:argType="string" app:nullable="false"/> + + \ No newline at end of file