Skip to content

Commit

Permalink
WASM Zlib support (#47)
Browse files Browse the repository at this point in the history
Use pako library for WASM zlib to fully support PNG
  • Loading branch information
StefanOltmann authored Dec 15, 2023
1 parent 49a94e8 commit 3b20dcb
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 5 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ of Ashampoo Photos, which, in turn, is driven by user community feedback.
## Installation

```
implementation("com.ashampoo:kim:0.8")
implementation("com.ashampoo:kim:0.8.1")
```

## Sample usages
Expand Down Expand Up @@ -139,7 +139,6 @@ val newBytes = Kim.updateThumbnail(
## Limitations

* Inability to update EXIF, IPTC and XMP in JPG files simultaneously.
* There is no implementation of WebAssembly (WASM) for ZLib compression, which means that PNG files utilizing this compression cannot be processed.

## Contributions

Expand Down
20 changes: 19 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension

plugins {
kotlin("multiplatform") version "1.9.21"
Expand Down Expand Up @@ -146,7 +147,11 @@ kotlin {
}

@OptIn(ExperimentalWasmDsl::class)
wasmJs()
wasmJs {
// All tests reading from files fail, because kotlinx-io
// has no Path support for WASM (yet?).
// nodejs()
}

// Note: Missing support in kotlinx-datetime
// @OptIn(ExperimentalWasmDsl::class)
Expand Down Expand Up @@ -278,6 +283,10 @@ kotlin {

wasmJsMain.dependsOn(this)
// wasmWasiMain.dependsOn(this)

dependencies {
implementation(npm("pako", "2.1.0"))
}
}
}

Expand Down Expand Up @@ -450,3 +459,12 @@ publishing {
}
}
// endregion

//rootProject.the<NodeJsRootExtension>().apply {
// nodeVersion = "21.0.0-v8-canary202309143a48826a08"
// nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary"
//}
//
//tasks.withType<org.jetbrains.kotlin.gradle.targets.js.npm.tasks.KotlinNpmInstallTask>().configureEach {
// args.add("--ignore-engines")
//}
23 changes: 23 additions & 0 deletions kotlin-js-store/yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


"@js-joda/[email protected]":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273"
integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==

format-util@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271"
integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg==

[email protected]:
version "2.1.0"
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==

[email protected]:
version "5.0.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==
27 changes: 25 additions & 2 deletions src/wasmMain/kotlin/com/ashampoo/kim/common/ZLib.wasm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,31 @@
*/
package com.ashampoo.kim.common

import org.khronos.webgl.Uint8Array
import org.khronos.webgl.get
import org.khronos.webgl.set

actual fun compress(input: String): ByteArray =
TODO("NOT implemented!") // FIXME
Pako.deflate(input).toByteArray()

actual fun decompress(byteArray: ByteArray): String =
TODO("NOT implemented!") // FIXME
Pako.inflate(byteArray.toUint8Array(), toStringOptions)

private val toStringOptions: JsAny = js("({to: 'string'})")

private fun Uint8Array.toByteArray(): ByteArray =
ByteArray(length) { this[it] }

private fun ByteArray.toUint8Array(): Uint8Array {
val result = Uint8Array(size)
forEachIndexed { index, byte ->
result[index] = byte
}
return result
}

@JsModule("pako")
private external object Pako {
fun deflate(data: String): Uint8Array
fun inflate(data: Uint8Array, options: JsAny): String
}

0 comments on commit 3b20dcb

Please sign in to comment.