Skip to content

#87 Support crop selection #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -277,48 +277,49 @@ 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<ImageProvider> {
context = activity, listener = object : ResultListener<ImageProvider> {
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
*/
private fun getBundle(): Bundle {
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)
putBoolean(MULTIPLE_FILES_ALLOWED, isMultiple)
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)
}
}
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -139,13 +127,24 @@ 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.
*/
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
requestCode: Int, permissions: Array<String>, grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
mCameraProvider?.onRequestPermissionsResult(requestCode)
Expand All @@ -170,8 +169,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)
}
Expand All @@ -180,7 +178,7 @@ class ImagePickerActivity : AppCompatActivity() {
fun setMultipleImage(fileList: ArrayList<Uri>) {
this.fileToCrop = fileList

if (!fileList.isNullOrEmpty()) {
if (fileList.isNotEmpty()) {
val file = fileList[0]
setMultipleCropper(uri = file)
try {
Expand All @@ -203,8 +201,7 @@ class ImagePickerActivity : AppCompatActivity() {
outputFormat = mCropProvider.outputFormat()
)
mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress(
uri = uri,
outputFormat = mCropProvider.outputFormat()
uri = uri, outputFormat = mCropProvider.outputFormat()
)
}
}
Expand Down Expand Up @@ -255,17 +252,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))
}

/**
Expand Down Expand Up @@ -308,4 +302,4 @@ class ImagePickerActivity : AppCompatActivity() {
finish()
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ package com.github.drjacky.imagepicker.constant
*/
enum class ImageProvider {
GALLERY,
GALLERY_WITH_CROP,
CAMERA,
CAMERA_WITH_CROP,
FRONT_CAMERA,
BOTH
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,18 @@ 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.
*
* @param savedInstanceState the Bundle returned by {@link #onSaveInstanceState()}
* @see #onSaveInstanceState()
*/
open fun onRestoreInstanceState(savedInstanceState: Bundle?) {
}
open fun onRestoreInstanceState(savedInstanceState: Bundle?) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -200,4 +198,4 @@ class CameraProvider(
}.toTypedArray()
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -90,15 +92,15 @@ 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()) {
delete()
}
}
out = activity.openFileOutput(temp, Context.MODE_PRIVATE)
bitmap.compress(format, 100, out)
bitmap?.compress(format, 100, out)
File(tempPath)
} catch (e: Exception) {
e.printStackTrace()
Expand All @@ -121,4 +123,4 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
BitmapFactory.decodeStream(contentResolver.openInputStream(uri), null, options)
return intArrayOf(options.outWidth, options.outHeight)
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -262,4 +241,4 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent)
cropImageUri = null
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Uri>? = null

Expand All @@ -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
Expand Down Expand Up @@ -162,7 +157,7 @@ class GalleryProvider(
*/
private fun handleResult(data: Intent?) {
data?.clipData?.let { dataClipData ->
fileList = ArrayList<Uri>()
fileList = ArrayList()
for (i in 0 until dataClipData.itemCount) {
val uri = dataClipData.getItemAt(i).uri
fileList!!.add(uri)
Expand Down Expand Up @@ -192,4 +187,4 @@ class GalleryProvider(
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
}
}
Loading