-
-
Notifications
You must be signed in to change notification settings - Fork 965
/
Util.kt
108 lines (90 loc) · 3.51 KB
/
Util.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package id.zelory.compressor
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import java.io.File
import java.io.FileOutputStream
/**
* Created on : January 24, 2020
* Author : zetbaitsu
* Name : Zetra
* GitHub : https://github.com/zetbaitsu
*/
private val separator = File.separator
private fun cachePath(context: Context) = "${context.cacheDir.path}${separator}compressor$separator"
fun File.compressFormat() = when (extension.toLowerCase()) {
"png" -> Bitmap.CompressFormat.PNG
"webp" -> Bitmap.CompressFormat.WEBP
else -> Bitmap.CompressFormat.JPEG
}
fun Bitmap.CompressFormat.extension() = when (this) {
Bitmap.CompressFormat.PNG -> "png"
Bitmap.CompressFormat.WEBP -> "webp"
else -> "jpg"
}
fun loadBitmap(imageFile: File) = BitmapFactory.decodeFile(imageFile.absolutePath).run {
determineImageRotation(imageFile, this)
}
fun decodeSampledBitmapFromFile(imageFile: File, reqWidth: Int, reqHeight: Int): Bitmap {
return BitmapFactory.Options().run {
inJustDecodeBounds = true
BitmapFactory.decodeFile(imageFile.absolutePath, this)
inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)
inJustDecodeBounds = false
BitmapFactory.decodeFile(imageFile.absolutePath, this)
}
}
fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
// Raw height and width of image
val (height: Int, width: Int) = options.run { outHeight to outWidth }
var inSampleSize = 1
if (height > reqHeight || width > reqWidth) {
val halfHeight: Int = height / 2
val halfWidth: Int = width / 2
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2
}
}
return inSampleSize
}
fun determineImageRotation(imageFile: File, bitmap: Bitmap): Bitmap {
val exif = ExifInterface(imageFile.absolutePath)
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)
val matrix = Matrix()
when (orientation) {
6 -> matrix.postRotate(90f)
3 -> matrix.postRotate(180f)
8 -> matrix.postRotate(270f)
}
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}
internal fun copyToCache(context: Context, imageFile: File): File {
return imageFile.copyTo(File("${cachePath(context)}${imageFile.name}"), true)
}
fun overWrite(imageFile: File, bitmap: Bitmap, format: Bitmap.CompressFormat = imageFile.compressFormat(), quality: Int = 100): File {
val result = if (format == imageFile.compressFormat()) {
imageFile
} else {
File("${imageFile.absolutePath.substringBeforeLast(".")}.${format.extension()}")
}
imageFile.delete()
saveBitmap(bitmap, result, format, quality)
return result
}
fun saveBitmap(bitmap: Bitmap, destination: File, format: Bitmap.CompressFormat = destination.compressFormat(), quality: Int = 100) {
destination.parentFile?.mkdirs()
var fileOutputStream: FileOutputStream? = null
try {
fileOutputStream = FileOutputStream(destination.absolutePath)
bitmap.compress(format, quality, fileOutputStream)
} finally {
fileOutputStream?.run {
flush()
close()
}
}
}