From e36fc8f849a617f9b3e47d9a7f8dd9f34dac0407 Mon Sep 17 00:00:00 2001 From: ZARA Date: Fri, 12 May 2023 14:59:31 +0330 Subject: [PATCH 1/2] #96 Fix picking camera image without cropping --- .../imagepicker/ImagePickerActivity.kt | 29 +++++++------------ .../imagepicker/provider/BaseProvider.kt | 9 ++---- .../imagepicker/provider/CameraProvider.kt | 6 ++-- .../provider/CompressionProvider.kt | 12 ++++---- .../imagepicker/provider/CropProvider.kt | 25 ++-------------- .../imagepicker/provider/GalleryProvider.kt | 15 ++++------ .../drjacky/imagepicker/util/ImageUtil.kt | 23 ++++++++++++++- .../sample/MainActivity.kt | 4 +-- 8 files changed, 54 insertions(+), 69 deletions(-) diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt index 7825a01..119ec37 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt @@ -143,9 +143,7 @@ class ImagePickerActivity : AppCompatActivity() { * Dispatch incoming result to the correct provider. */ override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray + requestCode: Int, permissions: Array, grantResults: IntArray ) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) mCameraProvider?.onRequestPermissionsResult(requestCode) @@ -170,8 +168,7 @@ class ImagePickerActivity : AppCompatActivity() { outputFormat = mCropProvider.outputFormat() ) mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress( - uri = uri, - outputFormat = mCropProvider.outputFormat() + uri = uri, outputFormat = mCropProvider.outputFormat() ) else -> setResult(uri) } @@ -180,7 +177,7 @@ class ImagePickerActivity : AppCompatActivity() { fun setMultipleImage(fileList: ArrayList) { this.fileToCrop = fileList - if (!fileList.isNullOrEmpty()) { + if (fileList.isNotEmpty()) { val file = fileList[0] setMultipleCropper(uri = file) try { @@ -203,8 +200,7 @@ class ImagePickerActivity : AppCompatActivity() { outputFormat = mCropProvider.outputFormat() ) mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress( - uri = uri, - outputFormat = mCropProvider.outputFormat() + uri = uri, outputFormat = mCropProvider.outputFormat() ) } } @@ -255,17 +251,14 @@ class ImagePickerActivity : AppCompatActivity() { mCameraProvider?.let { // Delete Camera file after Compress. Else there will be two image for the same action. // In case of Gallery Provider, we will get original image path, so we will not delete that. - file.delete() - // it.delete() - } - - // If crop file is not null, Delete it after crop - mCropUri?.path?.let { - File(it).delete() + mImageUri?.path?.let { path -> + File(path).delete() + } + it.delete() + mImageUri = null } - mCropUri = null - setResult(mCropUri!!) + setResult(Uri.fromFile(file)) } /** @@ -308,4 +301,4 @@ class ImagePickerActivity : AppCompatActivity() { finish() } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/BaseProvider.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/BaseProvider.kt index f3e279f..a0bc3b9 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/BaseProvider.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/BaseProvider.kt @@ -55,14 +55,12 @@ abstract class BaseProvider(protected val activity: ImagePickerActivity) : /** * This method will be Call on Error, It can be used for clean up Tasks */ - protected open fun onFailure() { - } + protected open fun onFailure() {} /** * Save all appropriate provider state. */ - open fun onSaveInstanceState(outState: Bundle) { - } + open fun onSaveInstanceState(outState: Bundle) {} /** * Restores the saved state for all Providers. @@ -70,6 +68,5 @@ abstract class BaseProvider(protected val activity: ImagePickerActivity) : * @param savedInstanceState the Bundle returned by {@link #onSaveInstanceState()} * @see #onSaveInstanceState() */ - open fun onRestoreInstanceState(savedInstanceState: Bundle?) { - } + open fun onRestoreInstanceState(savedInstanceState: Bundle?) {} } diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CameraProvider.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CameraProvider.kt index c90cfc3..608a4ab 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CameraProvider.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CameraProvider.kt @@ -39,9 +39,7 @@ class CameraProvider( /** * Permission Require for Image Capture using Camera */ - private val REQUIRED_PERMISSIONS = arrayOf( - Manifest.permission.CAMERA - ) + private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA) private const val PERMISSION_INTENT_REQ_CODE = 4282 } @@ -200,4 +198,4 @@ class CameraProvider( }.toTypedArray() } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CompressionProvider.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CompressionProvider.kt index 40011f8..cdab389 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CompressionProvider.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CompressionProvider.kt @@ -10,9 +10,11 @@ import com.github.drjacky.imagepicker.ImagePicker import com.github.drjacky.imagepicker.ImagePickerActivity import com.github.drjacky.imagepicker.util.ExifDataCopier import com.github.drjacky.imagepicker.util.FileUriUtils +import com.github.drjacky.imagepicker.util.ImageUtil.getBitmap import kotlinx.coroutines.launch import java.io.File import java.io.FileOutputStream +import java.util.* /** * Compress Selected/Captured Image @@ -66,8 +68,8 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity } private fun compressTask(uri: Uri, outputFormat: Bitmap.CompressFormat?): File? { - var bitmap = BitmapFactory.decodeFile(uri.path, BitmapFactory.Options()) - if (maxWidth > 0L && maxHeight > 0L) { + var bitmap = getBitmap(activity, uri) + if (bitmap != null && maxWidth > 0L && maxHeight > 0L) { // resize if desired bitmap = if ((bitmap.width > maxWidth || bitmap.height > maxHeight) && keepRatio) { var width = maxWidth @@ -90,7 +92,7 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity val format = outputFormat ?: FileUriUtils.getImageExtensionFormat(baseContext, uri) var out: FileOutputStream? = null return try { - val temp = "temp.${format.name}" + val temp = "temp${Random().nextInt()}.${format.name}" val tempPath = activity.filesDir.toString() + "/$temp" with(File(tempPath)) { if (exists()) { @@ -98,7 +100,7 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity } } out = activity.openFileOutput(temp, Context.MODE_PRIVATE) - bitmap.compress(format, 100, out) + bitmap?.compress(format, 100, out) File(tempPath) } catch (e: Exception) { e.printStackTrace() @@ -121,4 +123,4 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity BitmapFactory.decodeStream(contentResolver.openInputStream(uri), null, options) return intArrayOf(options.outWidth, options.outHeight) } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CropProvider.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CropProvider.kt index 2b57246..341076b 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CropProvider.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/CropProvider.kt @@ -1,13 +1,9 @@ package com.github.drjacky.imagepicker.provider import android.app.Activity -import android.content.Context import android.content.Intent import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.ImageDecoder import android.net.Uri -import android.os.Build import android.os.Bundle import android.os.Environment import androidx.activity.result.ActivityResult @@ -17,6 +13,7 @@ import com.github.drjacky.imagepicker.ImagePickerActivity import com.github.drjacky.imagepicker.R import com.github.drjacky.imagepicker.util.FileUriUtils import com.github.drjacky.imagepicker.util.FileUtil.getCompressFormat +import com.github.drjacky.imagepicker.util.ImageUtil.getBitmap import com.yalantis.ucrop.UCrop import java.io.ByteArrayOutputStream import java.io.File @@ -213,24 +210,6 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent) } } - private fun getBitmap(context: Context, imageUri: Uri): Bitmap? { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - try { - ImageDecoder.decodeBitmap( - ImageDecoder.createSource(context.contentResolver, imageUri) - ) - } catch (e: ImageDecoder.DecodeException) { - null - } - } else { - context - .contentResolver - .openInputStream(imageUri)?.use { inputStream -> - BitmapFactory.decodeStream(inputStream) - } - } - } - @Throws(IOException::class) private fun convertBitmapToFile(destinationFile: File, bitmap: Bitmap, extension: String) { destinationFile.createNewFile() @@ -262,4 +241,4 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent) cropImageUri = null } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/GalleryProvider.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/GalleryProvider.kt index 0ec356c..949874d 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/GalleryProvider.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/provider/GalleryProvider.kt @@ -26,8 +26,7 @@ import java.io.IOException class GalleryProvider( activity: ImagePickerActivity, private val launcher: (Intent) -> Unit -) : - BaseProvider(activity) { +) : BaseProvider(activity) { private var fileList: ArrayList? = null @@ -46,13 +45,9 @@ class GalleryProvider( Manifest.permission.WRITE_EXTERNAL_STORAGE ) } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - arrayOf( - Manifest.permission.READ_MEDIA_IMAGES - ) + arrayOf(Manifest.permission.READ_MEDIA_IMAGES) } else { - arrayOf( - Manifest.permission.READ_EXTERNAL_STORAGE - ) + arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE) } private const val PERMISSION_INTENT_REQ_CODE = 4262 @@ -162,7 +157,7 @@ class GalleryProvider( */ private fun handleResult(data: Intent?) { data?.clipData?.let { dataClipData -> - fileList = ArrayList() + fileList = ArrayList() for (i in 0 until dataClipData.itemCount) { val uri = dataClipData.getItemAt(i).uri fileList!!.add(uri) @@ -192,4 +187,4 @@ class GalleryProvider( } } } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/ImageUtil.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/ImageUtil.kt index 960f933..f301b18 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/ImageUtil.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/ImageUtil.kt @@ -15,7 +15,9 @@ */ package com.github.drjacky.imagepicker.util +import android.content.Context import android.graphics.* +import android.net.Uri import android.os.Build import java.io.File import java.io.FileOutputStream @@ -211,4 +213,23 @@ object ImageUtil { else -> 1 } } -} + + fun getBitmap(context: Context, imageUri: Uri): Bitmap? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + try { + ImageDecoder.decodeBitmap( + ImageDecoder.createSource(context.contentResolver, imageUri) + ) + } catch (e: ImageDecoder.DecodeException) { + e.printStackTrace() + null + } + } else { + context + .contentResolver + .openInputStream(imageUri)?.use { inputStream -> + BitmapFactory.decodeStream(inputStream) + } + } + } +} \ No newline at end of file diff --git a/sample/src/main/kotlin/com.github.drjacky.imagepicker/sample/MainActivity.kt b/sample/src/main/kotlin/com.github.drjacky.imagepicker/sample/MainActivity.kt index 5344ea1..1808748 100644 --- a/sample/src/main/kotlin/com.github.drjacky.imagepicker/sample/MainActivity.kt +++ b/sample/src/main/kotlin/com.github.drjacky.imagepicker/sample/MainActivity.kt @@ -140,7 +140,7 @@ class MainActivity : AppCompatActivity() { fun pickCameraImage(view: View) { cameraLauncher.launch( ImagePicker.with(this) - .crop() + //.crop() .cameraOnly() .maxResultSize(1080, 1920, true) .createIntent() @@ -174,4 +174,4 @@ class MainActivity : AppCompatActivity() { .setPositiveButton("Ok", null) .show() } -} +} \ No newline at end of file From f586c94cf2e65cf73dd0044cfbfa48491de59f5f Mon Sep 17 00:00:00 2001 From: ZARA Date: Fri, 19 May 2023 14:44:54 +0330 Subject: [PATCH 2/2] #87 Support crop selection --- .../github/drjacky/imagepicker/ImagePicker.kt | 23 ++-- .../imagepicker/ImagePickerActivity.kt | 35 +++--- .../imagepicker/constant/ImageProvider.kt | 2 + .../drjacky/imagepicker/util/DialogHelper.kt | 10 +- .../src/main/res/layout/dialog_choose_app.xml | 101 ++++++++++-------- imagepicker/src/main/res/values/strings.xml | 1 + 6 files changed, 98 insertions(+), 74 deletions(-) diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePicker.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePicker.kt index 76cfc22..1f3c40d 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePicker.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePicker.kt @@ -277,26 +277,30 @@ open class ImagePicker { fun createIntent(): Intent = Intent(activity, ImagePickerActivity::class.java).apply { putExtras(getBundle()) } - fun createIntentFromDialog( - onResult: (Intent) -> Unit - ) { + fun createIntentFromDialog(onResult: (Intent) -> Unit) { if (imageProvider == ImageProvider.BOTH) { DialogHelper.showChooseAppDialog( - context = activity, - listener = object : ResultListener { + context = activity, listener = object : ResultListener { override fun onResult(t: ImageProvider?) { t?.let { imageProvider = it + setImageProviderInterceptor { + setCrop(imageProvider) + } imageProviderInterceptor?.invoke(imageProvider) onResult(createIntent()) } } - }, - dismissListener + }, dismissListener ) } } + private fun setCrop(imageProvider: ImageProvider) { + crop = imageProvider == ImageProvider.CAMERA_WITH_CROP + || imageProvider == ImageProvider.GALLERY_WITH_CROP + } + /** * Get Bundle for ImagePickerActivity */ @@ -304,7 +308,6 @@ open class ImagePicker { return Bundle().apply { putSerializable(EXTRA_IMAGE_PROVIDER, imageProvider) putStringArray(EXTRA_MIME_TYPES, mimeTypes) - putBoolean(EXTRA_CROP_OVAL, cropOval) putBoolean(EXTRA_CROP_FREE_STYLE, cropFreeStyle) putBoolean(EXTRA_CROP, crop) @@ -312,13 +315,11 @@ open class ImagePicker { putFloat(EXTRA_CROP_X, cropX) putFloat(EXTRA_CROP_Y, cropY) putSerializable(EXTRA_OUTPUT_FORMAT, outputFormat) - putInt(EXTRA_MAX_WIDTH, maxWidth) putInt(EXTRA_MAX_HEIGHT, maxHeight) - putBoolean(EXTRA_KEEP_RATIO, keepRatio) } } } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt index 119ec37..c319f33 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/ImagePickerActivity.kt @@ -114,23 +114,11 @@ class ImagePickerActivity : AppCompatActivity() { // Create Gallery/Camera Provider when (intent?.getSerializableExtra(ImagePicker.EXTRA_IMAGE_PROVIDER) as ImageProvider?) { - ImageProvider.GALLERY -> { - mGalleryProvider = GalleryProvider(this) { galleryLauncher.launch(it) } - // Pick Gallery Image - savedInstanceState ?: mGalleryProvider?.startIntent() - } - ImageProvider.CAMERA -> { - mCameraProvider = CameraProvider(this, false) { cameraLauncher.launch(it) } - mCameraProvider?.onRestoreInstanceState(savedInstanceState) - // Pick Camera Image - savedInstanceState ?: mCameraProvider?.startIntent() - } - ImageProvider.FRONT_CAMERA -> { - mCameraProvider = CameraProvider(this, true) { cameraLauncher.launch(it) } - mCameraProvider?.onRestoreInstanceState(savedInstanceState) - // Try Pick Front Camera Image - savedInstanceState ?: mCameraProvider?.startIntent() - } + ImageProvider.GALLERY -> pickGalleryImage(savedInstanceState) + ImageProvider.GALLERY_WITH_CROP -> pickGalleryImage(savedInstanceState) + ImageProvider.CAMERA -> pickCameraImage(savedInstanceState, false) + ImageProvider.CAMERA_WITH_CROP -> pickCameraImage(savedInstanceState, false) + ImageProvider.FRONT_CAMERA -> pickCameraImage(savedInstanceState, true) else -> { // Something went Wrong! This case should never happen Log.e(TAG, "Image provider can not be null") @@ -139,6 +127,19 @@ class ImagePickerActivity : AppCompatActivity() { } } + private fun pickGalleryImage(savedInstanceState: Bundle?) { + mGalleryProvider = GalleryProvider(this) { galleryLauncher.launch(it) } + // Pick Gallery Image + savedInstanceState ?: mGalleryProvider?.startIntent() + } + + private fun pickCameraImage(savedInstanceState: Bundle?, tryFrontCamera: Boolean) { + mCameraProvider = CameraProvider(this, tryFrontCamera) { cameraLauncher.launch(it) } + mCameraProvider?.onRestoreInstanceState(savedInstanceState) + // Pick Camera Image + savedInstanceState ?: mCameraProvider?.startIntent() + } + /** * Dispatch incoming result to the correct provider. */ diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/constant/ImageProvider.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/constant/ImageProvider.kt index d5402c9..b489c54 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/constant/ImageProvider.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/constant/ImageProvider.kt @@ -9,7 +9,9 @@ package com.github.drjacky.imagepicker.constant */ enum class ImageProvider { GALLERY, + GALLERY_WITH_CROP, CAMERA, + CAMERA_WITH_CROP, FRONT_CAMERA, BOTH } diff --git a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/DialogHelper.kt b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/DialogHelper.kt index f5f2bd6..c1f961c 100644 --- a/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/DialogHelper.kt +++ b/imagepicker/src/main/kotlin/com/github/drjacky/imagepicker/util/DialogHelper.kt @@ -47,14 +47,18 @@ internal object DialogHelper { // Handle Camera option click customView.lytCameraPick.setOnClickListener { - listener.onResult(ImageProvider.CAMERA) + listener.onResult( + if (customView.displayCropCheckBox.isChecked) ImageProvider.CAMERA_WITH_CROP else ImageProvider.CAMERA + ) dialog.dismiss() } // Handle Gallery option click customView.lytGalleryPick.setOnClickListener { - listener.onResult(ImageProvider.GALLERY) + listener.onResult( + if (customView.displayCropCheckBox.isChecked) ImageProvider.GALLERY_WITH_CROP else ImageProvider.GALLERY + ) dialog.dismiss() } } -} +} \ No newline at end of file diff --git a/imagepicker/src/main/res/layout/dialog_choose_app.xml b/imagepicker/src/main/res/layout/dialog_choose_app.xml index 49a68e9..a0d51b7 100644 --- a/imagepicker/src/main/res/layout/dialog_choose_app.xml +++ b/imagepicker/src/main/res/layout/dialog_choose_app.xml @@ -3,58 +3,73 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:baselineAligned="false" - android:orientation="horizontal" + android:orientation="vertical" android:padding="16dp"> - - - - + + + android:layout_marginTop="10dp" + android:layout_weight="1" + android:gravity="center" + android:orientation="vertical"> - + - - - - - + + + + + android:layout_marginTop="10dp" + android:layout_weight="1" + android:gravity="center" + android:orientation="vertical"> + + + + + + + + \ No newline at end of file diff --git a/imagepicker/src/main/res/values/strings.xml b/imagepicker/src/main/res/values/strings.xml index 706e4c2..36c7fff 100644 --- a/imagepicker/src/main/res/values/strings.xml +++ b/imagepicker/src/main/res/values/strings.xml @@ -9,6 +9,7 @@ Cancel Gallery Camera + Display crop Permissions.]]>