From bbb5fa8cd52e26dee755ee73fae47fa4fabe6a94 Mon Sep 17 00:00:00 2001 From: Anatol Date: Thu, 7 Mar 2024 14:22:33 +0200 Subject: [PATCH] Ensuring compression quality value is in range 0.0 .. 1.0 Adding annotation library and marking compressionQuality param as FloatRange. --- gradle/libs.versions.toml | 1 + peekaboo-image-picker/build.gradle.kts | 1 + .../preat/peekaboo/image/picker/PeekabooImageResizer.kt | 6 +++++- .../preat/peekaboo/image/picker/ImagePickerLauncher.kt | 2 ++ .../peekaboo/image/picker/ImagePickerLauncher.ios.kt | 9 +++++++-- 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9350710..ddeab48 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -49,6 +49,7 @@ androidx-exifinterface = { group = "androidx.exifinterface", name = "exifinterfa androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "androidx-lifecycleViewmodelCompose" } paging-common = { module = "app.cash.paging:paging-common", version.ref = "multiplatform-paging" } paging-compose-common = { module = "app.cash.paging:paging-compose-common", version.ref = "multiplatform-paging" } +annotation = { module = "androidx.annotation:annotation", version = "1.7.1" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } diff --git a/peekaboo-image-picker/build.gradle.kts b/peekaboo-image-picker/build.gradle.kts index 7053d97..6fbbfb0 100644 --- a/peekaboo-image-picker/build.gradle.kts +++ b/peekaboo-image-picker/build.gradle.kts @@ -39,6 +39,7 @@ kotlin { implementation(compose.runtime) implementation(compose.foundation) implementation(compose.material) + implementation(libs.annotation) } commonTest.dependencies { implementation(libs.kotlin.test) diff --git a/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/PeekabooImageResizer.kt b/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/PeekabooImageResizer.kt index 95fd7ad..57a88f3 100644 --- a/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/PeekabooImageResizer.kt +++ b/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/PeekabooImageResizer.kt @@ -25,6 +25,7 @@ import android.graphics.Matrix import android.graphics.Paint import android.net.Uri import android.provider.OpenableColumns +import androidx.annotation.FloatRange import androidx.exifinterface.media.ExifInterface import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -40,6 +41,7 @@ internal object PeekabooImageResizer { width: Int, height: Int, resizeThresholdBytes: Long, + @FloatRange(from = 0.0, to = 1.0) compressionQuality: Double, filterOptions: FilterOptions, onResult: (ByteArray?) -> Unit, @@ -87,6 +89,7 @@ internal object PeekabooImageResizer { uri: Uri, width: Int, height: Int, + @FloatRange(from = 0.0, to = 1.0) compression: Double, filterOptions: FilterOptions, ): ByteArray? { @@ -129,7 +132,8 @@ internal object PeekabooImageResizer { val filteredBitmap = applyFilter(rotatedBitmap, filterOptions) ByteArrayOutputStream().use { byteArrayOutputStream -> - filteredBitmap.compress(Bitmap.CompressFormat.JPEG, (100 * compression).toInt(), byteArrayOutputStream) + val validatedCompression = compression.coerceIn(0.0, 1.0) + filteredBitmap.compress(Bitmap.CompressFormat.JPEG, (100 * validatedCompression).toInt(), byteArrayOutputStream) val byteArray = byteArrayOutputStream.toByteArray() PeekabooBitmapCache.instance.put(filterCacheKey, filteredBitmap) return byteArray diff --git a/peekaboo-image-picker/src/commonMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.kt b/peekaboo-image-picker/src/commonMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.kt index a0bd636..5dccb9a 100644 --- a/peekaboo-image-picker/src/commonMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.kt +++ b/peekaboo-image-picker/src/commonMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.kt @@ -15,6 +15,7 @@ */ package com.preat.peekaboo.image.picker +import androidx.annotation.FloatRange import androidx.compose.runtime.Composable import kotlinx.coroutines.CoroutineScope @@ -45,6 +46,7 @@ data class ResizeOptions( val width: Int = DEFAULT_RESIZE_IMAGE_WIDTH, val height: Int = DEFAULT_RESIZE_IMAGE_HEIGHT, val resizeThresholdBytes: Long = DEFAULT_RESIZE_THRESHOLD_BYTES, + @FloatRange(from = 0.0, to = 1.0) val compressionQuality: Double = 1.0, ) diff --git a/peekaboo-image-picker/src/iosMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.ios.kt b/peekaboo-image-picker/src/iosMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.ios.kt index eb609d1..bc95c46 100644 --- a/peekaboo-image-picker/src/iosMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.ios.kt +++ b/peekaboo-image-picker/src/iosMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.ios.kt @@ -15,6 +15,7 @@ */ package com.preat.peekaboo.image.picker +import androidx.annotation.FloatRange import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import kotlinx.cinterop.CValue @@ -86,6 +87,7 @@ actual fun rememberImagePickerLauncher( resizeOptions.width, resizeOptions.height, resizeOptions.resizeThresholdBytes, + resizeOptions.compressionQuality, filterOptions, ) val bytes = resizedImage?.toByteArray(resizeOptions.compressionQuality) @@ -123,7 +125,8 @@ actual fun rememberImagePickerLauncher( @OptIn(ExperimentalForeignApi::class) private fun UIImage.toByteArray(compressionQuality: Double): ByteArray { - val jpegData = UIImageJPEGRepresentation(this, compressionQuality)!! + val validCompressionQuality = compressionQuality.coerceIn(0.0, 1.0) + val jpegData = UIImageJPEGRepresentation(this, validCompressionQuality)!! return ByteArray(jpegData.length.toInt()).apply { memcpy(this.refTo(0), jpegData.bytes, jpegData.length) } @@ -134,9 +137,11 @@ private fun UIImage.fitInto( maxWidth: Int, maxHeight: Int, resizeThresholdBytes: Long, + @FloatRange(from = 0.0, to = 1.0) + compressionQuality: Double, filterOptions: FilterOptions, ): UIImage { - val imageData = this.toByteArray() + val imageData = this.toByteArray(compressionQuality) if (imageData.size > resizeThresholdBytes) { val originalWidth = this.size.useContents { width } val originalHeight = this.size.useContents { height }