Skip to content

Instantly share code, notes, and snippets.

@AndSky90
Created November 4, 2019 12:00
Show Gist options
  • Save AndSky90/640328d07df18e76f9687e8dd31d4e7a to your computer and use it in GitHub Desktop.
Save AndSky90/640328d07df18e76f9687e8dd31d4e7a to your computer and use it in GitHub Desktop.
Image compress and rotate
object ImageProcessor {
private const val MAX_IMAGE_DIMENSION = 1920
private const val COMPRESS_QUALITY = 100
@Throws(IOException::class)
fun saveImageWithFixFromUri(context: Context, uri: Uri, filePath: String) {
val bitmap = getFixedImageFromUri(context, uri)
saveBitmapToFile(bitmap, filePath)
}
@Throws(IOException::class)
private fun getFixedImageFromUri(context: Context, photoUri: Uri): Bitmap {
val bmpOptions =
BitmapFactory.Options().apply { inSampleSize = getScaleRatioFromUri(context, photoUri) }
val inputStream = context.contentResolver.openInputStream(photoUri)
val bitmap = BitmapFactory.decodeStream(inputStream, null, bmpOptions)!!
inputStream?.close()
val degrees = getOrientationFromUri(context, photoUri)
return if (degrees > 0) {
val output = rotate(bitmap, degrees.toFloat())
bitmap.recycle()
output
} else bitmap
}
private fun getScaleRatioFromUri(context: Context, photoUri: Uri): Int {
val inputStream = context.contentResolver.openInputStream(photoUri)
val boundsOptions = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeStream(inputStream, null, boundsOptions)
inputStream?.close()
return getScale(boundsOptions)
}
private fun getOrientationFromUri(context: Context, selectedImage: Uri): Int {
val cursor = context.contentResolver.query(
selectedImage,
arrayOf(MediaStore.Images.ImageColumns.ORIENTATION), null, null, null
)
return if (cursor?.count != 1)
0
else {
cursor.moveToFirst()
val degrees = cursor.getInt(0)
cursor.close()
degrees
}
}
fun fixBitmapOrientation(filePath: String?) {
if (filePath == null) return
val bitmap = getFixedImageFromPath(filePath)
saveBitmapToFile(bitmap, filePath)
}
private fun getFixedImageFromPath(filePath: String): Bitmap {
val bmpOptions =
BitmapFactory.Options().apply { inSampleSize = getScaleRatioFromPath(filePath) }
val bitmap = BitmapFactory.decodeFile(filePath, bmpOptions)
val degrees = getOrientationFromPath(filePath)
return if (degrees > 0) {
val output = rotate(bitmap, degrees.toFloat())
bitmap.recycle()
output
} else bitmap
}
private fun getScaleRatioFromPath(filePath: String): Int {
val boundsOptions = BitmapFactory.Options().apply { inJustDecodeBounds = true }
BitmapFactory.decodeFile(filePath, boundsOptions)
return getScale(boundsOptions)
}
private fun getOrientationFromPath(filePath: String): Int {
val exifOrientation = ExifInterface(filePath)
.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)
log("ExifInterface ......... orientation = $exifOrientation")
return when (exifOrientation) {
ExifInterface.ORIENTATION_ROTATE_180 -> 180
ExifInterface.ORIENTATION_ROTATE_90 -> 90
ExifInterface.ORIENTATION_ROTATE_270 -> 270
else -> 0
}
}
private fun getScale(boundsOptions: BitmapFactory.Options): Int {
// Find the correct scale value. It should be the power of 2.
var widthTmp = boundsOptions.outWidth
var heightTmp = boundsOptions.outHeight
val requiredSize = MAX_IMAGE_DIMENSION
var scale = 1
while (true) {
if (widthTmp / 2 < requiredSize && heightTmp / 2 < requiredSize) break
widthTmp /= 2
heightTmp /= 2
scale++
}
log("scale of saved image = $scale")
return scale
}
private fun saveBitmapToFile(bitmap: Bitmap, filePath: String) {
val os = BufferedOutputStream(FileOutputStream(filePath))
bitmap.compress(Bitmap.CompressFormat.PNG, COMPRESS_QUALITY, os)
log("height and width from gallery: ${bitmap.height}, ${bitmap.width}")
os.close()
}
private fun rotate(bitmap: Bitmap, degrees: Float): Bitmap {
val matrix = Matrix().apply { postRotate(degrees) }
return Bitmap
.createBitmap(bitmap, 0, 0, bitmap.width, bitmap.height, matrix, true)
}
fun createImageFile(context: Context?): File? {
try {
val storageDir: File? = context?.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
val photoFile = File.createTempFile("Current_user_avatar", ".jpg", storageDir)
photoFile.setWritable(true)
return photoFile
} catch (ex: IOException) {
log("Error creating file")
}
return null
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment