diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/dialogs/ChangeResolutionDialogX.kt b/app/src/main/kotlin/com/simplemobiletools/camera/dialogs/ChangeResolutionDialogX.kt new file mode 100644 index 00000000..1b5c69a7 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/dialogs/ChangeResolutionDialogX.kt @@ -0,0 +1,104 @@ +package com.simplemobiletools.camera.dialogs + +import android.app.Activity +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import androidx.appcompat.app.AlertDialog +import com.simplemobiletools.camera.R +import com.simplemobiletools.camera.extensions.config +import com.simplemobiletools.camera.models.MySize +import com.simplemobiletools.camera.models.VideoQuality +import com.simplemobiletools.commons.dialogs.RadioGroupDialog +import com.simplemobiletools.commons.extensions.setupDialogStuff +import com.simplemobiletools.commons.models.RadioItem +import kotlinx.android.synthetic.main.dialog_change_resolution.view.change_resolution_photo +import kotlinx.android.synthetic.main.dialog_change_resolution.view.change_resolution_photo_holder +import kotlinx.android.synthetic.main.dialog_change_resolution.view.change_resolution_video +import kotlinx.android.synthetic.main.dialog_change_resolution.view.change_resolution_video_holder + +class ChangeResolutionDialogX( + private val activity: Activity, + private val isFrontCamera: Boolean, + private val photoResolutions: List = listOf(), + private val videoResolutions: List, + private val callback: () -> Unit +) { + private var dialog: AlertDialog + private val config = activity.config + + private val TAG = "ChangeResolutionDialogX" + init { + val view = LayoutInflater.from(activity).inflate(R.layout.dialog_change_resolution, null).apply { + setupPhotoResolutionPicker(this) + setupVideoResolutionPicker(this) + } + + dialog = AlertDialog.Builder(activity) + .setPositiveButton(R.string.ok, null) + .create().apply { + activity.setupDialogStuff(view, this, if (isFrontCamera) R.string.front_camera else R.string.back_camera) + } + } + + private fun setupPhotoResolutionPicker(view: View) { + val items = getFormattedResolutions(photoResolutions) + var selectionIndex = if (isFrontCamera) config.frontPhotoResIndex else config.backPhotoResIndex + selectionIndex = Math.max(selectionIndex, 0) + + view.change_resolution_photo_holder.setOnClickListener { + RadioGroupDialog(activity, items, selectionIndex) { + selectionIndex = it as Int + Log.w(TAG, "setupPhotoResolutionPicker: selectionIndex=$it") + view.change_resolution_photo.text = items[selectionIndex].title + if (isFrontCamera) { + config.frontPhotoResIndex = it + } else { + config.backPhotoResIndex = it + } + dialog.dismiss() + callback.invoke() + } + } + view.change_resolution_photo.text = items.getOrNull(selectionIndex)?.title + } + + private fun setupVideoResolutionPicker(view: View) { + val items = videoResolutions.mapIndexed { index, videoQuality -> + val megapixels = videoQuality.megaPixels + val aspectRatio = videoQuality.getAspectRatio(activity) + RadioItem(index, "${videoQuality.width} x ${videoQuality.height} ($megapixels MP, $aspectRatio)") + } + + val videoQuality = if (isFrontCamera) config.frontVideoQuality else config.backVideoQuality + var selectionIndex = videoResolutions.indexOf(videoQuality) + + view.change_resolution_video_holder.setOnClickListener { + RadioGroupDialog(activity, ArrayList(items), selectionIndex) { + selectionIndex = it as Int + val selectedItem = items[selectionIndex] + val selectedQuality = videoResolutions[selectionIndex] + view.change_resolution_video.text = selectedItem.title + if (isFrontCamera) { + config.frontVideoQuality = selectedQuality + } else { + config.backVideoQuality = selectedQuality + } + dialog.dismiss() + callback.invoke() + } + } + view.change_resolution_video.text = items.getOrNull(selectionIndex)?.title + } + + private fun getFormattedResolutions(resolutions: List): ArrayList { + val items = ArrayList(resolutions.size) + val sorted = resolutions.sortedByDescending { it.width * it.height } + sorted.forEachIndexed { index, size -> + val megapixels = String.format("%.1f", (size.width * size.height.toFloat()) / 1000000) + val aspectRatio = size.getAspectRatio(activity) + items.add(RadioItem(index, "${size.width} x ${size.height} ($megapixels MP, $aspectRatio)")) + } + return items + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/extensions/Quality.kt b/app/src/main/kotlin/com/simplemobiletools/camera/extensions/Quality.kt new file mode 100644 index 00000000..017f6c01 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/extensions/Quality.kt @@ -0,0 +1,32 @@ +package com.simplemobiletools.camera.extensions + +import androidx.camera.core.AspectRatio +import androidx.camera.video.Quality +import com.simplemobiletools.camera.models.VideoQuality + +fun Quality.toVideoQuality(): VideoQuality { + return when (this) { + Quality.UHD -> VideoQuality.UHD + Quality.FHD -> VideoQuality.FHD + Quality.HD -> VideoQuality.HD + Quality.SD -> VideoQuality.SD + else -> throw IllegalArgumentException("Unsupported quality: $this") + } +} + +fun VideoQuality.toCameraXQuality(): Quality { + return when (this) { + VideoQuality.UHD -> Quality.UHD + VideoQuality.FHD -> Quality.FHD + VideoQuality.HD -> Quality.HD + VideoQuality.SD -> Quality.SD + } +} + +fun Quality.getAspectRatio(): Int { + return when(this) { + Quality.UHD, Quality.FHD, Quality.HD -> AspectRatio.RATIO_16_9 + Quality.SD -> AspectRatio.RATIO_4_3 + else -> throw IllegalArgumentException("Unsupported quality: $this") + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Config.kt index 5ede2c12..6ae1a3ed 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Config.kt @@ -3,6 +3,7 @@ package com.simplemobiletools.camera.helpers import android.content.Context import android.os.Environment import androidx.camera.core.CameraSelector +import com.simplemobiletools.camera.models.VideoQuality import com.simplemobiletools.commons.helpers.BaseConfig import java.io.File @@ -62,6 +63,20 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getInt(FRONT_PHOTO_RESOLUTION_INDEX, 0) set(frontPhotoResIndex) = prefs.edit().putInt(FRONT_PHOTO_RESOLUTION_INDEX, frontPhotoResIndex).apply() + var backVideoQuality: VideoQuality + get() { + val backQuality = prefs.getString(BACK_VIDEO_QUALITY, VideoQuality.UHD.name) + return VideoQuality.values().first { it.name == backQuality } + } + set(backVideoQuality) = prefs.edit().putString(BACK_VIDEO_QUALITY, backVideoQuality.name).apply() + + var frontVideoQuality: VideoQuality + get() { + val frontQuality = prefs.getString(FRONT_VIDEO_QUALITY, VideoQuality.UHD.name) + return VideoQuality.values().first { it.name == frontQuality } + } + set(frontVideoQuality) = prefs.edit().putString(FRONT_VIDEO_QUALITY, frontVideoQuality.name).apply() + var frontVideoResIndex: Int get() = prefs.getInt(FRONT_VIDEO_RESOLUTION_INDEX, 0) set(frontVideoResIndex) = prefs.edit().putInt(FRONT_VIDEO_RESOLUTION_INDEX, frontVideoResIndex).apply() diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Constants.kt index 0b543b7c..b36a6ba2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/Constants.kt @@ -15,6 +15,8 @@ const val FLASHLIGHT_STATE = "flashlight_state" const val INIT_PHOTO_MODE = "init_photo_mode" const val BACK_PHOTO_RESOLUTION_INDEX = "back_photo_resolution_index_2" const val BACK_VIDEO_RESOLUTION_INDEX = "back_video_resolution_index_2" +const val BACK_VIDEO_QUALITY = "back_video_quality_2" +const val FRONT_VIDEO_QUALITY = "front_video_quality_2" const val FRONT_PHOTO_RESOLUTION_INDEX = "front_photo_resolution_index_2" const val FRONT_VIDEO_RESOLUTION_INDEX = "front_video_resolution_index_2" const val KEEP_SETTINGS_VISIBLE = "keep_settings_visible" diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/ImageQualityManager.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/ImageQualityManager.kt new file mode 100644 index 00000000..bad6f719 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/ImageQualityManager.kt @@ -0,0 +1,89 @@ +package com.simplemobiletools.camera.helpers + +import android.content.Context +import android.graphics.ImageFormat +import android.hardware.camera2.CameraCharacteristics +import android.hardware.camera2.CameraManager +import android.hardware.camera2.params.StreamConfigurationMap +import android.media.MediaRecorder +import android.util.Log +import android.util.Size +import androidx.appcompat.app.AppCompatActivity +import androidx.camera.core.CameraSelector +import androidx.camera.video.Quality +import com.simplemobiletools.camera.extensions.config +import com.simplemobiletools.camera.extensions.toCameraXQuality +import com.simplemobiletools.camera.models.CameraSelectorImageQualities +import com.simplemobiletools.camera.models.CameraSelectorVideoQualities +import com.simplemobiletools.camera.models.MySize + +class ImageQualityManager( + activity: AppCompatActivity, +) { + + companion object { + private const val TAG = "ImageQualityManager" + private const val MAX_VIDEO_WIDTH = 4096 + private const val MAX_VIDEO_HEIGHT = 2160 + private val CAMERA_LENS = arrayOf(CameraCharacteristics.LENS_FACING_FRONT, CameraCharacteristics.LENS_FACING_BACK) + } + + private val cameraManager = activity.getSystemService(Context.CAMERA_SERVICE) as CameraManager + private val config = activity.config + private val imageQualities = mutableListOf() + + fun initSupportedQualities() { + for (cameraId in cameraManager.cameraIdList) { + try { + val characteristics = cameraManager.getCameraCharacteristics(cameraId) + for (lens in CAMERA_LENS) { + if (characteristics.get(CameraCharacteristics.LENS_FACING) == lens) { + val configMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue + val imageSizes = configMap.getOutputSizes(ImageFormat.JPEG).map { MySize(it.width, it.height) } + val cameraSelector = lens.toCameraSelector() + imageQualities.add(CameraSelectorImageQualities(cameraSelector, imageSizes)) + Log.i(TAG, "initQualities: imageSizes=$imageSizes") + } + } + } catch (e: Exception) { + Log.e(TAG, "Camera ID=$cameraId is not supported", e) + } + } + } + + private fun getAvailableVideoSizes(configMap: StreamConfigurationMap): List { + return configMap.getOutputSizes(MediaRecorder::class.java).filter { + it.width <= MAX_VIDEO_WIDTH && it.height <= MAX_VIDEO_HEIGHT + } + } + + private fun Int.toCameraSelector(): CameraSelector { + return if (this == CameraCharacteristics.LENS_FACING_FRONT) { + CameraSelector.DEFAULT_FRONT_CAMERA + } else { + CameraSelector.DEFAULT_BACK_CAMERA + } + } + + fun getUserSelectedResolution(cameraSelector: CameraSelector): Size? { + val index = if (cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA) config.frontPhotoResIndex else config.backPhotoResIndex + return imageQualities.filter { it.camSelector == cameraSelector } + .flatMap { it.qualities } + .sortedByDescending { it.pixels} + .distinctBy { it.pixels } + .map { Size(it.width, it.height) } + .also { + Log.i(TAG, "Resolutions: $it, index=$index") + } + .getOrNull(index).also { + Log.i(TAG, "getUserSelectedResolution: $it, index=$index") + } + } + + fun getSupportedResolutions(cameraSelector: CameraSelector): List { + return imageQualities.filter { it.camSelector == cameraSelector } + .flatMap { it.qualities } + .sortedByDescending { it.pixels } + .distinctBy { it.pixels } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/helpers/VideoQualityManager.kt b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/VideoQualityManager.kt new file mode 100644 index 00000000..26f3dc3b --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/helpers/VideoQualityManager.kt @@ -0,0 +1,60 @@ +package com.simplemobiletools.camera.helpers + +import android.util.Log +import androidx.camera.core.Camera +import androidx.camera.core.CameraSelector +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.camera.video.Quality +import androidx.camera.video.QualitySelector +import com.simplemobiletools.camera.extensions.toCameraXQuality +import com.simplemobiletools.camera.extensions.toVideoQuality +import com.simplemobiletools.camera.models.CameraSelectorVideoQualities +import com.simplemobiletools.camera.models.VideoQuality + +class VideoQualityManager(private val config: Config) { + + companion object { + private const val TAG = "VideoQualityHelper" + private val QUALITIES = listOf(Quality.UHD, Quality.FHD, Quality.HD, Quality.SD) + private val CAMERA_SELECTORS = arrayOf(CameraSelector.DEFAULT_BACK_CAMERA, CameraSelector.DEFAULT_FRONT_CAMERA) + } + + private val videoQualities = mutableListOf() + + fun initSupportedQualities( + cameraProvider: ProcessCameraProvider, + camera: Camera, + ) { + if (videoQualities.isEmpty()) { + for (camSelector in CAMERA_SELECTORS) { + try { + if (cameraProvider.hasCamera(camSelector)) { + QualitySelector.getSupportedQualities(camera.cameraInfo) + .filter(QUALITIES::contains) + .also { allQualities -> + val qualities = allQualities.map { it.toVideoQuality() } + videoQualities.add(CameraSelectorVideoQualities(camSelector, qualities)) + } + Log.i(TAG, "bindCameraUseCases: videoQualities=$videoQualities") + } + } catch (e: Exception) { + Log.e(TAG, "Camera Face $camSelector is not supported", e) + } + } + } + } + + fun getUserSelectedQuality(cameraSelector: CameraSelector): Quality { + return if (cameraSelector == CameraSelector.DEFAULT_FRONT_CAMERA) { + config.frontVideoQuality.toCameraXQuality() + } else { + config.backVideoQuality.toCameraXQuality() + } + } + + fun getSupportedQualities(cameraSelector: CameraSelector): List { + return videoQualities.filter { it.camSelector == cameraSelector } + .flatMap { it.qualities } + .sortedByDescending { it.pixels } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt index 5207a8f6..89bfe1ba 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/implementations/CameraXPreview.kt @@ -1,13 +1,9 @@ package com.simplemobiletools.camera.implementations import android.annotation.SuppressLint -import android.content.ContentValues import android.content.Context import android.hardware.SensorManager import android.hardware.display.DisplayManager -import android.net.Uri -import android.os.Environment -import android.provider.MediaStore import android.util.Log import android.view.Display import android.view.GestureDetector @@ -36,14 +32,7 @@ import androidx.camera.core.ImageCaptureException import androidx.camera.core.Preview import androidx.camera.core.UseCase import androidx.camera.lifecycle.ProcessCameraProvider -import androidx.camera.video.FileDescriptorOutputOptions -import androidx.camera.video.MediaStoreOutputOptions -import androidx.camera.video.Quality -import androidx.camera.video.QualitySelector -import androidx.camera.video.Recorder -import androidx.camera.video.Recording -import androidx.camera.video.VideoCapture -import androidx.camera.video.VideoRecordEvent +import androidx.camera.video.* import androidx.camera.view.PreviewView import androidx.core.content.ContextCompat import androidx.core.view.doOnLayout @@ -52,23 +41,12 @@ import androidx.lifecycle.LifecycleOwner import androidx.window.layout.WindowMetricsCalculator import com.bumptech.glide.load.ImageHeaderParser.UNKNOWN_ORIENTATION import com.simplemobiletools.camera.R -import com.simplemobiletools.camera.extensions.config -import com.simplemobiletools.camera.extensions.getRandomMediaName -import com.simplemobiletools.camera.extensions.toAppFlashMode -import com.simplemobiletools.camera.extensions.toCameraSelector -import com.simplemobiletools.camera.extensions.toLensFacing -import com.simplemobiletools.camera.helpers.CameraErrorHandler -import com.simplemobiletools.camera.helpers.MediaOutputHelper -import com.simplemobiletools.camera.helpers.MediaSoundHelper -import com.simplemobiletools.camera.helpers.PinchToZoomOnScaleGestureListener +import com.simplemobiletools.camera.dialogs.ChangeResolutionDialogX +import com.simplemobiletools.camera.extensions.* +import com.simplemobiletools.camera.helpers.* import com.simplemobiletools.camera.interfaces.MyPreview import com.simplemobiletools.camera.models.MediaOutput -import com.simplemobiletools.commons.extensions.hasPermission import com.simplemobiletools.commons.extensions.toast -import com.simplemobiletools.commons.helpers.PERMISSION_RECORD_AUDIO -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import kotlin.math.abs import kotlin.math.max import kotlin.math.min @@ -98,6 +76,8 @@ class CameraXPreview( private val displayManager = activity.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager private val mediaSoundHelper = MediaSoundHelper() private val windowMetricsCalculator = WindowMetricsCalculator.getOrCreate() + private val videoQualityManager = VideoQualityManager(config) + private val imageQualityManager = ImageQualityManager(activity) private val orientationEventListener = object : OrientationEventListener(activity, SensorManager.SENSOR_DELAY_NORMAL) { @SuppressLint("RestrictedApi") @@ -146,6 +126,7 @@ class CameraXPreview( private fun startCamera(switching: Boolean = false) { Log.i(TAG, "startCamera: ") + imageQualityManager.initSupportedQualities() val cameraProviderFuture = ProcessCameraProvider.getInstance(activity) cameraProviderFuture.addListener({ try { @@ -163,7 +144,12 @@ class CameraXPreview( private fun bindCameraUseCases() { val cameraProvider = cameraProvider ?: throw IllegalStateException("Camera initialization failed.") val metrics = windowMetricsCalculator.computeCurrentWindowMetrics(activity).bounds - val aspectRatio = aspectRatio(metrics.width(), metrics.height()) + val aspectRatio = if (isPhotoCapture) { + aspectRatio(metrics.width(), metrics.height()) + } else { + val selectedQuality = videoQualityManager.getUserSelectedQuality(cameraSelector) + selectedQuality.getAspectRatio() + } val rotation = previewView.display.rotation preview = buildPreview(aspectRatio, rotation) @@ -174,7 +160,10 @@ class CameraXPreview( cameraSelector, preview, captureUseCase, - ) + ).also { + videoQualityManager.initSupportedQualities(cameraProvider, it) + } + preview?.setSurfaceProvider(previewView.surfaceProvider) setupZoomAndFocus() } @@ -220,22 +209,30 @@ class CameraXPreview( .setCaptureMode(CAPTURE_MODE_MAXIMIZE_QUALITY) .setFlashMode(flashMode) .setJpegQuality(config.photoQuality) - .setTargetAspectRatio(aspectRatio) .setTargetRotation(rotation) + .apply { + imageQualityManager.getUserSelectedResolution(cameraSelector)?.let { resolution -> + Log.i(TAG, "buildImageCapture: resolution=$resolution") + setTargetResolution(resolution) + } ?: setTargetAspectRatio(aspectRatio) + } .build() } private fun buildPreview(aspectRatio: Int, rotation: Int): Preview { return Preview.Builder() - .setTargetAspectRatio(aspectRatio) .setTargetRotation(rotation) + .setTargetAspectRatio(aspectRatio) .build() } private fun buildVideoCapture(): VideoCapture { + val qualitySelector = QualitySelector.from( + videoQualityManager.getUserSelectedQuality(cameraSelector), + FallbackStrategy.lowerQualityOrHigherThan(Quality.SD), + ) val recorder = Recorder.Builder() - //TODO: user control for quality - .setQualitySelector(QualitySelector.from(Quality.FHD)) + .setQualitySelector(qualitySelector) .build() return VideoCapture.withOutput(recorder) } @@ -305,7 +302,18 @@ class CameraXPreview( } override fun showChangeResolutionDialog() { - + val oldQuality = videoQualityManager.getUserSelectedQuality(cameraSelector) + ChangeResolutionDialogX( + activity, + isFrontCameraInUse(), + imageQualityManager.getSupportedResolutions(cameraSelector), + videoQualityManager.getSupportedQualities(cameraSelector) + ) { + if (oldQuality != videoQualityManager.getUserSelectedQuality(cameraSelector)) { + currentRecording?.stop() + } + startCamera() + } } override fun toggleFrontBackCamera() { @@ -344,7 +352,6 @@ class CameraXPreview( } override fun tryTakePicture() { - Log.i(TAG, "captureImage: ") val imageCapture = imageCapture ?: throw IllegalStateException("Camera initialization failed.") val metadata = Metadata().apply { diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/models/CameraSelectorImageQualities.kt b/app/src/main/kotlin/com/simplemobiletools/camera/models/CameraSelectorImageQualities.kt new file mode 100644 index 00000000..b354f453 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/models/CameraSelectorImageQualities.kt @@ -0,0 +1,8 @@ +package com.simplemobiletools.camera.models + +import androidx.camera.core.CameraSelector + +data class CameraSelectorImageQualities( + val camSelector: CameraSelector, + val qualities: List, +) diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/models/CameraSelectorVideoQualities.kt b/app/src/main/kotlin/com/simplemobiletools/camera/models/CameraSelectorVideoQualities.kt new file mode 100644 index 00000000..cca1c2ed --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/models/CameraSelectorVideoQualities.kt @@ -0,0 +1,8 @@ +package com.simplemobiletools.camera.models + +import androidx.camera.core.CameraSelector + +data class CameraSelectorVideoQualities( + val camSelector: CameraSelector, + val qualities: List, +) diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/models/MySize.kt b/app/src/main/kotlin/com/simplemobiletools/camera/models/MySize.kt index 96b7b65d..d1a77804 100644 --- a/app/src/main/kotlin/com/simplemobiletools/camera/models/MySize.kt +++ b/app/src/main/kotlin/com/simplemobiletools/camera/models/MySize.kt @@ -6,6 +6,7 @@ import com.simplemobiletools.camera.R data class MySize(val width: Int, val height: Int) { val ratio = width / height.toFloat() + val pixels: Int = width * height fun isSixteenToNine() = ratio == 16 / 9f private fun isFiveToThree() = ratio == 5 / 3f diff --git a/app/src/main/kotlin/com/simplemobiletools/camera/models/VideoQuality.kt b/app/src/main/kotlin/com/simplemobiletools/camera/models/VideoQuality.kt new file mode 100644 index 00000000..9fce732f --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/camera/models/VideoQuality.kt @@ -0,0 +1,59 @@ +package com.simplemobiletools.camera.models + +import android.content.Context +import com.simplemobiletools.camera.R + +enum class VideoQuality(val width: Int, val height: Int) { + UHD(3840, 2160), + FHD(1920, 1080), + HD(1280, 720), + SD(720, 480); + + + val pixels: Int = width * height + + val megaPixels: String = String.format("%.1f", (width * height.toFloat()) / VideoQuality.ONE_MEGA_PIXELS) + + val ratio = width / height.toFloat() + + private fun isSixteenToNine() = ratio == 16 / 9f + + private fun isFiveToThree() = ratio == 5 / 3f + + private fun isFourToThree() = ratio == 4 / 3f + + private fun isTwoToOne() = ratio == 2f + + private fun isThreeToFour() = ratio == 3 / 4f + + private fun isThreeToTwo() = ratio == 3 / 2f + + private fun isSixToFive() = ratio == 6 / 5f + + private fun isNineteenToNine() = ratio == 19 / 9f + + private fun isNineteenToEight() = ratio == 19 / 8f + + private fun isOneNineToOne() = ratio == 1.9f + + private fun isSquare() = width == height + + fun getAspectRatio(context: Context) = when { + isSixteenToNine() -> "16:9" + isFiveToThree() -> "5:3" + isFourToThree() -> "4:3" + isThreeToFour() -> "3:4" + isThreeToTwo() -> "3:2" + isSixToFive() -> "6:5" + isOneNineToOne() -> "1.9:1" + isNineteenToNine() -> "19:9" + isNineteenToEight() -> "19:8" + isSquare() -> "1:1" + isTwoToOne() -> "2:1" + else -> context.resources.getString(R.string.other) + } + + companion object { + private const val ONE_MEGA_PIXELS = 1000000 + } +}