Skip to content
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
1 change: 1 addition & 0 deletions imagepicker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ dependencies {

//More Info: https://github.com/Yalantis/uCrop
implementation 'com.github.yalantis:ucrop:2.2.6'
implementation "com.github.forJrking:KLuban:1.1.0"

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package com.github.dhaval2404.imagepicker.provider

import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.net.Uri
import android.os.AsyncTask
import android.os.Bundle
import com.forjrking.lubankt.Luban
import com.github.dhaval2404.imagepicker.ImagePicker
import com.github.dhaval2404.imagepicker.ImagePickerActivity
import com.github.dhaval2404.imagepicker.util.ExifDataCopier
import com.github.dhaval2404.imagepicker.util.FileUtil
import com.github.dhaval2404.imagepicker.util.ImageUtil
import java.io.File

/**
Expand All @@ -21,10 +18,6 @@ import java.io.File
*/
class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity) {

companion object {
private val TAG = CompressionProvider::class.java.simpleName
}

private val mMaxWidth: Int
private val mMaxHeight: Int
private val mMaxFileSize: Long
Expand Down Expand Up @@ -55,20 +48,6 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
return mMaxFileSize > 0L
}

/**
* Check if compression is required
* @param file File object to apply Compression
*/
private fun isCompressionRequired(file: File): Boolean {
val status = isCompressEnabled() && getSizeDiff(file) > 0L
if (!status && mMaxWidth > 0 && mMaxHeight > 0) {
// Check image resolution
val resolution = FileUtil.getImageResolution(file)
return resolution.first > mMaxWidth || resolution.second > mMaxHeight
}
return status
}

/**
* Check if compression is required
* @param uri Uri object to apply Compression
Expand All @@ -83,10 +62,6 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
return status
}

private fun getSizeDiff(file: File): Long {
return file.length() - mMaxFileSize
}

private fun getSizeDiff(uri: Uri): Long {
val length = FileUtil.getImageSize(this, uri)
return length - mMaxFileSize
Expand All @@ -106,128 +81,20 @@ class CompressionProvider(activity: ImagePickerActivity) : BaseProvider(activity
*/
@SuppressLint("StaticFieldLeak")
private fun startCompressionWorker(uri: Uri) {
object : AsyncTask<Uri, Void, File>() {
override fun doInBackground(vararg params: Uri): File? {
// Perform operation in background
val file = FileUtil.getTempFile(this@CompressionProvider, params[0]) ?: return null
return startCompression(file)
}

override fun onPostExecute(file: File?) {
super.onPostExecute(file)
if (file != null) {
// Post Result
handleResult(file)
} else {
// Post Error
setError(com.github.dhaval2404.imagepicker.R.string.error_failed_to_compress_image)
}
}
}.execute(uri)
}

/**
* Check if compression required, And Apply compression until file size reach below Max Size.
*/
private fun startCompression(file: File): File? {
var newFile: File? = null
var attempt = 0
var lastAttempt = 0
do {
// Delete file if exist, fill will be exist in second loop.
newFile?.delete()

newFile = applyCompression(file, attempt)
if (newFile == null) {
return if (attempt > 0) {
applyCompression(file, lastAttempt)
} else {
null
runCatching { mFileDir.mkdirs() }
Luban.with(activity)
.load(uri)
.ignoreBy(mMaxFileSize / 1024L)
.setOutPutDir("$mFileDir")
.compressObserver {
onSuccess = { compressFile ->
handleResult(compressFile)
}
}
lastAttempt = attempt

if (mMaxFileSize > 0) {
val diff = getSizeDiff(newFile)
// Log.i(TAG, "Size Diff:$diff")
attempt += when {
diff > 1024 * 1024 -> 3
diff > 500 * 1024 -> 2
else -> 1
onError = { e, s ->
setError(com.github.dhaval2404.imagepicker.R.string.error_failed_to_compress_image)
}
} else {
attempt++
}
} while (isCompressionRequired(newFile!!))

// Copy Exif Data
ExifDataCopier.copyExif(file, newFile)

return newFile
}

/**
* Compress the file
*/
private fun applyCompression(file: File, attempt: Int): File? {
val resList = resolutionList()
if (attempt >= resList.size) {
return null
}

// Apply logic to get scaled bitmap resolution.
val resolution = resList[attempt]
var maxWidth = resolution[0]
var maxHeight = resolution[1]

if (mMaxWidth > 0 && mMaxHeight > 0) {
if (maxWidth > mMaxWidth || maxHeight > mMaxHeight) {
maxHeight = mMaxHeight
maxWidth = mMaxWidth
}
}
// Log.d(TAG, "maxWidth:$maxWidth, maxHeight:$maxHeight")

// Check file format
var format = Bitmap.CompressFormat.JPEG
if (file.absolutePath.endsWith(".png")) {
format = Bitmap.CompressFormat.PNG
}

val extension = FileUtil.getImageExtension(file)
val compressFile: File? = FileUtil.getImageFile(fileDir = mFileDir, extension = extension)
return if (compressFile != null) {
ImageUtil.compressImage(
file, maxWidth.toFloat(), maxHeight.toFloat(),
format, compressFile.absolutePath
)
} else {
null
}
}

/**
* Image Resolution will be reduce with below parameters.
*
*/
private fun resolutionList(): List<IntArray> {
return listOf(
intArrayOf(2448, 3264), // 8.0 Megapixel
intArrayOf(2008, 3032), // 6.0 Megapixel
intArrayOf(1944, 2580), // 5.0 Megapixel
intArrayOf(1680, 2240), // 4.0 Megapixel
intArrayOf(1536, 2048), // 3.0 Megapixel
intArrayOf(1200, 1600), // 2.0 Megapixel
intArrayOf(1024, 1392), // 1.3 Megapixel
intArrayOf(960, 1280), // 1.0 Megapixel
intArrayOf(768, 1024), // 0.7 Megapixel
intArrayOf(600, 800), // 0.4 Megapixel
intArrayOf(480, 640), // 0.3 Megapixel
intArrayOf(240, 320), // 0.15 Megapixel
intArrayOf(120, 160), // 0.08 Megapixel
intArrayOf(60, 80), // 0.04 Megapixel
intArrayOf(30, 40) // 0.02 Megapixel
)
.launch()
}

/**
Expand Down