From c22bdd0758b0a80f8a5eac88afdcea63a6c264a9 Mon Sep 17 00:00:00 2001 From: wonseok Date: Sat, 27 Jan 2024 15:55:56 +0900 Subject: [PATCH 1/3] Add resize threshold based on image size --- .../picker/ImagePickerLauncher.android.kt | 2 + .../image/picker/PeekabooImageResizer.kt | 40 +++++++++++++++++-- .../image/picker/ImagePickerLauncher.kt | 9 ++++- .../image/picker/ImagePickerLauncher.ios.kt | 39 ++++++++++-------- 4 files changed, 69 insertions(+), 21 deletions(-) diff --git a/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.android.kt b/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.android.kt index d32f2b8..76d4688 100644 --- a/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.android.kt +++ b/peekaboo-image-picker/src/androidMain/kotlin/com/preat/peekaboo/image/picker/ImagePickerLauncher.android.kt @@ -74,6 +74,7 @@ private fun pickSingleImage( uri = uri, width = resizeOptions.width, height = resizeOptions.height, + resizeThresholdBytes = resizeOptions.resizeThresholdBytes, filterOptions = filterOptions, ) { resizedImage -> if (resizedImage != null) { @@ -127,6 +128,7 @@ private fun pickMultipleImages( uri = uri, width = resizeOptions.width, height = resizeOptions.height, + resizeThresholdBytes = resizeOptions.resizeThresholdBytes, filterOptions = filterOptions, ) { resizedImage -> resizedImage?.let { 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 aef270b..192eaae 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 @@ -24,6 +24,7 @@ import android.graphics.ColorMatrixColorFilter import android.graphics.Matrix import android.graphics.Paint import android.net.Uri +import android.provider.OpenableColumns import androidx.exifinterface.media.ExifInterface import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -38,17 +39,50 @@ internal object PeekabooImageResizer { uri: Uri, width: Int, height: Int, + resizeThresholdBytes: Long, filterOptions: FilterOptions, onResult: (ByteArray?) -> Unit, ) { coroutineScope.launch(Dispatchers.Default) { - val byteArray = resizeImage(context, uri, width, height, filterOptions) - withContext(Dispatchers.Main) { - onResult(byteArray) + if (getImageSize(context, uri) > resizeThresholdBytes) { + val byteArray = resizeImage(context, uri, width, height, filterOptions) + withContext(Dispatchers.Main) { + onResult(byteArray) + } + } else { + withContext(Dispatchers.Main) { + onResult(getOriginalImageByteArray(context, uri)) + } } } } + private fun getImageSize( + context: Context, + uri: Uri, + ): Int { + val cursor = context.contentResolver.query(uri, null, null, null, null) + val sizeIndex = cursor?.getColumnIndex(OpenableColumns.SIZE) + cursor?.moveToFirst() + val size = sizeIndex?.let { cursor.getInt(it) } ?: 0 + cursor?.close() + return size + } + + private fun getOriginalImageByteArray( + context: Context, + uri: Uri, + ): ByteArray? { + return context.contentResolver.openInputStream(uri)?.use { inputStream -> + val bitmap = BitmapFactory.decodeStream(inputStream) + val rotatedBitmap = rotateImageIfRequired(context, bitmap, uri) + + ByteArrayOutputStream().apply { + rotatedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, this) + }.toByteArray() + } + } + private suspend fun resizeImage( context: Context, uri: Uri, 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 b9df4b2..4dd8cf8 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 @@ -18,6 +18,10 @@ package com.preat.peekaboo.image.picker import androidx.compose.runtime.Composable import kotlinx.coroutines.CoroutineScope +private const val DEFAULT_RESIZE_IMAGE_WIDTH = 800 +private const val DEFAULT_RESIZE_IMAGE_HEIGHT = 800 +private const val DEFAULT_RESIZE_THRESHOLD_BYTES = 1048576L // 1MB + @Composable expect fun rememberImagePickerLauncher( selectionMode: SelectionMode = SelectionMode.Single, @@ -38,8 +42,9 @@ sealed class SelectionMode { } data class ResizeOptions( - val width: Int = 800, - val height: Int = 800, + val width: Int = DEFAULT_RESIZE_IMAGE_WIDTH, + val height: Int = DEFAULT_RESIZE_IMAGE_HEIGHT, + val resizeThresholdBytes: Long = DEFAULT_RESIZE_THRESHOLD_BYTES, ) sealed interface FilterOptions { 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 e792348..228884a 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 @@ -85,6 +85,7 @@ actual fun rememberImagePickerLauncher( image?.fitInto( resizeOptions.width, resizeOptions.height, + resizeOptions.resizeThresholdBytes, filterOptions, ) val bytes = resizedImage?.toByteArray() @@ -132,27 +133,33 @@ private fun UIImage.toByteArray(): ByteArray { private fun UIImage.fitInto( maxWidth: Int, maxHeight: Int, + resizeThresholdBytes: Long, filterOptions: FilterOptions, ): UIImage { - val originalWidth = this.size.useContents { width } - val originalHeight = this.size.useContents { height } - val originalRatio = originalWidth / originalHeight - - val targetRatio = maxWidth.toDouble() / maxHeight.toDouble() - val scale = - if (originalRatio > targetRatio) { - maxWidth.toDouble() / originalWidth - } else { - maxHeight.toDouble() / originalHeight - } + val imageData = this.toByteArray() + if (imageData.size > resizeThresholdBytes) { + val originalWidth = this.size.useContents { width } + val originalHeight = this.size.useContents { height } + val originalRatio = originalWidth / originalHeight + + val targetRatio = maxWidth.toDouble() / maxHeight.toDouble() + val scale = + if (originalRatio > targetRatio) { + maxWidth.toDouble() / originalWidth + } else { + maxHeight.toDouble() / originalHeight + } - val newWidth = originalWidth * scale - val newHeight = originalHeight * scale + val newWidth = originalWidth * scale + val newHeight = originalHeight * scale - val targetSize = CGSizeMake(newWidth, newHeight) - val resizedImage = this.resize(targetSize) + val targetSize = CGSizeMake(newWidth, newHeight) + val resizedImage = this.resize(targetSize) - return applyFilterToUIImage(resizedImage, filterOptions) + return applyFilterToUIImage(resizedImage, filterOptions) + } else { + return this + } } @OptIn(ExperimentalForeignApi::class) From 1c3decf975bcd5cd63a654dd00f4d7ae628feaac Mon Sep 17 00:00:00 2001 From: wonseok Date: Sat, 27 Jan 2024 17:40:37 +0900 Subject: [PATCH 2/3] Update README.md with conditional image resizing feature --- README.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 05dc086..5b0de97 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # peekaboo [![Kotlin](https://img.shields.io/badge/kotlin-1.9.21-blue.svg?logo=kotlin)](http://kotlinlang.org) [![Compose Multiplatform](https://img.shields.io/badge/Compose%20Multiplatform-v1.5.11-blue)](https://github.com/JetBrains/compose-multiplatform) -[![Maven Central](https://img.shields.io/maven-central/v/io.github.team-preat/peekaboo-image-picker?color=orange)](https://search.maven.org/search?q=g:io.github.team-preat) +[![Maven Central](https://img.shields.io/maven-central/v/io.github.onseok/peekaboo-image-picker?color=orange)](https://search.maven.org/search?q=g:io.github.onseok) [![Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-green.svg)](https://opensource.org/licenses/Apache-2.0) -[![Build](https://github.com/team-preat/peekaboo/actions/workflows/ci_check.yml/badge.svg)](https://github.com/team-preat/peekaboo/actions/workflows/ci_check.yml) +[![Build](https://github.com/onseok/peekaboo/actions/workflows/ci_check.yml/badge.svg)](https://github.com/onseok/peekaboo/actions/workflows/ci_check.yml) ![badge-android](http://img.shields.io/badge/platform-android-6EDB8D.svg?style=flat) ![badge-ios](http://img.shields.io/badge/platform-ios-CDCDCD.svg?style=flat) [![Featured in androidweekly.net](https://img.shields.io/badge/Featured%20in%20androidweekly.net-Issue%20%23601-4998C2)](https://androidweekly.net/issues/issue-601) @@ -32,10 +32,10 @@ In your `commonMain` configuration, add the desired dependency, either **`peekab commonMain { dependencies { // peekaboo-ui - implementation("io.github.team-preat:peekaboo-ui:$latest_version") + implementation("io.github.onseok:peekaboo-ui:$latest_version") // peekaboo-image-picker - implementation("io.github.team-preat:peekaboo-image-picker:$latest_version") + implementation("io.github.onseok:peekaboo-image-picker:$latest_version") } } ``` @@ -47,11 +47,11 @@ First, define the version in `libs.versions.toml`: ```toml [versions] -peekaboo = "0.4.2" +peekaboo = "0.4.3" [libraries] -peekaboo-ui = { module = "io.github.team-preat:peekaboo-ui", version.ref = "peekaboo" } -peekaboo-image-picker = { module = "io.github.team-preat:peekaboo-image-picker", version.ref = "peekaboo" } +peekaboo-ui = { module = "io.github.onseok:peekaboo-ui", version.ref = "peekaboo" } +peekaboo-image-picker = { module = "io.github.onseok:peekaboo-image-picker", version.ref = "peekaboo" } ``` Then, in your `commonMain` configuration, reference the defined version: @@ -204,17 +204,22 @@ Button(
## Image Resizing Options -`peekaboo` offers customizable resizing options for both single and multiple image selections.
+`peekaboo` offers customizable resizing options for both single and multiple image selections, along with a new feature to resize images only if they exceed a certain file size.
This feature allows you to resize the selected images to specific dimensions, optimizing them for your application's requirements and enhancing performance. - The default resizing dimensions are set to `800 x 800` pixels. -- You can customize the resizing dimensions according to your needs. +- The default threshold for resizing is set to `1MB`, meaning images larger than this size will be resized. +- You can customize the resizing dimensions and threshold according to your needs. ### Usage -Set the `resizeOptions` parameter in `rememberImagePickerLauncher` with your desired dimensions: +Set the `resizeOptions` parameter in `rememberImagePickerLauncher` with your desired dimensions and threshold: ```kotlin -val resizeOptions = ResizeOptions(width = 1200, height = 1200) // Custom dimensions +val resizeOptions = ResizeOptions( + width = 1200, // Custom width + height = 1200, // Custom height + resizeThresholdBytes = 2 * 1024 * 1024L // Custom threshold for 2MB +) ``` #### Single Image Selection with Resizing @@ -299,7 +304,7 @@ If you'd like to contribute, please feel free to create a PR or open an issue.
## Stargazers :star: -Support it by joining __[stargazers](https://github.com/TEAM-PREAT/peekaboo/stargazers)__ for this repository. :star:
+Support it by joining __[stargazers](https://github.com/onseok/peekaboo/stargazers)__ for this repository. :star:
## License From 38fa50e3d89973208fba07a6b93b12cdc3f251bc Mon Sep 17 00:00:00 2001 From: wonseok Date: Sat, 27 Jan 2024 17:42:15 +0900 Subject: [PATCH 3/3] Update peekaboo group ID and version --- .../src/main/kotlin/root.publication.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/convention-plugins/src/main/kotlin/root.publication.gradle.kts b/convention-plugins/src/main/kotlin/root.publication.gradle.kts index 9b8a76a..9740c4d 100644 --- a/convention-plugins/src/main/kotlin/root.publication.gradle.kts +++ b/convention-plugins/src/main/kotlin/root.publication.gradle.kts @@ -18,8 +18,8 @@ plugins { } allprojects { - group = "io.github.team-preat" - version = "0.4.2" + group = "io.github.onseok" + version = "0.4.3" } nexusPublishing {