Last active
September 8, 2018 12:50
-
-
Save phatnhse/523a9b2560c38d940e7c0e5ddeca63d2 to your computer and use it in GitHub Desktop.
BitmapUtils for java/android developement (written with Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object BitmapUtils { | |
private const val MAX_HEIGHT = 1280.0f | |
private const val MAX_WIDTH = 1280.0f | |
fun getScaledBitmap(bm: Bitmap, | |
bmOriginalWidth: Int, | |
bmOriginalHeight: Int, | |
originalWidthToHeightRatio: Double, | |
originalHeightToWidthRatio: Double, | |
maxHeight: Int, | |
maxWidth: Int): Bitmap { | |
var bm = bm | |
if (bmOriginalWidth > maxWidth || bmOriginalHeight > maxHeight) { | |
bm = if (bmOriginalWidth > bmOriginalHeight) { | |
scaleDeminsFromWidth(bm, maxWidth, bmOriginalHeight, originalHeightToWidthRatio) | |
} else { | |
scaleDeminsFromHeight(bm, maxHeight, bmOriginalHeight, originalWidthToHeightRatio) | |
} | |
} | |
return bm | |
} | |
private fun scaleDeminsFromHeight(bm: Bitmap, | |
maxHeight: Int, | |
bmOriginalHeight: Int, | |
originalWidthToHeightRatio: Double): Bitmap { | |
var bm = bm | |
val newHeight = Math.min(maxHeight.toDouble(), bmOriginalHeight * .75).toInt() | |
val newWidth = (newHeight * originalWidthToHeightRatio).toInt() | |
bm = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true) | |
return bm | |
} | |
private fun scaleDeminsFromWidth(bm: Bitmap, | |
maxWidth: Int, | |
bmOriginalWidth: Int, | |
originalHeightToWidthRatio: Double): Bitmap { | |
var bm = bm | |
//scale the width | |
val newWidth = Math.min(maxWidth.toDouble(), bmOriginalWidth * .75).toInt() | |
val newHeight = (newWidth * originalHeightToWidthRatio).toInt() | |
bm = Bitmap.createScaledBitmap(bm, newWidth, newHeight, true) | |
return bm | |
} | |
fun compressImage(imagePath: String) { | |
var scaledBitmap: Bitmap? = null | |
val options = BitmapFactory.Options() | |
options.inJustDecodeBounds = true | |
var bmp: Bitmap? = BitmapFactory.decodeFile(imagePath, options) | |
var actualHeight = options.outHeight | |
var actualWidth = options.outWidth | |
var imgRatio = actualWidth.toFloat() / actualHeight.toFloat() | |
val maxRatio = MAX_WIDTH / MAX_HEIGHT | |
if (actualHeight > MAX_HEIGHT || actualWidth > MAX_WIDTH) { | |
if (imgRatio < maxRatio) { | |
imgRatio = MAX_HEIGHT / actualHeight | |
actualWidth = (imgRatio * actualWidth).toInt() | |
actualHeight = MAX_HEIGHT.toInt() | |
} else if (imgRatio > maxRatio) { | |
imgRatio = MAX_WIDTH / actualWidth | |
actualHeight = (imgRatio * actualHeight).toInt() | |
actualWidth = MAX_WIDTH.toInt() | |
} else { | |
actualHeight = MAX_HEIGHT.toInt() | |
actualWidth = MAX_WIDTH.toInt() | |
} | |
} | |
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight) | |
options.inJustDecodeBounds = false | |
options.inDither = false | |
options.inScaled = false | |
options.inPurgeable = true | |
options.inInputShareable = true | |
options.inPreferredConfig = Bitmap.Config.ARGB_8888 | |
options.inTempStorage = ByteArray(16 * 1024) | |
try { | |
bmp = BitmapFactory.decodeFile(imagePath, options) | |
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565) | |
} catch (exception: OutOfMemoryError) { | |
exception.printStackTrace() | |
} | |
val ratioX = actualWidth / options.outWidth.toFloat() | |
val ratioY = actualHeight / options.outHeight.toFloat() | |
val middleX = actualWidth / 2.0f | |
val middleY = actualHeight / 2.0f | |
val scaleMatrix = Matrix() | |
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY) | |
if (scaledBitmap == null) { | |
return | |
} | |
val canvas = Canvas(scaledBitmap) | |
canvas.matrix = scaleMatrix | |
canvas.drawBitmap(bmp!!, middleX - bmp.width / 2, middleY - bmp.height / 2, Paint(Paint.FILTER_BITMAP_FLAG)) | |
bmp.recycle() | |
val exif: ExifInterface | |
try { | |
exif = ExifInterface(imagePath) | |
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) | |
} | |
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, | |
scaledBitmap.width, scaledBitmap.height, | |
matrix, true) | |
val bytes = ByteArrayOutputStream() | |
scaledBitmap!!.compress(Bitmap.CompressFormat.JPEG, 95, bytes) | |
val f = File(imagePath) | |
val fo = FileOutputStream(f) | |
fo.write(bytes.toByteArray()) | |
fo.close() | |
} catch (e: Exception) { | |
e.printStackTrace() | |
} | |
} | |
private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { | |
val height = options.outHeight | |
val width = options.outWidth | |
var inSampleSize = 1 | |
if (height > reqHeight || width > reqWidth) { | |
val heightRatio = Math.round(height.toFloat() / reqHeight.toFloat()) | |
val widthRatio = Math.round(width.toFloat() / reqWidth.toFloat()) | |
inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio | |
} | |
val totalPixels = (width * height).toFloat() | |
val totalReqPixelsCap = (reqWidth * reqHeight * 2).toFloat() | |
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) { | |
inSampleSize++ | |
} | |
return inSampleSize | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment