Summary
ImageEncoder.encodeToJpeg (kmp/src/wasmJsMain/kotlin/dev/stapler/stelekit/ui/annotate/ImageEncoder.wasmJs.kt) returns ByteArray(0) on WASM. Any attempt to export an annotated image on the web target silently produces a 0-byte file.
Root cause
There is no straightforward way to encode a Compose ImageBitmap to JPEG bytes on WASM/browser without one of:
- Skia JPEG encoder — not exposed to user code in Compose Multiplatform WASM builds.
- Pixel iteration + Canvas 2D —
toPixelMap() works on WASM, but writing O(width×height) pixels to a Uint8ClampedArray via JS interop is too slow for real images.
- A JS JPEG encoder library — not currently on the classpath.
Proposed fix
Use bitmap.toPixelMap() + a hidden <canvas> element + canvas.toDataURL('image/jpeg', quality) + base64 decode to ByteArray. The main concern is performance — a 3000×2000 image requires 6M JS interop calls for pixel setting. Batching via Uint8Array written in a single JS call (passing pixel data as a flat array) would make this practical.
Alternatively, add a small JS JPEG encoder (e.g. jpeg-js) as a bundled dependency.
Affected files
kmp/src/wasmJsMain/kotlin/dev/stapler/stelekit/ui/annotate/ImageEncoder.wasmJs.kt
kmp/src/commonMain/kotlin/dev/stapler/stelekit/ui/annotate/AnnotationExporter.kt
Labels
bug, platform: web, needs-design
Summary
ImageEncoder.encodeToJpeg(kmp/src/wasmJsMain/kotlin/dev/stapler/stelekit/ui/annotate/ImageEncoder.wasmJs.kt) returnsByteArray(0)on WASM. Any attempt to export an annotated image on the web target silently produces a 0-byte file.Root cause
There is no straightforward way to encode a Compose
ImageBitmapto JPEG bytes on WASM/browser without one of:toPixelMap()works on WASM, but writing O(width×height) pixels to aUint8ClampedArrayvia JS interop is too slow for real images.Proposed fix
Use
bitmap.toPixelMap()+ a hidden<canvas>element +canvas.toDataURL('image/jpeg', quality)+ base64 decode toByteArray. The main concern is performance — a 3000×2000 image requires 6M JS interop calls for pixel setting. Batching viaUint8Arraywritten in a single JS call (passing pixel data as a flat array) would make this practical.Alternatively, add a small JS JPEG encoder (e.g. jpeg-js) as a bundled dependency.
Affected files
kmp/src/wasmJsMain/kotlin/dev/stapler/stelekit/ui/annotate/ImageEncoder.wasmJs.ktkmp/src/commonMain/kotlin/dev/stapler/stelekit/ui/annotate/AnnotationExporter.ktLabels
bug,platform: web,needs-design