Basically, I'm reading images from user's storage for processing, and while reading images, I'm calculating inSampleSize for saving some memory, here's my code:
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
}
But, I'm getting ArithmeticException: Divide by zero inside while loop condition:
halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth
I don't think inSampleSize will ever be zero since it's starting from 1 and multiplied by 2 in each iteration. Can anyone help me what's going on here?
It's only crashing for some users (got around 13 crashes till now) and I'm not able to reproduce it.
Edit, added crash log:
Non-fatal Exception: java.lang.ArithmeticException: divide by zero
at myapp.myapp.myapp.utils.UtilsKt.calculateInSampleSize(Utils.kt:108)
at myapp.myapp.myapp.utils.UtilsKt$resizeImageWithPixel$2.invokeSuspend(Utils.kt:464)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
CodePudding user response:
I don't think inSampleSize will ever be zero since it's starting from 1 and multiplied by 2 in each iteration. Can anyone help me what's going on here?
That's where you're wrong I think. You can definitely get zero by multiplying by 2 enough times if you make your integer overflow:
var inSampleSize = 1
while (inSampleSize != 0) {
println("inSampleSize = $inSampleSize")
inSampleSize *= 2
}
println("inSampleSize is 0 now!")
See for yourself here: https://pl.kotl.in/uZHs7YQCW
inSampleSize = 1
inSampleSize = 2
inSampleSize = 4
inSampleSize = 8
inSampleSize = 16
inSampleSize = 32
inSampleSize = 64
inSampleSize = 128
inSampleSize = 256
inSampleSize = 512
inSampleSize = 1024
inSampleSize = 2048
inSampleSize = 4096
inSampleSize = 8192
inSampleSize = 16384
inSampleSize = 32768
inSampleSize = 65536
inSampleSize = 131072
inSampleSize = 262144
inSampleSize = 524288
inSampleSize = 1048576
inSampleSize = 2097152
inSampleSize = 4194304
inSampleSize = 8388608
inSampleSize = 16777216
inSampleSize = 33554432
inSampleSize = 67108864
inSampleSize = 134217728
inSampleSize = 268435456
inSampleSize = 536870912
inSampleSize = 1073741824
inSampleSize = -2147483648
inSampleSize is 0 now!