Skip to content

Commit

Permalink
Let usser define the output format
Browse files Browse the repository at this point in the history
  • Loading branch information
Drjacky committed Aug 23, 2022
1 parent d9bb1d8 commit 7594348
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 69 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![PRWelcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/Drjacky/ImagePicker/pulls)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FDrjacky%2FImagePicker.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FDrjacky%2FImagePicker?ref=badge_shield)
[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-ImagePicker-green.svg?style=flat)](https://android-arsenal.com/details/1/8208)
![Language](https://img.shields.io/badge/Kotlin-1.5.31-blue)
![Language](https://img.shields.io/badge/Kotlin-1.7.10-blue)

Easy to use and configurable library to **Pick an image from the Gallery or Capture image using Camera**. It also allows to **Crop the Image based on Aspect Ratio, Resolution and Image Size**.

Expand Down Expand Up @@ -123,12 +123,13 @@ Where `$libVersion` = [![libVersion](https://img.shields.io/github/release/drjac

```java
ImagePicker.Companion.with(this)
.crop() //Crop image(Optional), Check Customization for more option
.cropOval() //Allow dimmed layer to have a circle inside
.cropFreeStyle() //Let the user to resize crop bounds
.setMultipleAllowed(true) //true or false if you want to pick multiple files or single file in gallery mode
.galleryOnly() //We have to define what image provider we want to use
.maxResultSize(1080,1080) //Final image resolution will be less than 1080 x 1080(Optional)
.crop() //Crop image(Optional), Check Customization for more option
.cropOval() //Allow dimmed layer to have a circle inside
.cropFreeStyle() //Let the user to resize crop bounds
.setMultipleAllowed(true) //Let the user to pick multiple files or single file in gallery mode
.setOutputFormat(Bitmap.CompressFormat.WEBP) //Let the user defines the output format
.galleryOnly() //We have to define what image provider we want to use
.maxResultSize(1080,1080) //Final image resolution will be less than 1080 x 1080(Optional)
.createIntent()
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.drjacky.imagepicker

import android.app.Activity
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import com.github.drjacky.imagepicker.constant.ImageProvider
Expand Down Expand Up @@ -33,6 +34,7 @@ open class ImagePicker {
internal const val EXTRA_MAX_WIDTH = "extra.max_width"
internal const val EXTRA_MAX_HEIGHT = "extra.max_height"
internal const val EXTRA_KEEP_RATIO = "extra.keep_ratio"
internal const val EXTRA_OUTPUT_FORMAT = "extra.output_format"

internal const val EXTRA_ERROR = "extra.error"
const val MULTIPLE_FILES_PATH = "extra.multiple_file_path"
Expand Down Expand Up @@ -113,6 +115,7 @@ open class ImagePicker {
private var crop: Boolean = false
private var cropOval: Boolean = false
private var cropFreeStyle: Boolean = false
private var outputFormat: Bitmap.CompressFormat? = null
private var isMultiple: Boolean = false

/*
Expand Down Expand Up @@ -220,6 +223,11 @@ open class ImagePicker {
return this
}

fun setOutputFormat(outputFormat: Bitmap.CompressFormat): Builder {
this.outputFormat = outputFormat
return this
}

/**
* Max Width and Height of final image
*/
Expand All @@ -243,7 +251,9 @@ 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,
Expand Down Expand Up @@ -274,6 +284,7 @@ open class ImagePicker {
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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,9 @@ class ImagePickerActivity : AppCompatActivity() {
mCompressionProvider = CompressionProvider(this)
mCroppedImageList = ArrayList()
// Retrieve Image Provider
val provider: ImageProvider? =
intent?.getSerializableExtra(ImagePicker.EXTRA_IMAGE_PROVIDER) as ImageProvider?

// Create Gallery/Camera Provider
when (provider) {
when (intent?.getSerializableExtra(ImagePicker.EXTRA_IMAGE_PROVIDER) as ImageProvider?) {
ImageProvider.GALLERY -> {
mGalleryProvider = GalleryProvider(this) { galleryLauncher.launch(it) }
// Pick Gallery Image
Expand Down Expand Up @@ -169,13 +167,49 @@ class ImagePickerActivity : AppCompatActivity() {
cropOval = mCropProvider.isCropOvalEnabled(),
cropFreeStyle = mCropProvider.isCropFreeStyleEnabled(),
isCamera = isCamera,
isMultipleFiles = false
isMultipleFiles = false,
outputFormat = mCropProvider.outputFormat()
)
mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress(
uri = uri,
outputFormat = mCropProvider.outputFormat()
)
mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress(uri)
else -> setResult(uri)
}
}

fun setMultipleImage(fileList: ArrayList<Uri>) {
this.fileToCrop = fileList

if (!fileList.isNullOrEmpty()) {
val file = fileList[0]
setMultipleCropper(uri = file)
try {
fileList.remove(fileList[0])
} catch (e: Exception) {
e.printStackTrace()
}
}
}

private fun setMultipleCropper(uri: Uri) {
mImageUri = uri
when {
mCropProvider.isCropEnabled() -> mCropProvider.startIntent(
uri = uri,
cropOval = mCropProvider.isCropOvalEnabled(),
cropFreeStyle = mCropProvider.isCropFreeStyleEnabled(),
isCamera = false,
isMultipleFiles = true,
outputFormat = mCropProvider.outputFormat()
)
mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress(
uri = uri,
outputFormat = mCropProvider.outputFormat()
)
}
}

/**
* {@link CropProviders} Result will be available here.
*
Expand All @@ -197,12 +231,21 @@ class ImagePickerActivity : AppCompatActivity() {
}

if (mCompressionProvider.isResizeRequired(uri)) {
mCompressionProvider.compress(uri)
mCompressionProvider.compress(uri = uri, outputFormat = mCropProvider.outputFormat())
} else {
setResult(uri)
}
}

fun setMultipleCropImage(uri: Uri) {
mCroppedImageList?.add(uri)
if (mCroppedImageList?.size == selectedNumberOfImages) {
setMultipleImageResult(mCroppedImageList!!)
} else {
setMultipleImage(fileToCrop)
}
}

/**
* {@link CompressionProvider} Result will be available here.
*
Expand Down Expand Up @@ -239,6 +282,13 @@ class ImagePickerActivity : AppCompatActivity() {
finish()
}

private fun setMultipleImageResult(uris: ArrayList<Uri>) {
val intent = Intent()
intent.putExtra(ImagePicker.MULTIPLE_FILES_PATH, uris)
setResult(Activity.RESULT_OK, intent)
finish()
}

/**
* User has cancelled the task
*/
Expand All @@ -259,48 +309,4 @@ class ImagePickerActivity : AppCompatActivity() {
finish()
}

fun setMultipleImage(fileList: ArrayList<Uri>) {
this.fileToCrop = fileList

if (!fileList.isNullOrEmpty()) {
val file = fileList[0]
setMultipleCropper(file)
try {
fileList.remove(fileList[0])
} catch (e: Exception) {
e.printStackTrace()
}
}
}

private fun setMultipleCropper(uri: Uri) {
mImageUri = uri
when {
mCropProvider.isCropEnabled() -> mCropProvider.startIntent(
uri = uri,
cropOval = mCropProvider.isCropOvalEnabled(),
cropFreeStyle = mCropProvider.isCropFreeStyleEnabled(),
isCamera = false,
isMultipleFiles = true
)
mCompressionProvider.isResizeRequired(uri) -> mCompressionProvider.compress(uri)
}
}

private fun setMultipleImageResult(uris: ArrayList<Uri>) {
val intent = Intent()
intent.putExtra(ImagePicker.MULTIPLE_FILES_PATH, uris)
setResult(Activity.RESULT_OK, intent)
finish()
}

fun setMultipleCropImage(uri: Uri) {
mCroppedImageList?.add(uri)
if (mCroppedImageList?.size == selectedNumberOfImages) {
setMultipleImageResult(mCroppedImageList!!)
} else {
setMultipleImage(fileToCrop)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
*
* @param uri File to compress
*/
fun compress(uri: Uri) {
fun compress(uri: Uri, outputFormat: Bitmap.CompressFormat?) {
activity.lifecycleScope.launch {
val res = compressTask(uri)
val res = compressTask(uri, outputFormat)
if (res != null) {
ExifDataCopier.copyExif(uri, res)
activity.setCompressedImage(res)
Expand All @@ -63,7 +63,7 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
}
}

private fun compressTask(uri: Uri): File? {
private fun compressTask(uri: Uri, outputFormat: Bitmap.CompressFormat?): File? {
var bitmap = BitmapFactory.decodeFile(uri.path, BitmapFactory.Options())
if (maxWidth > 0L && maxHeight > 0L) {
// resize if desired
Expand All @@ -85,7 +85,7 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
}
}

val format = FileUriUtils.getImageExtensionFormat(uri)
val format = outputFormat ?: FileUriUtils.getImageExtensionFormat(uri)
var out: FileOutputStream? = null
return try {
val temp = "temp.${format.name}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import android.os.Build
import android.os.Bundle
import android.os.Environment
import androidx.activity.result.ActivityResult
import androidx.annotation.Nullable
import com.github.drjacky.imagepicker.ImagePicker
import com.github.drjacky.imagepicker.ImagePickerActivity
import com.github.drjacky.imagepicker.R
Expand Down Expand Up @@ -46,6 +47,7 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent)
private val crop: Boolean
private val cropAspectX: Float
private val cropAspectY: Float
private val outputFormat: Bitmap.CompressFormat?

private var cropImageUri: Uri? = null

Expand All @@ -58,6 +60,7 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent)
cropFreeStyle = getBoolean(ImagePicker.EXTRA_CROP_FREE_STYLE, false)
cropAspectX = getFloat(ImagePicker.EXTRA_CROP_X, 0f)
cropAspectY = getFloat(ImagePicker.EXTRA_CROP_Y, 0f)
outputFormat = this.get(ImagePicker.EXTRA_OUTPUT_FORMAT) as Bitmap.CompressFormat
}
}

Expand Down Expand Up @@ -101,6 +104,14 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent)
*/
fun isCropEnabled() = crop

/**
* Get the output format if it has been set
*
* @return Bitmap.CompressFormat?. In case of Null, it will use the extension from the input file
*/
@Nullable
fun outputFormat() = outputFormat

/**
* Start Crop Activity
*/
Expand All @@ -110,14 +121,16 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent)
cropOval: Boolean,
cropFreeStyle: Boolean,
isCamera: Boolean,
isMultipleFiles: Boolean
isMultipleFiles: Boolean,
outputFormat: Bitmap.CompressFormat?
) {
this.isMultipleFiles = isMultipleFiles
cropImage(
uri = uri,
cropOval = cropOval,
cropFreeStyle = cropFreeStyle,
isCamera = isCamera,
outputFormat = outputFormat
)
}

Expand All @@ -131,13 +144,14 @@ class CropProvider(activity: ImagePickerActivity, private val launcher: (Intent)
cropOval: Boolean,
cropFreeStyle: Boolean,
isCamera: Boolean,
outputFormat: Bitmap.CompressFormat?
) {
val path = if (isCamera) {
Environment.DIRECTORY_DCIM
} else {
Environment.DIRECTORY_PICTURES
}
val extension = FileUriUtils.getImageExtension(uri)
val extension = outputFormat?.let { ".${it.name}" } ?: FileUriUtils.getImageExtension(uri)
cropImageUri = uri

// Later we will use this bitmap to create the File.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ internal object DialogHelper {
.setOnCancelListener {
listener.onResult(null)
}
.setOnDismissListener {
listener.onResult(null)
}
.setNegativeButton(R.string.action_cancel) { _, _ ->
listener.onResult(null)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,11 @@ object FileUtil {
* @return Bitmap CompressFormat
*/
fun getCompressFormat(extension: String): Bitmap.CompressFormat {
return when {
extension.contains("png", ignoreCase = true) -> Bitmap.CompressFormat.PNG
extension.contains("webp", ignoreCase = true) -> Bitmap.CompressFormat.WEBP
else -> Bitmap.CompressFormat.JPEG
}
val withoutDotExtension = extension.replace(".", "")
return safeValueOf<Bitmap.CompressFormat>(
name = withoutDotExtension.uppercase(),
defaultValue = Bitmap.CompressFormat.JPEG
)
}

/**
Expand All @@ -231,4 +231,12 @@ object FileUtil {
private fun isFileUri(uri: Uri): Boolean {
return "file".equals(uri.scheme, ignoreCase = true)
}

private inline fun <reified T : Enum<T>> safeValueOf(name: String, defaultValue: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, name) ?: defaultValue
} catch (e: IllegalArgumentException) {
defaultValue
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class MainActivity : AppCompatActivity() {
.crop()
.galleryOnly()
.setMultipleAllowed(true)
// .setOutputFormat(Bitmap.CompressFormat.WEBP)
.cropFreeStyle()
.galleryMimeTypes( // no gif images at all
mimeTypes = arrayOf(
Expand Down

0 comments on commit 7594348

Please sign in to comment.