#android #android-jetpack #android-camerax
#Android #android-jetpack #android-camerax
Вопрос:
Я новичок в использовании библиотеки camera X. Я пытаюсь следовать кодовой таблице из Google здесь
Я могу показать предварительный просмотр и захватить изображение. но проблема в том……
когда я снимаю изображение в альбомной ориентации, результат изображения будет по-прежнему в портретной ориентации. Я хочу, чтобы оно автоматически вращалось. если я беру изображение в альбомной ориентации, то результат должен быть в альбомной ориентации, а если я беру его в портретной ориентации, то результат должен быть в портретной ориентации. как камера в приложении «Камера»
как это сделать?
Я использую Redmi Note 7, Android 10.
gradle, который я использую:
implementation "androidx.camera:camera-camera2:1.0.0-beta11"
implementation "androidx.camera:camera-lifecycle:1.0.0-beta11"
implementation "androidx.camera:camera-view:1.0.0-alpha18"
вот мой код для отображения предварительного просмотра и захвата изображения
class CameraFragment : Fragment() {
private var imageCapture: ImageCapture? = null
private lateinit var outputDirectory: File
private lateinit var cameraExecutor: ExecutorService
private var cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
companion object {
private const val TAG = "CameraFragment"
private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
private const val CAMERA_REQUEST_CODE_PERMISSIONS = 10
}
lateinit var mContext : Context
lateinit var mActivity : FragmentActivity
override fun onAttach(context: Context) {
super.onAttach(context)
mContext = context
activity?.let { mActivity = it }
}
private fun getOutputDirectory(): File {
val mediaDir = mActivity.externalMediaDirs.firstOrNull()?.let {
File(it, resources.getString(R.string.app_name)).apply { mkdirs() }
}
return if (mediaDir != null amp;amp; mediaDir.exists())
mediaDir else mActivity.filesDir
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(mContext)
cameraProviderFuture.addListener(Runnable {
// 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(previewView.surfaceProvider)
}
imageCapture = ImageCapture.Builder().build()
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(mContext))
}
private fun takePhoto() {
// Get a stable reference of the modifiable image capture use case
val imageCapture = imageCapture ?: return
// Create time-stamped output file to hold the image
val photoFile = File(
outputDirectory,
SimpleDateFormat(FILENAME_FORMAT, Locale.US
).format(System.currentTimeMillis()) ".jpg")
// Create output options object which contains file metadata
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
// Set up image capture listener, which is triggered after photo has
// been taken
imageCapture.takePicture(outputOptions, ContextCompat.getMainExecutor(mContext), object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.d("agungxxx", "2: ${exc.localizedMessage}")
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
cameraSharedViewModel.sendImageUriPathToPreviousDestination(photoFile)
findNavController().navigateUp()
}
})
}
}
Ответ №1:
Поворот захваченного изображения зависит от целевого поворота ImageCapture
варианта использования. По умолчанию, когда оно не задано приложением, оно равно Display.getRotation()
, где Display
отображается по умолчанию на момент ImageCapture
создания варианта использования.
Это означает, что вам необходимо обновлять ImageCapture
целевой поворот каждый раз, когда меняется ориентация дисплея, например, когда устройство физически поворачивается с портретной на альбомную.
Я предполагаю, что ваша активность имеет заблокированную ориентацию (?). В этом случае вы можете использовать an OrientationEventListener
для непрерывного получения обновлений о повороте устройства, а затем соответствующим образом обновлять целевой поворот варианта использования.
val orientationEventListener = object : OrientationEventListener(this) {
override fun onOrientationChanged(orientation: Int) {
if (orientation == OrientationEventListener.UNKNOWN_ORIENTATION) {
return
}
val rotation = when (orientation) {
in 45 until 135 -> Surface.ROTATION_270
in 135 until 225 -> Surface.ROTATION_180
in 225 until 315 -> Surface.ROTATION_90
else -> Surface.ROTATION_0
}
imageCapture.targetRotation = rotation
}
}
Вы должны запускать / останавливать orientationEventListener
, когда жизненный цикл действия запускается / останавливается, это также соответствует моменту запуска / остановки камеры. Вы можете увидеть пример этого здесь.
Вы также можете узнать больше о вариантах использования и поворота CameraX в официальной документации.
Комментарии:
1. @Husyan Большое вам спасибо, это решает мою проблему, я использую такой код i.stack.imgur.com/hcJGd.png , но не могли бы вы, пожалуйста, предоставить информацию о значении UNKNOWN_ORIENTATION здесь? поскольку я также не могу найти его в документации, это отрицательное целое число?
2. Рад это слышать.
UNKNOWN_ORIENTATION
равно -1, прослушиватель получает, когда поворот устройства не может быть определен.