Mercurial > cgi-bin > hgweb.cgi > SimpleResizer
annotate app/src/main/java/com/bartsent/simpleresizer/lib/getScaledInstance.kt @ 6:e8059b166de1
Lanczos works, but is painfully slow.
author | David Barts <n5jrn@me.com> |
---|---|
date | Tue, 16 Feb 2021 17:29:52 -0800 |
parents | |
children | 9374d044a132 b1605be35bcc |
rev | line source |
---|---|
6
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
1 package com.bartsent.simpleresizer.lib |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
2 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
3 import android.graphics.Bitmap |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
4 import android.graphics.Canvas |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
5 import android.graphics.Color |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
6 import android.graphics.Matrix |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
7 import kotlin.math.ceil |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
8 import kotlin.math.floor |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
9 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
10 private data class IndexWeight(var index: Int, var weight: Double) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
11 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
12 fun Bitmap.getScaledInstance(newWidth: Int, newHeight: Int, kernel: ScalingKernel = LanczosKernel): Bitmap { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
13 if (newWidth <= 0) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
14 throw IllegalArgumentException("invalid width: $newWidth") |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
15 if (newHeight <= 0) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
16 throw IllegalArgumentException("invalid height: $newHeight") |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
17 if (width == newWidth && height == newHeight) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
18 return Bitmap.createBitmap(this) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
19 val input = if (config == Bitmap.Config.ARGB_8888) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
20 this |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
21 else { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
22 Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).also { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
23 Canvas(it).drawBitmap(this, Matrix(), null) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
24 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
25 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
26 if (width != newWidth) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
27 if (height != newHeight) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
28 return resizeVertical(resizeHorizontal(input, newWidth, kernel), newHeight, kernel) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
29 else |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
30 return resizeHorizontal(input, newWidth, kernel) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
31 } else { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
32 return resizeVertical(input, newHeight, kernel) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
33 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
34 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
35 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
36 private fun precomputeWeights(dstSize: Int, srcSize: Int, filter: ScalingKernel): Array<Array<IndexWeight>> { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
37 val du = srcSize.toDouble() / dstSize.toDouble() |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
38 val scale = maxOf(1.0, du) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
39 val ru = ceil(scale * filter.size) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
40 val TEMPLATE = arrayOf<IndexWeight>() |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
41 val out = Array<Array<IndexWeight>>(dstSize) { TEMPLATE } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
42 val tmp = ArrayList<IndexWeight>((ru.toInt()+2)*2) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
43 val emax = srcSize - 1 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
44 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
45 for (v in 0 until dstSize) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
46 val fu = (v.toDouble()+0.5)*du - 0.5 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
47 val begin = maxOf(0, ceil(fu - ru).toInt()) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
48 val end = minOf(emax, floor(fu + ru).toInt()) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
49 var sum: Double = 0.0 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
50 for (u in begin..end) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
51 val w = filter.weight((u.toDouble() - fu) / scale) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
52 if (w != 0.0) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
53 sum += w |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
54 tmp.add(IndexWeight(u, w)) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
55 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
56 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
57 if (sum != 0.0) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
58 tmp.forEach { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
59 it.weight /= sum |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
60 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
61 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
62 out[v] = tmp.toArray(TEMPLATE) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
63 tmp.clear() |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
64 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
65 return out |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
66 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
67 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
68 private fun clamp(v: Double): Int = minOf(255, maxOf(0, (v + 0.5).toInt())) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
69 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
70 private fun resample(target: Bitmap, x: Int, y: Int, weights: Array<IndexWeight>, scanLine: IntArray): Unit { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
71 var r = 0.0; var g = 0.0; var b = 0.0; var a = 0.0 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
72 weights.forEach { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
73 val c = scanLine[it.index] |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
74 val aw = Color.alpha(c).toDouble() * it.weight |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
75 r += Color.red(c).toDouble() * aw |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
76 g += Color.green(c).toDouble() * aw |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
77 b += Color.blue(c).toDouble() * aw |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
78 a += aw |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
79 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
80 if (a == 0.0) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
81 return |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
82 target.setPixel(x, y, Color.argb(clamp(a), clamp(r/a), clamp(g/a), clamp(b/a))) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
83 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
84 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
85 private fun resizeHorizontal(image: Bitmap, newWidth: Int, kernel: ScalingKernel): Bitmap { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
86 val dst = Bitmap.createBitmap(newWidth, image.height, Bitmap.Config.ARGB_8888) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
87 val weights = precomputeWeights(newWidth, image.width, kernel) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
88 val scanLine = IntArray(image.width) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
89 for (y in 0 until image.height) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
90 for (x in 0 until image.width) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
91 scanLine[x] = image.getPixel(x, y) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
92 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
93 for (x in weights.indices) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
94 resample(dst, x, y, weights[x], scanLine) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
95 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
96 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
97 return dst |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
98 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
99 |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
100 private fun resizeVertical(image: Bitmap, newHeight: Int, kernel: ScalingKernel): Bitmap { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
101 val dst = Bitmap.createBitmap(image.width, newHeight, Bitmap.Config.ARGB_8888) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
102 val weights = precomputeWeights(newHeight, image.height, kernel) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
103 val scanLine = IntArray(image.height) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
104 for (x in 0 until image.width) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
105 for (y in 0 until image.height) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
106 scanLine[y] = image.getPixel(x, y) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
107 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
108 for (y in weights.indices) { |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
109 resample(dst, x, y, weights[y], scanLine) |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
110 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
111 } |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
112 return dst |
e8059b166de1
Lanczos works, but is painfully slow.
David Barts <n5jrn@me.com>
parents:
diff
changeset
|
113 } |