@@ -48,7 +48,6 @@ import androidx.annotation.RequiresApi
4848import androidx.core.content.ContextCompat
4949import androidx.core.graphics.drawable.toDrawable
5050import androidx.core.os.bundleOf
51- import androidx.exifinterface.media.ExifInterface
5251import androidx.fragment.app.Fragment
5352import androidx.fragment.app.commit
5453import androidx.lifecycle.lifecycleScope
@@ -76,14 +75,15 @@ import kotlin.coroutines.resume
7675import kotlin.coroutines.resumeWithException
7776import kotlin.coroutines.suspendCoroutine
7877
79- @RequiresApi(Build .VERSION_CODES .UPSIDE_DOWN_CAKE )
80- class Camera2UltraHDRCapture : Fragment () {
78+ open class Camera2UltraHDRCapture : Fragment () {
8179 /* *
8280 * Android ViewBinding.
8381 */
8482 private var _binding : Camera2UltrahdrCaptureBinding ? = null
8583 private val binding get() = _binding !!
8684
85+ protected open val ULTRAHDR_FORMAT = ImageFormat .JPEG_R
86+
8787 /* *
8888 * Detects, characterizes, and connects to a CameraDevice (used for all camera operations).
8989 */
@@ -303,13 +303,13 @@ class Camera2UltraHDRCapture : Fragment() {
303303
304304 private fun setUpImageReader () {
305305 // Initialize an image reader which will be used to capture still photos
306- val pixelFormat = ImageFormat . JPEG_R
306+ val pixelFormat = ULTRAHDR_FORMAT
307307 val configMap = characteristics.get(CameraCharacteristics .SCALER_STREAM_CONFIGURATION_MAP )
308308 configMap?.let { config ->
309309 config.getOutputSizes(pixelFormat).maxByOrNull { it.height * it.width }
310310 ?.let { size ->
311311 imageReader = ImageReader .newInstance(
312- size.width, size.height, pixelFormat , IMAGE_BUFFER_SIZE ,
312+ size.width, size.height, ULTRAHDR_FORMAT , IMAGE_BUFFER_SIZE ,
313313 )
314314 }
315315 }
@@ -324,13 +324,11 @@ class Camera2UltraHDRCapture : Fragment() {
324324 takePhoto().use { result ->
325325 Log .d(TAG , " Result received: $result " )
326326
327- // Save the result to disk, update EXIF metadata with orientation info
327+ // Save the result to disk, the previous EXIF orientation approach
328+ // will not work in case of HEIC images so use the corresponding
329+ // Camera2 control path instead.
328330 val output = saveResult(result)
329331 Log .d(TAG , " Image saved: ${output.absolutePath} " )
330- val exif = ExifInterface (output.absolutePath)
331- exif.setAttribute(ExifInterface .TAG_ORIENTATION , result.orientation.toString())
332- exif.saveAttributes()
333- Log .d(TAG , " EXIF metadata saved: ${output.absolutePath} " )
334332
335333 // Display the photo taken to user
336334 lifecycleScope.launch(Dispatchers .Main ) {
@@ -355,7 +353,7 @@ class Camera2UltraHDRCapture : Fragment() {
355353 // Query the available output formats.
356354 val formats = c.get(CameraCharacteristics .SCALER_STREAM_CONFIGURATION_MAP )?.outputFormats
357355
358- val canEncodeUltraHDR = formats?.contains(ImageFormat . JPEG_R ) ? : false
356+ val canEncodeUltraHDR = formats?.contains(ULTRAHDR_FORMAT ) ? : false
359357
360358 return canEncodeUltraHDR
361359 }
@@ -499,6 +497,7 @@ class Camera2UltraHDRCapture : Fragment() {
499497
500498 val request = session.device.createCaptureRequest(CameraDevice .TEMPLATE_STILL_CAPTURE )
501499 .apply { addTarget(imageReader.surface) }
500+ request.set(CaptureRequest .JPEG_ORIENTATION , relativeOrientation.value ? : 0 )
502501
503502 session.capture(
504503 request.build(),
@@ -584,7 +583,7 @@ class Camera2UltraHDRCapture : Fragment() {
584583 val buffer = result.image.planes[0 ].buffer
585584 val bytes = ByteArray (buffer.remaining()).apply { buffer.get(this ) }
586585 try {
587- val output = createFile(requireContext())
586+ val output = createFile(requireContext(), ULTRAHDR_FORMAT )
588587 FileOutputStream (output).use { it.write(bytes) }
589588 cont.resume(output)
590589 } catch (exc: IOException ) {
@@ -635,9 +634,13 @@ class Camera2UltraHDRCapture : Fragment() {
635634 *
636635 * @return [File] created.
637636 */
638- private fun createFile (context : Context ): File {
637+ private fun createFile (context : Context , format : Int ): File {
639638 val sdf = SimpleDateFormat (" yyyy_MM_dd_HH_mm_ss_SSS" , Locale .US )
640- return File (context.filesDir, " IMG_${sdf.format(Date ())} .jpg" )
639+ val fileType = when (format) {
640+ ImageFormat .JPEG_R -> " .jpg"
641+ else -> " .heic"
642+ }
643+ return File (context.filesDir, " IMG_${sdf.format(Date ())} " + fileType)
641644 }
642645 }
643646}
0 commit comments