-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathBlurHashImage.kt
100 lines (84 loc) · 3.34 KB
/
BlurHashImage.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package gg.essential.elementa.components.image
import gg.essential.elementa.UIComponent
import gg.essential.elementa.components.UIImage
import gg.essential.elementa.utils.decodeBlurHash
import gg.essential.elementa.utils.drawTexture
import gg.essential.universal.UGraphics
import gg.essential.universal.UMatrixStack
import gg.essential.universal.utils.ReleasedDynamicTexture
import java.awt.Color
import java.io.File
import java.net.URL
import java.util.concurrent.CompletableFuture
import javax.imageio.ImageIO
import kotlin.math.abs
open class BlurHashImage(private val hash: String) : UIComponent(), ImageProvider {
private lateinit var texture: ReleasedDynamicTexture
private var dimensions = BASE_WIDTH to BASE_HEIGHT
private fun generateTexture(): ReleasedDynamicTexture {
return decodeBlurHash(hash, dimensions.first.toInt(), dimensions.second.toInt())?.let {
UGraphics.getTexture(it)
} ?: run {
// We encountered an issue decoding the blur hash, it's probably invalid.
UGraphics.getEmptyTexture()
}
}
override fun drawImage(matrixStack: UMatrixStack, x: Double, y: Double, width: Double, height: Double, color: Color) {
if (::texture.isInitialized) {
if (width > 0 && height > 0) {
val sizeDifference = abs(dimensions.first * dimensions.second - width * height)
if (sizeDifference > SIZE_THRESHOLD) {
dimensions = width to height
texture = generateTexture()
}
}
} else {
texture = generateTexture()
}
drawTexture(matrixStack, texture, color, x, y, width, height)
}
override fun draw(matrixStack: UMatrixStack) {
beforeDrawCompat(matrixStack)
val x = this.getLeft().toDouble()
val y = this.getTop().toDouble()
val width = this.getWidth().toDouble()
val height = this.getHeight().toDouble()
val color = this.getColor()
if (color.alpha == 0) {
return super.draw(matrixStack)
}
drawImageCompat(matrixStack, x, y, width, height, color)
super.draw(matrixStack)
}
companion object {
const val BASE_WIDTH = 50.0
const val BASE_HEIGHT = 50.0
const val SIZE_THRESHOLD = 2000
/**
* Creates a [UIImage] component that will be backed by a [BlurHashImage] until it is fully
* loaded.
*/
@JvmStatic
fun ofFile(hash: String, file: File): UIImage {
return UIImage(CompletableFuture.supplyAsync { ImageIO.read(file) }, BlurHashImage(hash))
}
/**
* Creates a [UIImage] component that will be backed by a [BlurHashImage] until it is fully
* loaded.
*/
@JvmStatic
fun ofURL(hash: String, url: URL): UIImage {
return UIImage(CompletableFuture.supplyAsync { UIImage.get(url) }, BlurHashImage(hash))
}
/**
* Creates a [UIImage] component that will be backed by a [BlurHashImage] until it is fully
* loaded.
*/
@JvmStatic
fun ofResource(hash: String, path: String): UIImage {
return UIImage(CompletableFuture.supplyAsync {
ImageIO.read(this::class.java.getResourceAsStream(path))
}, BlurHashImage(hash))
}
}
}