Mercurial > cgi-bin > hgweb.cgi > SimpleResizer
diff app/src/main/java/com/bartsent/simpleresizer/lib/getScaledInstance.kt @ 13:b1605be35bcc memo.oo
Dumping Bitmap yields 2x improvement!
author | David Barts <n5jrn@me.com> |
---|---|
date | Thu, 18 Feb 2021 14:15:26 -0800 |
parents | e8059b166de1 |
children | 20da616dcda0 |
line wrap: on
line diff
--- a/app/src/main/java/com/bartsent/simpleresizer/lib/getScaledInstance.kt Wed Feb 17 14:29:45 2021 -0800 +++ b/app/src/main/java/com/bartsent/simpleresizer/lib/getScaledInstance.kt Thu Feb 18 14:15:26 2021 -0800 @@ -9,105 +9,18 @@ private data class IndexWeight(var index: Int, var weight: Double) -fun Bitmap.getScaledInstance(newWidth: Int, newHeight: Int, kernel: ScalingKernel = LanczosKernel): Bitmap { +fun Bitmap.getScaledInstance(newWidth: Int, newHeight: Int): Bitmap { if (newWidth <= 0) throw IllegalArgumentException("invalid width: $newWidth") if (newHeight <= 0) throw IllegalArgumentException("invalid height: $newHeight") if (width == newWidth && height == newHeight) return Bitmap.createBitmap(this) - val input = if (config == Bitmap.Config.ARGB_8888) - this - else { - Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).also { - Canvas(it).drawBitmap(this, Matrix(), null) + return if (width != newWidth) { + Resizer.fromBitmap(this).horizontal(newWidth).let { + if (height == newHeight) it else it.vertical(newHeight) } - } - if (width != newWidth) { - if (height != newHeight) - return resizeVertical(resizeHorizontal(input, newWidth, kernel), newHeight, kernel) - else - return resizeHorizontal(input, newWidth, kernel) } else { - return resizeVertical(input, newHeight, kernel) - } -} - -private fun precomputeWeights(dstSize: Int, srcSize: Int, filter: ScalingKernel): Array<Array<IndexWeight>> { - val du = srcSize.toDouble() / dstSize.toDouble() - val scale = maxOf(1.0, du) - val ru = ceil(scale * filter.size) - val TEMPLATE = arrayOf<IndexWeight>() - val out = Array<Array<IndexWeight>>(dstSize) { TEMPLATE } - val tmp = ArrayList<IndexWeight>((ru.toInt()+2)*2) - val emax = srcSize - 1 - - for (v in 0 until dstSize) { - val fu = (v.toDouble()+0.5)*du - 0.5 - val begin = maxOf(0, ceil(fu - ru).toInt()) - val end = minOf(emax, floor(fu + ru).toInt()) - var sum: Double = 0.0 - for (u in begin..end) { - val w = filter.weight((u.toDouble() - fu) / scale) - if (w != 0.0) { - sum += w - tmp.add(IndexWeight(u, w)) - } - } - if (sum != 0.0) { - tmp.forEach { - it.weight /= sum - } - } - out[v] = tmp.toArray(TEMPLATE) - tmp.clear() - } - return out + Resizer.fromBitmap(this).vertical(newHeight) + } .toBitmap() } - -private fun clamp(v: Double): Int = minOf(255, maxOf(0, (v + 0.5).toInt())) - -private fun resample(target: Bitmap, x: Int, y: Int, weights: Array<IndexWeight>, scanLine: IntArray): Unit { - var r = 0.0; var g = 0.0; var b = 0.0; var a = 0.0 - weights.forEach { - val c = scanLine[it.index] - val aw = Color.alpha(c).toDouble() * it.weight - r += Color.red(c).toDouble() * aw - g += Color.green(c).toDouble() * aw - b += Color.blue(c).toDouble() * aw - a += aw - } - if (a == 0.0) - return - target.setPixel(x, y, Color.argb(clamp(a), clamp(r/a), clamp(g/a), clamp(b/a))) -} - -private fun resizeHorizontal(image: Bitmap, newWidth: Int, kernel: ScalingKernel): Bitmap { - val dst = Bitmap.createBitmap(newWidth, image.height, Bitmap.Config.ARGB_8888) - val weights = precomputeWeights(newWidth, image.width, kernel) - val scanLine = IntArray(image.width) - for (y in 0 until image.height) { - for (x in 0 until image.width) { - scanLine[x] = image.getPixel(x, y) - } - for (x in weights.indices) { - resample(dst, x, y, weights[x], scanLine) - } - } - return dst -} - -private fun resizeVertical(image: Bitmap, newHeight: Int, kernel: ScalingKernel): Bitmap { - val dst = Bitmap.createBitmap(image.width, newHeight, Bitmap.Config.ARGB_8888) - val weights = precomputeWeights(newHeight, image.height, kernel) - val scanLine = IntArray(image.height) - for (x in 0 until image.width) { - for (y in 0 until image.height) { - scanLine[y] = image.getPixel(x, y) - } - for (y in weights.indices) { - resample(dst, x, y, weights[y], scanLine) - } - } - return dst -}