From 7856fafb3a8b3bff997174eb83bfbd92893a6653 Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:30:59 -0800
Subject: [PATCH 01/10] Upgrade gradle, dependencies and android SDK
---
Kotlin/build.gradle | 4 ++--
Kotlin/demo/build.gradle | 19 +++++++++++++------
Kotlin/gradle.properties | 11 ++++++++---
.../gradle/wrapper/gradle-wrapper.properties | 4 ++--
Kotlin/lib/build.gradle | 11 ++++++-----
5 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/Kotlin/build.gradle b/Kotlin/build.gradle
index b971d828..6e2b8b1f 100644
--- a/Kotlin/build.gradle
+++ b/Kotlin/build.gradle
@@ -1,7 +1,7 @@
buildscript {
- ext.kotlin_version = '1.3.72'
+ ext.kotlin_version = '1.5.31'
repositories {
google()
@@ -9,7 +9,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
diff --git a/Kotlin/demo/build.gradle b/Kotlin/demo/build.gradle
index 6ccb0378..4db68381 100644
--- a/Kotlin/demo/build.gradle
+++ b/Kotlin/demo/build.gradle
@@ -1,19 +1,26 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply plugin: 'kotlin-android-extensions'
+plugins {
+ id 'com.android.application'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+}
android {
- compileSdkVersion 29
+ compileSdkVersion 31
defaultConfig {
applicationId "com.wolt.blurhash"
minSdkVersion 14
- targetSdkVersion 29
+ targetSdkVersion 31
versionCode 1
versionName "1.0"
}
+ buildFeatures {
+ dataBinding true
+ }
+
+
buildTypes {
release {
minifyEnabled false
@@ -25,5 +32,5 @@ android {
dependencies {
implementation project(path: ':lib')
- implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation "androidx.appcompat:appcompat:1.3.1"
}
diff --git a/Kotlin/gradle.properties b/Kotlin/gradle.properties
index 8de50581..dc6984dd 100644
--- a/Kotlin/gradle.properties
+++ b/Kotlin/gradle.properties
@@ -6,10 +6,15 @@
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
-android.enableJetifier=true
-android.useAndroidX=true
-org.gradle.jvmargs=-Xmx1536m
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+android.enableJetifier=true
\ No newline at end of file
diff --git a/Kotlin/gradle/wrapper/gradle-wrapper.properties b/Kotlin/gradle/wrapper/gradle-wrapper.properties
index 032d0433..db4c5393 100644
--- a/Kotlin/gradle/wrapper/gradle-wrapper.properties
+++ b/Kotlin/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Mon Jul 01 10:02:38 EEST 2019
distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+zipStoreBase=GRADLE_USER_HOME
diff --git a/Kotlin/lib/build.gradle b/Kotlin/lib/build.gradle
index 35dd930e..54db51a6 100644
--- a/Kotlin/lib/build.gradle
+++ b/Kotlin/lib/build.gradle
@@ -1,14 +1,13 @@
apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-android'
android {
- compileSdkVersion 29
+ compileSdkVersion 31
defaultConfig {
minSdkVersion 14
- targetSdkVersion 29
+ targetSdkVersion 31
versionCode 1
versionName "1.0"
@@ -27,6 +26,8 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
- androidTestImplementation 'junit:junit:4.13'
- androidTestImplementation 'androidx.test:runner:1.2.0'
+
+ testImplementation "junit:junit:4.13.2"
+ androidTestImplementation "androidx.test.ext:junit:1.1.3"
+ androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
}
From 7691cb3cf5c7ff432ef181f1a26bad1a658b8d3a Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:31:33 -0800
Subject: [PATCH 02/10] Add tag for use databinding
---
.../src/main/res/layout/activity_main.xml | 98 ++++++++++---------
1 file changed, 51 insertions(+), 47 deletions(-)
diff --git a/Kotlin/demo/src/main/res/layout/activity_main.xml b/Kotlin/demo/src/main/res/layout/activity_main.xml
index 3b22c57d..100d12fa 100644
--- a/Kotlin/demo/src/main/res/layout/activity_main.xml
+++ b/Kotlin/demo/src/main/res/layout/activity_main.xml
@@ -1,53 +1,57 @@
-
+
+
+
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="24dp">
-
+
-
+
-
-
+
+
+
+
+
\ No newline at end of file
From 8a4c27097820b2b6ff7d7f94357f6ee772d90c1d Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:32:55 -0800
Subject: [PATCH 03/10] Add android:exported="true" Flag indicating whether the
given application component is available to other applications. If false, it
can only be accessed by applications with its same user id (which usually
means only by code in its own package). If true, it can be invoked by
external entities.
---
Kotlin/demo/src/main/AndroidManifest.xml | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/Kotlin/demo/src/main/AndroidManifest.xml b/Kotlin/demo/src/main/AndroidManifest.xml
index 3be7349e..759897a6 100644
--- a/Kotlin/demo/src/main/AndroidManifest.xml
+++ b/Kotlin/demo/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
+ package="com.wolt.blurhashapp">
-
+
-
+
-
+
From 34280bac04e1b36c2462fc27f9f1024573d2e1db Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:33:18 -0800
Subject: [PATCH 04/10] Implementing databinding
---
.../java/com/wolt/blurhashapp/MainActivity.kt | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/Kotlin/demo/src/main/java/com/wolt/blurhashapp/MainActivity.kt b/Kotlin/demo/src/main/java/com/wolt/blurhashapp/MainActivity.kt
index 3d48edba..5402ee91 100644
--- a/Kotlin/demo/src/main/java/com/wolt/blurhashapp/MainActivity.kt
+++ b/Kotlin/demo/src/main/java/com/wolt/blurhashapp/MainActivity.kt
@@ -4,21 +4,27 @@ import android.graphics.Bitmap
import android.os.Bundle
import android.os.SystemClock
import androidx.appcompat.app.AppCompatActivity
+import com.wolt.blurhashapp.databinding.ActivityMainBinding
import com.wolt.blurhashkt.BlurHashDecoder
-import kotlinx.android.synthetic.main.activity_main.*
+
class MainActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityMainBinding
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
- tvDecode.setOnClickListener {
+
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.tvDecode.setOnClickListener {
var bitmap: Bitmap? = null
val time = timed {
- bitmap = BlurHashDecoder.decode(etInput.text.toString(), 20, 12)
+ bitmap = BlurHashDecoder.decode(binding.etInput.text.toString(), 20, 12)
}
- ivResult.setImageBitmap(bitmap)
- ivResultTime.text = "Time: $time ms"
+ binding.ivResult.setImageBitmap(bitmap)
+ binding.ivResultTime.text = "Time: $time ms"
}
}
From 61a93aaa67be2e5b3edad303fa924158fb62dcd7 Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:48:33 -0800
Subject: [PATCH 05/10] Change lib name
---
Kotlin/settings.gradle | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Kotlin/settings.gradle b/Kotlin/settings.gradle
index 42198e65..7af76dcc 100644
--- a/Kotlin/settings.gradle
+++ b/Kotlin/settings.gradle
@@ -1 +1 @@
-include ':demo', ':lib'
+include ':demo', ':blurhashkt-lib'
From 70f18714340cac1d1b7b6ada30f52deae5578ee3 Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:49:39 -0800
Subject: [PATCH 06/10] Change name blurhash for blurhashkt to specify this is
a kotlin lib.
---
Kotlin/{lib => blurhashkt-lib}/src/main/AndroidManifest.xml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename Kotlin/{lib => blurhashkt-lib}/src/main/AndroidManifest.xml (100%)
diff --git a/Kotlin/lib/src/main/AndroidManifest.xml b/Kotlin/blurhashkt-lib/src/main/AndroidManifest.xml
similarity index 100%
rename from Kotlin/lib/src/main/AndroidManifest.xml
rename to Kotlin/blurhashkt-lib/src/main/AndroidManifest.xml
From aca4d565b51c1ea1f94aec0df3762845c2607f90 Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:50:08 -0800
Subject: [PATCH 07/10] Add maven dependencies and configuration for jitpack.io
---
Kotlin/blurhashkt-lib/build.gradle | 46 +++++++++++++++++++
.../proguard-rules.pro | 0
.../wolt/blurhashkt/BlurHashDecoderTest.kt | 0
.../com/wolt/blurhashkt/BlurHashDecoder.kt | 0
Kotlin/demo/build.gradle | 6 ++-
Kotlin/lib/build.gradle | 33 -------------
6 files changed, 50 insertions(+), 35 deletions(-)
create mode 100644 Kotlin/blurhashkt-lib/build.gradle
rename Kotlin/{lib => blurhashkt-lib}/proguard-rules.pro (100%)
rename Kotlin/{lib => blurhashkt-lib}/src/androidTest/java/com/wolt/blurhashkt/BlurHashDecoderTest.kt (100%)
rename Kotlin/{lib => blurhashkt-lib}/src/main/java/com/wolt/blurhashkt/BlurHashDecoder.kt (100%)
delete mode 100644 Kotlin/lib/build.gradle
diff --git a/Kotlin/blurhashkt-lib/build.gradle b/Kotlin/blurhashkt-lib/build.gradle
new file mode 100644
index 00000000..43fd9fc5
--- /dev/null
+++ b/Kotlin/blurhashkt-lib/build.gradle
@@ -0,0 +1,46 @@
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android'
+ id 'kotlin-kapt'
+ id 'maven-publish'
+}
+
+android {
+
+ compileSdkVersion 31
+
+ defaultConfig {
+ minSdkVersion 14
+ targetSdkVersion 31
+ versionCode 2
+ versionName "1.0.$versionCode"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+}
+
+dependencies {
+ testImplementation "junit:junit:4.13.2"
+}
+
+
+afterEvaluate {
+ publishing {
+ publications {
+ release(MavenPublication) {
+ from components.release
+ groupId = 'com.github.wolt'
+ artifactId = 'blurhash-lib'
+ version = '1.0.2'
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kotlin/lib/proguard-rules.pro b/Kotlin/blurhashkt-lib/proguard-rules.pro
similarity index 100%
rename from Kotlin/lib/proguard-rules.pro
rename to Kotlin/blurhashkt-lib/proguard-rules.pro
diff --git a/Kotlin/lib/src/androidTest/java/com/wolt/blurhashkt/BlurHashDecoderTest.kt b/Kotlin/blurhashkt-lib/src/androidTest/java/com/wolt/blurhashkt/BlurHashDecoderTest.kt
similarity index 100%
rename from Kotlin/lib/src/androidTest/java/com/wolt/blurhashkt/BlurHashDecoderTest.kt
rename to Kotlin/blurhashkt-lib/src/androidTest/java/com/wolt/blurhashkt/BlurHashDecoderTest.kt
diff --git a/Kotlin/lib/src/main/java/com/wolt/blurhashkt/BlurHashDecoder.kt b/Kotlin/blurhashkt-lib/src/main/java/com/wolt/blurhashkt/BlurHashDecoder.kt
similarity index 100%
rename from Kotlin/lib/src/main/java/com/wolt/blurhashkt/BlurHashDecoder.kt
rename to Kotlin/blurhashkt-lib/src/main/java/com/wolt/blurhashkt/BlurHashDecoder.kt
diff --git a/Kotlin/demo/build.gradle b/Kotlin/demo/build.gradle
index 4db68381..23b1cca2 100644
--- a/Kotlin/demo/build.gradle
+++ b/Kotlin/demo/build.gradle
@@ -2,6 +2,7 @@ plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
+ id 'maven-publish'
}
android {
@@ -12,7 +13,7 @@ android {
applicationId "com.wolt.blurhash"
minSdkVersion 14
targetSdkVersion 31
- versionCode 1
+ versionCode 2
versionName "1.0"
}
@@ -31,6 +32,7 @@ android {
}
dependencies {
- implementation project(path: ':lib')
+ implementation project(path: ':blurhashkt-lib')
implementation "androidx.appcompat:appcompat:1.3.1"
}
+
diff --git a/Kotlin/lib/build.gradle b/Kotlin/lib/build.gradle
deleted file mode 100644
index 54db51a6..00000000
--- a/Kotlin/lib/build.gradle
+++ /dev/null
@@ -1,33 +0,0 @@
-apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android'
-
-android {
-
- compileSdkVersion 31
-
- defaultConfig {
- minSdkVersion 14
- targetSdkVersion 31
- versionCode 1
- versionName "1.0"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- }
-
-}
-
-dependencies {
- implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-
- testImplementation "junit:junit:4.13.2"
- androidTestImplementation "androidx.test.ext:junit:1.1.3"
- androidTestImplementation "androidx.test.espresso:espresso-core:3.4.0"
-}
From 2a9a72655f7004e85b5eb3750a0e27881c331389 Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:52:15 -0800
Subject: [PATCH 08/10] Add jitpack.yml file configuration for jitpack.io issue
Error build with gradle 7.0.2
https://github.com/jitpack/jitpack.io/issues/4824#
---
Kotlin/jitpack.yml | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 Kotlin/jitpack.yml
diff --git a/Kotlin/jitpack.yml b/Kotlin/jitpack.yml
new file mode 100644
index 00000000..1bfc0d7d
--- /dev/null
+++ b/Kotlin/jitpack.yml
@@ -0,0 +1,4 @@
+jdk:
+ - openjdk11
+before_install:
+ - ./scripts/prepareJitpackEnvironment.sh
\ No newline at end of file
From 41e8e849077b1d2befe99970daecb58ab1bac8ff Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 06:56:43 -0800
Subject: [PATCH 09/10] FIXED Test dependencies.
---
Kotlin/blurhashkt-lib/build.gradle | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Kotlin/blurhashkt-lib/build.gradle b/Kotlin/blurhashkt-lib/build.gradle
index 43fd9fc5..a29454aa 100644
--- a/Kotlin/blurhashkt-lib/build.gradle
+++ b/Kotlin/blurhashkt-lib/build.gradle
@@ -20,7 +20,7 @@ android {
buildTypes {
release {
- minifyEnabled false
+ minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
@@ -28,7 +28,7 @@ android {
}
dependencies {
- testImplementation "junit:junit:4.13.2"
+ androidTestImplementation "junit:junit:4.13.2"
}
From df95c2d459fb0ee4d2494fa206ce27b97e83fe7a Mon Sep 17 00:00:00 2001
From: Orlando Novas Rodriguez
<38017009+orlando-dev-code@users.noreply.github.com>
Date: Tue, 9 Nov 2021 07:22:38 -0800
Subject: [PATCH 10/10] Add BlurHashEncoder.kt from branch
blur-hash-encoder-kotlin untested
---
.../com/wolt/blurhashkt/BlurHashEncoder.kt | 169 ++++++++++++++++++
1 file changed, 169 insertions(+)
create mode 100644 Kotlin/blurhashkt-lib/src/main/java/com/wolt/blurhashkt/BlurHashEncoder.kt
diff --git a/Kotlin/blurhashkt-lib/src/main/java/com/wolt/blurhashkt/BlurHashEncoder.kt b/Kotlin/blurhashkt-lib/src/main/java/com/wolt/blurhashkt/BlurHashEncoder.kt
new file mode 100644
index 00000000..5772e7ff
--- /dev/null
+++ b/Kotlin/blurhashkt-lib/src/main/java/com/wolt/blurhashkt/BlurHashEncoder.kt
@@ -0,0 +1,169 @@
+package com.wolt.blurhashkt
+
+import android.graphics.Bitmap
+import java.lang.Math.*
+import java.nio.IntBuffer
+import kotlin.math.PI
+import kotlin.math.pow
+
+object BlurHashEncoder {
+
+ fun blurHash(bitmap: Bitmap, components: Pair): String? {
+ if (components.first !in 1..9 || components.second !in 1..9) {
+ return null
+ }
+
+
+ val width = bitmap.width
+ val height = bitmap.height
+ val bytesPerRow = bitmap.rowBytes
+ var pixels: IntArray? = null
+ bitmap.getPixels(pixels, 0, bitmap.width, 0, 0, bitmap.width, bitmap.height)
+
+ if (pixels == null) {
+ return null
+ }
+
+ val factors: MutableList> = mutableListOf()
+ for (y in 0 until components.second) {
+ for (x in 0 until components.first) {
+ val normalisation: Float = if (x == 0 && y == 0) 1f else 2f
+ val factor =
+ multiplyBasisFunction(pixels, width, height, bytesPerRow, 4, 0) { a, b ->
+ (normalisation * kotlin.math.cos(PI * x * a / width) * kotlin.math.cos(PI * y * b / height)).toFloat()
+ }
+ factors.add(factor)
+ }
+ }
+
+ val dc = factors.removeAt(0)
+ val ac = factors
+
+ var hash = ""
+
+ val sizeFlag = (components.first - 1) + (components.second - 1) * 9
+ hash += sizeFlag.encode83(1)
+
+ val maximumValue: Float
+ if (ac.size > 0) {
+ val actualMaximumValue = ac.map { it.maxOrNull() }.maxByOrNull { it!! }!!
+ val quantisedMaximumValue =
+ 0.0.coerceAtLeast(82.0.coerceAtMost(kotlin.math.floor(actualMaximumValue * 166 - 0.5)))
+ .toInt()
+ maximumValue = (quantisedMaximumValue + 1) / 166.0f
+ hash += quantisedMaximumValue.encode83(1)
+ } else {
+ maximumValue = 1f
+ hash += 0.encode83(1)
+ }
+
+ hash += encodeDC(dc).encode83(4)
+
+ for (factor in ac) {
+ hash += encodeAC(factor, maximumValue).encode83(2)
+ }
+
+ return hash
+ }
+
+ private fun multiplyBasisFunction(
+ pixels: IntArray,
+ width: Int,
+ height: Int,
+ bytesPerRow: Int,
+ bytesPerPixel: Int,
+ pixelOffset: Int,
+ basisFunction: (Float, Float) -> Float
+ ): Array {
+ var r = 0f
+ var g = 0f
+ var b = 0f
+
+ val buffer = IntBuffer.wrap(pixels, pixels.size, height * bytesPerRow)
+
+ for (x in 0 until width) {
+ for (y in 0 until height) {
+ val basis = basisFunction(x.toFloat(), y.toFloat())
+ r += basis * sRgbToLinear(buffer[bytesPerPixel * x + pixelOffset + 0 + y * bytesPerRow])
+ g += basis * sRgbToLinear(buffer[bytesPerPixel * x + pixelOffset + 1 + y * bytesPerRow])
+ b += basis * sRgbToLinear(buffer[bytesPerPixel * x + pixelOffset + 2 + y * bytesPerRow])
+ }
+ }
+
+ val scale = 1 / (width * height).toFloat()
+
+ return arrayOf(r * scale, g * scale, b * scale)
+ }
+
+
+ private val encodeCharacters: List =
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { it.toString() }
+
+ private fun encodeDC(value: Array): Int {
+ val roundedR = linearToSRgb(value[0])
+ val roundedG = linearToSRgb(value[1])
+ val roundedB = linearToSRgb(value[2])
+ return (roundedR shl 16) + (roundedG shl 8) + roundedB
+ }
+
+ private fun encodeAC(value: Array, maximumValue: Float): Int {
+ 0.0.coerceAtLeast(
+ 18.0.coerceAtMost(
+ kotlin.math.floor(
+ (value[0] / maximumValue.toDouble()).pow(0.5) * 9 + 9.5
+ )
+ )
+ )
+ val quantR = 0.0.coerceAtLeast(
+ 18.0.coerceAtMost(
+ kotlin.math.floor(
+ (value[0] / maximumValue.toDouble()).pow(0.5) * 9 + 9.5
+ )
+ )
+ ).toInt()
+ val quantG = 0.0.coerceAtLeast(
+ 18.0.coerceAtMost(
+ kotlin.math.floor(
+ (value[1] / maximumValue.toDouble()).pow(0.5) * 9 + 9.5
+ )
+ )
+ ).toInt()
+ val quantB = 0.0.coerceAtLeast(
+ 18.0.coerceAtMost(
+ kotlin.math.floor(
+ (value[2] / maximumValue.toDouble()).pow(0.5) * 9 + 9.5
+ )
+ )
+ ).toInt()
+
+ return quantR * 19 * 19 + quantG * 19 + quantB
+ }
+
+ private fun sRgbToLinear(value: Int): Float {
+ val v = value / 255f
+ return if (v <= 0.04045) (v / 12.92f) else (pow((v + 0.055) / 1.055, 2.4).toFloat())
+ }
+
+ private fun linearToSRgb(value: Float): Int {
+ val v = 0f.coerceAtLeast(1f.coerceAtMost(value))
+ return if (v <= 0.0031308f) {
+ (v * 12.92f * 255 + 0.5f).toInt()
+ } else {
+ ((1.055f * v.toDouble().pow(1 / 2.4) - 0.055f) * 255 + 0.5f).toInt()
+ }
+ }
+
+
+ private fun Int.encode83(length: Int): String {
+ var result = ""
+ for (i in 1..length) {
+ val digit = (this / myPow(83, (length - i))) % 83
+ result += encodeCharacters[digit]
+ }
+ return result
+ }
+
+ private fun myPow(base: Int, exponent: Int): Int {
+ return (0 until exponent).fold(1) { acc, _ -> acc * base }
+ }
+}