-
Notifications
You must be signed in to change notification settings - Fork 327
Add support for HEIC_ULTRAHDR #282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
* Copyright 2025 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.example.platform.camera.imagecapture | ||
|
||
import android.graphics.ImageFormat | ||
import android.os.Build | ||
import androidx.annotation.RequiresApi | ||
|
||
@RequiresApi(Build.VERSION_CODES.BAKLAVA) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
class Camera2HeicUltraHDRCapture : Camera2UltraHDRCapture() { | ||
override val ULTRAHDR_FORMAT = ImageFormat.HEIC_ULTRAHDR | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,11 +44,9 @@ import android.view.SurfaceView | |
import android.view.View | ||
import android.view.ViewGroup | ||
import androidx.activity.result.contract.ActivityResultContracts | ||
import androidx.annotation.RequiresApi | ||
import androidx.core.content.ContextCompat | ||
import androidx.core.graphics.drawable.toDrawable | ||
import androidx.core.os.bundleOf | ||
import androidx.exifinterface.media.ExifInterface | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.commit | ||
import androidx.lifecycle.lifecycleScope | ||
|
@@ -76,14 +74,16 @@ import kotlin.coroutines.resume | |
import kotlin.coroutines.resumeWithException | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) | ||
class Camera2UltraHDRCapture : Fragment() { | ||
@RequiresApi(Build.VERSION_CODES.BAKLAVA) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
open class Camera2UltraHDRCapture : Fragment() { | ||
/** | ||
* Android ViewBinding. | ||
*/ | ||
private var _binding: Camera2UltrahdrCaptureBinding? = null | ||
private val binding get() = _binding!! | ||
|
||
protected open val ULTRAHDR_FORMAT = ImageFormat.JPEG_R | ||
|
||
/** | ||
* Detects, characterizes, and connects to a CameraDevice (used for all camera operations). | ||
*/ | ||
|
@@ -303,13 +303,13 @@ class Camera2UltraHDRCapture : Fragment() { | |
|
||
private fun setUpImageReader() { | ||
// Initialize an image reader which will be used to capture still photos | ||
val pixelFormat = ImageFormat.JPEG_R | ||
val pixelFormat = ULTRAHDR_FORMAT | ||
val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) | ||
configMap?.let { config -> | ||
config.getOutputSizes(pixelFormat).maxByOrNull { it.height * it.width } | ||
?.let { size -> | ||
imageReader = ImageReader.newInstance( | ||
size.width, size.height, pixelFormat, IMAGE_BUFFER_SIZE, | ||
size.width, size.height, ULTRAHDR_FORMAT, IMAGE_BUFFER_SIZE, | ||
) | ||
} | ||
} | ||
|
@@ -324,13 +324,9 @@ class Camera2UltraHDRCapture : Fragment() { | |
takePhoto().use { result -> | ||
Log.d(TAG, "Result received: $result") | ||
|
||
// Save the result to disk, update EXIF metadata with orientation info | ||
// Save the result to disk | ||
val output = saveResult(result) | ||
Log.d(TAG, "Image saved: ${output.absolutePath}") | ||
Comment on lines
+327
to
329
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
val exif = ExifInterface(output.absolutePath) | ||
exif.setAttribute(ExifInterface.TAG_ORIENTATION, result.orientation.toString()) | ||
exif.saveAttributes() | ||
Log.d(TAG, "EXIF metadata saved: ${output.absolutePath}") | ||
|
||
// Display the photo taken to user | ||
lifecycleScope.launch(Dispatchers.Main) { | ||
|
@@ -355,7 +351,7 @@ class Camera2UltraHDRCapture : Fragment() { | |
// Query the available output formats. | ||
val formats = c.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)?.outputFormats | ||
|
||
val canEncodeUltraHDR = formats?.contains(ImageFormat.JPEG_R) ?: false | ||
val canEncodeUltraHDR = formats?.contains(ULTRAHDR_FORMAT) ?: false | ||
|
||
return canEncodeUltraHDR | ||
} | ||
|
@@ -499,6 +495,7 @@ class Camera2UltraHDRCapture : Fragment() { | |
|
||
val request = session.device.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE) | ||
.apply { addTarget(imageReader.surface) } | ||
request.set(CaptureRequest.JPEG_ORIENTATION, relativeOrientation.value ?: 0) | ||
|
||
session.capture( | ||
request.build(), | ||
|
@@ -584,7 +581,7 @@ class Camera2UltraHDRCapture : Fragment() { | |
val buffer = result.image.planes[0].buffer | ||
val bytes = ByteArray(buffer.remaining()).apply { buffer.get(this) } | ||
try { | ||
val output = createFile(requireContext()) | ||
val output = createFile(requireContext(), ULTRAHDR_FORMAT) | ||
FileOutputStream(output).use { it.write(bytes) } | ||
cont.resume(output) | ||
} catch (exc: IOException) { | ||
|
@@ -635,9 +632,13 @@ class Camera2UltraHDRCapture : Fragment() { | |
* | ||
* @return [File] created. | ||
*/ | ||
private fun createFile(context: Context): File { | ||
private fun createFile(context: Context, format: Int): File { | ||
val sdf = SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS", Locale.US) | ||
return File(context.filesDir, "IMG_${sdf.format(Date())}.jpg") | ||
fileType = when (format) { | ||
ImageFormat.JPEG_R -> ".jpg" | ||
else -> ".heic" | ||
} | ||
return File(context.filesDir, "IMG_${sdf.format(Date())}" + fileType) | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a comment explaining why
compileSdkPreview
andtargetSdkPreview
are being used. This can help future developers understand the purpose of these settings and avoid accidental removal or modification.Also, ensure that using a preview SDK doesn't introduce unexpected behavior or compatibility issues on older devices. It might be useful to add a check to ensure that the app gracefully handles cases where the preview SDK is not available.