@wasmedia/wimagemagick 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/CHANGELOG.md +230 -0
  2. package/LICENSE +199 -0
  3. package/README.md +75 -0
  4. package/dist/api.d.ts +68 -0
  5. package/dist/api.d.ts.map +1 -0
  6. package/dist/api.js +218 -0
  7. package/dist/api.js.map +1 -0
  8. package/dist/cli.d.ts +71 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +273 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/filesystem.d.ts +37 -0
  13. package/dist/filesystem.d.ts.map +1 -0
  14. package/dist/filesystem.js +141 -0
  15. package/dist/filesystem.js.map +1 -0
  16. package/dist/image.d.ts +125 -0
  17. package/dist/image.d.ts.map +1 -0
  18. package/dist/image.js +426 -0
  19. package/dist/image.js.map +1 -0
  20. package/dist/index.d.ts +30 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +34 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/licenses/README.txt +11 -0
  25. package/dist/licenses/aom-LICENSE.txt +28 -0
  26. package/dist/licenses/brotli-LICENSE.txt +21 -0
  27. package/dist/licenses/de265-LICENSE.txt +873 -0
  28. package/dist/licenses/ffi-LICENSE.txt +23 -0
  29. package/dist/licenses/freetype-LICENSE.txt +171 -0
  30. package/dist/licenses/glib-LICENSE.txt +504 -0
  31. package/dist/licenses/heif-LICENSE.txt +873 -0
  32. package/dist/licenses/highway-LICENSE.txt +203 -0
  33. package/dist/licenses/imagemagick-LICENSE.txt +106 -0
  34. package/dist/licenses/imagemagick-NOTICE.txt +240 -0
  35. package/dist/licenses/jpeg-turbo-LICENSE.txt +137 -0
  36. package/dist/licenses/jpeg-xl-LICENSE.txt +29 -0
  37. package/dist/licenses/lcms-LICENSE.txt +24 -0
  38. package/dist/licenses/libraw-COPYRIGHT.txt +27 -0
  39. package/dist/licenses/libraw-LICENSE.CDDL.txt +340 -0
  40. package/dist/licenses/libraw-LICENSE.LGPL.txt +458 -0
  41. package/dist/licenses/lqr-LICENSE.txt +167 -0
  42. package/dist/licenses/openjpeg-LICENSE.txt +41 -0
  43. package/dist/licenses/png-LICENSE.txt +136 -0
  44. package/dist/licenses/tiff-LICENSE.txt +51 -0
  45. package/dist/licenses/webp-LICENSE.txt +31 -0
  46. package/dist/licenses/xml-LICENSE.txt +26 -0
  47. package/dist/licenses/zlib-LICENSE.txt +24 -0
  48. package/dist/loader.d.ts +25 -0
  49. package/dist/loader.d.ts.map +1 -0
  50. package/dist/loader.js +50 -0
  51. package/dist/loader.js.map +1 -0
  52. package/dist/raw.d.ts +39 -0
  53. package/dist/raw.d.ts.map +1 -0
  54. package/dist/raw.js +151 -0
  55. package/dist/raw.js.map +1 -0
  56. package/dist/types.d.ts +164 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +94 -0
  59. package/dist/types.js.map +1 -0
  60. package/dist/wimagemagick.js +15 -0
  61. package/dist/wimagemagick.wasm +0 -0
  62. package/dist/worker-handler.d.ts +46 -0
  63. package/dist/worker-handler.d.ts.map +1 -0
  64. package/dist/worker-handler.js +165 -0
  65. package/dist/worker-handler.js.map +1 -0
  66. package/dist/worker.d.ts +14 -0
  67. package/dist/worker.d.ts.map +1 -0
  68. package/dist/worker.js +19 -0
  69. package/dist/worker.js.map +1 -0
  70. package/package.json +51 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,230 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-10-03
11
+
12
+ First release published to npm, as `@wasmedia/wimagemagick`.
13
+
14
+ ### Added
15
+ - npm package: `@wasmedia/wimagemagick`, published by the CI pipeline when a
16
+ `vX.Y.Z` tag is pushed, from the same build the tests ran on and with an npm
17
+ provenance statement. The package (and the Pages playground) now ship
18
+ `dist/licenses/`: the licence of ImageMagick and of every library linked
19
+ into the `.wasm`, several of which are LGPL and linked statically.
20
+ - Samsung SRW and Kodak KDC files are recognised on their own, like ARW and
21
+ DCR. Without a format hint both used to fail with
22
+ `missing required "ImageLength"`. Pentax PEF is now the only common raw that
23
+ still needs the hint (or a `.pef` filename).
24
+ - `detectRawFormat()` also names Fujifilm RAF, Panasonic RW2, Olympus ORF
25
+ (`IIRO`), Canon CRW, Minolta MRW and older Leica/Panasonic RAW files. These
26
+ already decoded without a hint, because ImageMagick recognises them itself,
27
+ but `detectRawFormat()` returned `undefined` for them, so it could not be
28
+ used to ask whether a file is a raw.
29
+ - Sony ARW and Kodak DCR files are recognised on their own by `identify()`,
30
+ `WMagickImage.fromBuffer()`, `fromBlob()` and `detectRawFormat()`, like NEF
31
+ and CR2 already were. Without a format hint they used to fail with
32
+ `missing required "ImageLength"` or `CompressNotSupported`. Checked against
33
+ ARWs from three Sony bodies (2010–2016) and a Kodak DCS Pro SLR/n.
34
+ - A `process` message for the Web Worker: decode once, run a list of
35
+ `WMagickImage` operations in order, encode once, and get back the bytes plus
36
+ the image's size and format before and after. The convert/resize/identify
37
+ messages each did one fixed thing. The protocol is exported as
38
+ `createWorkerHandler()` and is now covered by tests.
39
+ - `WMagickImage.fit(maxWidth, maxHeight)`: shrink to fit a box, keeping the
40
+ aspect ratio and never enlarging, like `-resize WxH>`.
41
+ - `identify()`, `WMagickImage.fromBuffer()` and `fromBlob()` recognise Canon
42
+ CR2/CR3, Nikon NEF, DNG, Hasselblad 3FR and Phase One IIQ files on their own
43
+ and read them with LibRaw — no format hint needed. Without one these files
44
+ used to come back as the embedded preview (NEF, 3FR, IIQ: a 160x120 to
45
+ 640x480 thumbnail with exit code 0), the undemosaiced mosaic (DNG), or an
46
+ error (CR2, CR3). The detection is exported as `detectRawFormat()`. An
47
+ explicit format still wins, and other raw formats still need one.
48
+ - Two more kinds of DNG decode: floating-point Deflate DNGs, the layout HDR
49
+ merges produce, and lossy JPEG DNGs, Lightroom's "lossy compressed" option.
50
+ LibRaw is now built with zlib and libjpeg; previously the first failed with
51
+ "Corrupted data" and the second was rejected as an unsupported format.
52
+ - RAW camera files can now actually be decoded through the public API. LibRaw
53
+ was linked all along, but ImageMagick registers the raw coders as
54
+ "explicit format" coders and never picks them from a file's magic bytes —
55
+ a DNG, CR2, NEF or ARW is a TIFF at that level, so the TIFF coder claimed
56
+ every raw and returned the undemosaiced sensor mosaic instead of a
57
+ photograph, with no error. The format can now be named:
58
+ `identify(module, bytes, { format: 'CR2' })`,
59
+ `WMagickImage.fromBuffer(bytes, 'DNG')`,
60
+ `Image.fromBlob(file, 'DNG')`, or an explicit `dng:` prefix in a command.
61
+ A filename that already ends in a raw extension (`shot.cr2`) worked before
62
+ and still does.
63
+ - Format coverage tests (`tests/integration/formats.test.ts`, 30 cases). Every
64
+ decode case reads a file produced outside this build — `sips`, `cwebp`,
65
+ `avifenc`, `cjxl`, and a Bayer-mosaic DNG generated by
66
+ `tests/fixtures/make-bayer-dng.py` and verified with LibRaw's own
67
+ `raw-identify`/`dcraw_emu` — and every encode case checks the bytes against
68
+ the container's signature before ImageMagick reads them back. Removing a
69
+ delegate now fails a named test instead of quietly shrinking the format set.
70
+ - The native build fails loudly when a delegate goes missing.
71
+ `native/settings/common.sh` passes an explicit `--with-<delegate>` flag for
72
+ everything the build promises and lists the set in `REQUIRED_DELEGATES`;
73
+ `build-imagemagick.sh` checks the generated `magick-baseconfig.h` after
74
+ configure and stops the build if one is absent. configure discovers
75
+ delegates through pkg-config and otherwise carries on without them.
76
+ - Test suite (`npm test`): unit tests for the pure helpers plus
77
+ integration tests that drive the real WASM build through the CLI interface,
78
+ `WMagickImage`, the MEMFS helpers, the MagickWand bindings and the loader.
79
+ `npm run typecheck` type-checks `src/` and `tests/` together, since vitest
80
+ does not.
81
+ - `npm run playground` (`scripts/playground.mjs`) — local static server that
82
+ serves `examples/browser/index.html` with `dist/` mounted alongside, so the
83
+ WASM playground works without a separate web server.
84
+ - `LICENSE`, `CHANGELOG.md`, `CONTRIBUTING.md`.
85
+ - README badges (pipeline status, latest release, license, ImageMagick
86
+ version, WebAssembly+SIMD).
87
+ - Playground UI improvements:
88
+ - JXL and JP2 added to the output format dropdown.
89
+ - Output panel now shows input → output size delta with percent change
90
+ (green if smaller, red if larger).
91
+ - Resize controls gain an aspect-ratio lock and `Fit 2048 / 1024 / 512 /
92
+ Clear` presets driven by the loaded image's intrinsic dimensions.
93
+ - View toggle between side-by-side preview and a draggable compare
94
+ slider that overlays output on top of input.
95
+ - CLI mode gains a persistent localStorage history (50 commands, ↑/↓
96
+ navigation) and an `Examples ▾` dropdown with six canned commands.
97
+ - File picker accepts RAW (CR2/CR3/NEF/ARW/RAF/ORF/DNG/RW2/PEF), JXL,
98
+ and JP2 extensions.
99
+
100
+ ### Changed
101
+ - The package is renamed from `wimagemagick` to `@wasmedia/wimagemagick`,
102
+ matching the other wasmedia packages. Imports change accordingly
103
+ (`@wasmedia/wimagemagick`, `@wasmedia/wimagemagick/worker`).
104
+ - The browser playground decodes and encodes in the library's Web Worker
105
+ instead of on the page. A large file no longer freezes the page while
106
+ ImageMagick works: loading a 24 MP TIFF used to block it for about two
107
+ seconds, and now the longest stall is under 20 ms.
108
+ - Documentation now matches the build. The delegate list claimed harfbuzz,
109
+ which has never been in the prebuilt dependency bundle, and listed openjph
110
+ as "JPEG XL (via JPEG Pleno)" — openjph is High-Throughput JPEG 2000, and
111
+ ImageMagick has no HTJ2K coder at the pinned commit, so it was never used.
112
+ `docs/building.md` now carries the delegate list the build actually reports,
113
+ says which libraries are deliberately absent and why, and documents two
114
+ behaviours that had been catching people out: a missing encoder (HEIC, EXR,
115
+ any raw format) is a warning rather than an error, so ImageMagick writes the
116
+ input's format under the requested name and returns 0; and `label:`,
117
+ `caption:` and `-annotate` need the caller to supply a font, because
118
+ fontconfig is absent and no fonts ship inside the WASM filesystem.
119
+ - `libopenjph` is no longer linked. Nothing referenced it, so the binary is
120
+ unchanged; the link list now reflects that JPEG 2000 comes from openjpeg and
121
+ JPEG XL from libjxl.
122
+ - The browser playground reads RAW files properly. It advertised CR2/NEF/ARW/DNG
123
+ in the file picker but read every drop as a plain buffer, so a raw came back
124
+ as the TIFF-container mosaic; it now derives the format from the file
125
+ extension.
126
+ - CI runs the tests for real: the `test` job no longer carries
127
+ `allow_failure: true` (it had been failing on every pipeline with "No test
128
+ files found") and now type-checks before running the suite.
129
+ - CI validates merge requests. Jobs without `rules:` defaulted to
130
+ `only: [branches, tags]`, so a merge request pipeline ran nothing but
131
+ `build-image` and an MR could merge green without the WASM or TypeScript ever
132
+ being compiled. Every job now runs on both merge request and branch
133
+ pipelines, and a `workflow:` block keeps a branch with an open MR from
134
+ building twice.
135
+ - CI pipeline runs on GitLab SaaS instance (shared) runners:
136
+ `default: tags: [saas-linux-small-amd64]`, with `build-image` and
137
+ `build-wasm` overriding to `saas-linux-medium-amd64` for the extra RAM
138
+ needed by Docker-in-Docker and WASM linking. No self-hosted runner is
139
+ required to build the project.
140
+ - `build-image` now sets `DOCKER_HOST`, `DOCKER_TLS_VERIFY`, and
141
+ `DOCKER_CERT_PATH` so the docker client connects to the `dind` service
142
+ over TLS on port 2376 (matching `DOCKER_TLS_CERTDIR`).
143
+ - Build pipeline consolidated to a single output: single-threaded + SIMD.
144
+ Previously the build attempted to produce both a single-threaded and a
145
+ threaded variant; the threaded path was unbuildable against the prebuilt
146
+ delegate bundle (libheif/libde265/libaom and OpenEXR objects lack the
147
+ atomics feature flag, blocking `wasm-ld --shared-memory`).
148
+ - `dist/` layout is now flat (`dist/wimagemagick.{js,wasm}`); the per-variant
149
+ subdirectories (`dist/single/`, `dist/threaded/`) are gone.
150
+ - `native/settings/single.sh` renamed to `native/settings/build.sh`. The
151
+ `threaded.sh` settings file has been removed.
152
+ - TypeScript wrapper no longer branches on threading: `WImageMagickOptions`
153
+ drops `preferThreaded`, `WImageMagickInstance` drops `isThreaded`, and the
154
+ `detectThreadingSupport()` helper is gone.
155
+
156
+ ### Fixed
157
+ - In the playground, Auto-orient, Strip and Convert with "Same as input" work
158
+ on camera raws and HEIC. They used to fail with
159
+ `NoEncodeDelegateForThisImageFormat`, since ImageMagick cannot write those
160
+ formats; the result is now saved as PNG, and the output line says so.
161
+ - The playground's input panel previews camera raws (and HEIC, JXL, TIFF or
162
+ JP2 in browsers that cannot display them) instead of showing a broken image.
163
+ When the browser cannot decode a file itself, the preview is rendered from
164
+ ImageMagick's decode — oriented, and capped at 2048 px — and the compare
165
+ slider uses it too. A file that cannot be read at all shows "No preview".
166
+ - A truncated or damaged RAW file now fails like any other bad image — exit
167
+ code 1 and an ImageMagick error from the DNG coder — instead of throwing a bare
168
+ pointer out of `callMain`. The prebuilt LibRaw had its exception handlers
169
+ compiled out, so every such file leaked about a megabyte and a few dozen of
170
+ them crashed the module for good (`memory access out of bounds`). LibRaw is
171
+ now built from source with exception catching; a thousand damaged raws in a
172
+ row leave the module healthy.
173
+ - A command's `stdout` now arrives with that command. The CLI entry point
174
+ (`native/bindings/api-exports.c`) flushes libc's streams before returning:
175
+ the runtime is deliberately kept alive between commands (`EXIT_RUNTIME=0`),
176
+ so nothing flushed at exit and a command's output sat in the buffer until
177
+ some later command pushed it out. Output is line-buffered, so `-format`
178
+ strings still need their trailing `\n`. Requires a WASM rebuild.
179
+ - `execute()` now resolves the filename behind an explicit format prefix.
180
+ `dng:capture` and `info:report.txt` were treated as pseudo-formats and left
181
+ pointing outside the command's working directory, so the first failed with
182
+ "No such file or directory" and the second silently wrote its report where
183
+ nothing could read it back — including the `info:report.txt` example in
184
+ `docs/api.md`. Pseudo-formats whose argument is content (`xc:`, `gradient:`,
185
+ `label:`, `plasma:`, `null:` and friends) are still passed through untouched.
186
+ - `execute()` and `identify()` return the command's output again. Emscripten
187
+ captures `print`/`printErr` while the module is being constructed, so the
188
+ previous approach of reassigning them per command left `stdout` and
189
+ `stderr` permanently empty; the loader now installs the hooks up front.
190
+ - `identify()` returns a real description (`"<width> <height> <format>"`, or
191
+ ImageMagick's verbose report). It used to invoke a non-existent `identify`
192
+ sub-command — this build exposes ImageMagick's image command directly — and
193
+ returned an empty string for every image.
194
+ - `execute()` resolves filenames that start with a digit or with `x`
195
+ (`2024-photo.jpg`, `xray.png`), which it previously mistook for geometry and
196
+ pseudo-format arguments and failed to find, and it no longer rewrites
197
+ pseudo-format arguments such as `gradient:red-blue`, `null:` or `info:` into
198
+ working-directory paths. Output names now need an extension to be recognised.
199
+ - `parseCommand()` keeps an explicitly empty quoted argument (`-set comment ""`)
200
+ instead of dropping it and shifting the rest of argv.
201
+
202
+ ### Removed
203
+ - OpenEXR support (`--with-openexr=no`). The prebuilt EXR objects trip
204
+ Emscripten cross-compile feature detection; HEIC/AVIF/JXL/JP2 cover the
205
+ high-dynamic-range and modern-format use cases.
206
+ - Threaded build infrastructure: `native/settings/threaded.sh`,
207
+ `native/scripts/build-deps-threaded.sh`, the `BUILD_VARIANT` and
208
+ `WASM_THREAD_FLAGS` CMake plumbing, the `build:native:threaded` /
209
+ `build:native:single` npm scripts, and the dual-variant CI jobs.
210
+
211
+ ## [0.1.0] - Initial development (not tagged or published)
212
+
213
+ ### Added
214
+ - Native WASM build pipeline (`native/`): Dockerised Emscripten toolchain,
215
+ ImageMagick v7 cross-compile against prebuilt delegate static libraries.
216
+ - Verified format support: JPEG, PNG, WebP, TIFF, GIF, BMP, AVIF, JXL, JP2,
217
+ HEIC (decode), RAW (via LibRaw).
218
+ - TypeScript wrapper (`src/`): `initWImageMagick()` loader, `WMagickImage`
219
+ high-level chainable image class, MagickWand C-API bindings via `cwrap`,
220
+ CLI-style `execute()`, MEMFS file helpers, Web Worker entry point.
221
+ - GitLab CI pipeline (`.gitlab-ci.yml`): registry-cached Docker image,
222
+ WASM build, TypeScript build, test stage, GitLab Pages deploy of the
223
+ browser playground.
224
+ - Browser playground (`examples/browser/index.html`): drag-and-drop, format
225
+ conversion, resize, quality, strip metadata, auto-orient, CLI mode.
226
+ - Convenience C wrappers exported from the WASM module:
227
+ `wimagemagick_identify`, `wimagemagick_convert`, `wimagemagick_resize`.
228
+
229
+ [Unreleased]: https://gitlab.com/wasmedia/wimagemagick/-/compare/v0.2.0...HEAD
230
+ [0.2.0]: https://gitlab.com/wasmedia/wimagemagick/-/tags/v0.2.0
package/LICENSE ADDED
@@ -0,0 +1,199 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for describing the origin of the Work and
141
+ reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Support. While redistributing the Work or
166
+ Derivative Works thereof, You may choose to offer, and charge a
167
+ fee for, acceptance of support, warranty, indemnity, or other
168
+ liability obligations and/or rights consistent with this License.
169
+ However, in accepting such obligations, You may act only on Your
170
+ own behalf and on Your sole responsibility, not on behalf of any
171
+ other Contributor, and only if You agree to indemnify, defend,
172
+ and hold each Contributor harmless for any liability incurred by,
173
+ or claims asserted against, such Contributor by reason of your
174
+ accepting any such warranty or support.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recognize an "include"
185
+ as a comment marker.
186
+
187
+ Copyright 2026 Roger Howard
188
+
189
+ Licensed under the Apache License, Version 2.0 (the "License");
190
+ you may not use this file except in compliance with the License.
191
+ You may obtain a copy of the License at
192
+
193
+ http://www.apache.org/licenses/LICENSE-2.0
194
+
195
+ Unless required by applicable law or agreed to in writing, software
196
+ distributed under the License is distributed on an "AS IS" BASIS,
197
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
198
+ See the License for the specific language governing permissions and
199
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # wimagemagick
2
+
3
+ [![pipeline status](https://gitlab.com/wasmedia/wimagemagick/badges/main/pipeline.svg)](https://gitlab.com/wasmedia/wimagemagick/-/commits/main)
4
+ [![latest release](https://gitlab.com/wasmedia/wimagemagick/-/badges/release.svg)](https://gitlab.com/wasmedia/wimagemagick/-/releases)
5
+ [![license: Apache 2.0](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
6
+ [![ImageMagick](https://img.shields.io/badge/ImageMagick-v7-orange.svg)](https://imagemagick.org/)
7
+ [![WebAssembly](https://img.shields.io/badge/WebAssembly-SIMD-654ff0.svg)](https://webassembly.org/)
8
+
9
+ A feature-complete ImageMagick build with all modern dependencies, compiled for WASM so it can be easily run in a modern browser.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @wasmedia/wimagemagick
15
+ ```
16
+
17
+ ```typescript
18
+ import { initWImageMagick } from '@wasmedia/wimagemagick';
19
+
20
+ const wim = await initWImageMagick();
21
+ const img = wim.Image.fromBuffer(bytes);
22
+ const jpeg = img.fit(1600, 1600).quality(85).toBuffer('JPEG');
23
+ img.dispose();
24
+ ```
25
+
26
+ The package ships the `.wasm` (about 13 MB, 5 MB gzipped) next to its JS, and
27
+ loads it relative to the module, so a bundler that copies assets referenced by
28
+ `new URL(..., import.meta.url)` needs no configuration. [docs/api.md](docs/api.md)
29
+ has the full API, including the Web Worker entry
30
+ (`@wasmedia/wimagemagick/worker`). The WASM statically links ImageMagick and
31
+ several LGPL libraries; their licences are in `dist/licenses/`.
32
+
33
+ Try it without installing at [magick.wasmedia.org](https://magick.wasmedia.org/).
34
+
35
+ ## Format & Feature Scope
36
+
37
+ - **Excluded:** Ghostscript-based features (PDF rendering), FFmpeg-based features (video)
38
+ - **Included:** As many image formats as practical, specifically:
39
+ - Common raster, read and write: JPEG, PNG, WebP, TIFF, GIF, BMP, AVIF, JXL, JP2/J2K
40
+ - HEIC/HEIF (via libheif) — decode only; encoding would need x265
41
+ - RAW camera formats (via LibRaw) — decode only; the common ones are
42
+ detected from their headers, see [Reading RAW files](docs/api.md#reading-raw-files)
43
+ - Other formats as practical to cross-compile
44
+
45
+ `docs/building.md` has the verified format matrix and the list of delegates
46
+ that are deliberately absent.
47
+
48
+ ## Technical Requirements
49
+
50
+ - **ImageMagick version:** Always target the current stable release (currently v7)
51
+ - **API surface:** Both CLI-style interface (pass command strings) and C API (MagickWand/MagickCore)
52
+ - **JS wrapper:** High-level JS wrapper on top of the C bindings, plus CLI-style command execution
53
+ - **Toolchain:** Open to any practical WASM toolchain (Emscripten is the likely choice)
54
+ - **Output:** Both a single `.wasm` + JS glue bundle and an npm-distributable package
55
+ - **Bundle size:** Large binaries are acceptable if necessary to support the full format set
56
+ - **File I/O:** Support both Emscripten virtual filesystem (MEMFS) and direct `ArrayBuffer`/`Blob` passing
57
+ - **Web Workers:** Should support running off the main thread
58
+ - **Distribution:** Open source, published to npm as `@wasmedia/wimagemagick`
59
+ - **Browser support:** Chrome and Safari at minimum
60
+ - **Build:** Single-threaded + SIMD — works on any site without special headers
61
+
62
+ ## Prior Art
63
+
64
+ | Project | Status | IM Version | Delegates | Threading/SIMD | API Style |
65
+ |---------|--------|------------|-----------|----------------|-----------|
66
+ | [@imagemagick/magick-wasm](https://github.com/dlemstra/magick-wasm) | Active, ~853 stars | v7 (current) | Rich (HEIF, WebP, RAW, JXL, EXR) | None | OOP TypeScript only |
67
+ | [WASM-ImageMagick](https://github.com/KnicKnic/WASM-ImageMagick) | Abandoned (2023) | v7 (~2019 era) | Minimal (JPEG, PNG, TIFF, GIF) | None | CLI strings only |
68
+ | [magickwand.js](https://github.com/mmomtchev/magickwand.js) | Active, ~91 stars | v7 (current) | Rich (HEIF, WebP, EXR) | Partial async workers | Full Magick++ OOP |
69
+
70
+ **Gaps wimagemagick fills:**
71
+ - No project offers both CLI-style and programmatic API
72
+ - AVIF support is absent from all
73
+
74
+ **Build-on opportunity:** dlemstra's [Magick.Native](https://github.com/dlemstra/Magick.Native) already cross-compiles ImageMagick v7 + rich delegates to WASM via Emscripten. It could serve as a foundation for the native build, with wimagemagick adding threading/SIMD builds, CLI interface, and the JS wrapper layer on top.
75
+
package/dist/api.d.ts ADDED
@@ -0,0 +1,68 @@
1
+ /**
2
+ * MagickWand C API bindings via Emscripten cwrap.
3
+ *
4
+ * Provides typed wrappers around all exported MagickWand functions.
5
+ * For direct, low-level access to ImageMagick's C API from JavaScript.
6
+ */
7
+ import type { WasmModule } from "./types.js";
8
+ export interface MagickBindings {
9
+ MagickWandGenesis(): void;
10
+ MagickWandTerminus(): void;
11
+ NewMagickWand(): number;
12
+ DestroyMagickWand(wand: number): number;
13
+ CloneMagickWand(wand: number): number;
14
+ MagickReadImage(wand: number, filename: string): number;
15
+ MagickWriteImage(wand: number, filename: string): number;
16
+ MagickReadImageBlob(wand: number, blob: number, length: number): number;
17
+ MagickGetImageBlob(wand: number, lengthPtr: number): number;
18
+ MagickRelinquishMemory(ptr: number): number;
19
+ MagickGetImageWidth(wand: number): number;
20
+ MagickGetImageHeight(wand: number): number;
21
+ MagickGetImageFormat(wand: number): string;
22
+ MagickSetImageFormat(wand: number, format: string): number;
23
+ MagickResizeImage(wand: number, width: number, height: number, filter: number): number;
24
+ MagickAdaptiveResizeImage(wand: number, width: number, height: number): number;
25
+ MagickThumbnailImage(wand: number, width: number, height: number): number;
26
+ MagickCropImage(wand: number, width: number, height: number, x: number, y: number): number;
27
+ MagickExtentImage(wand: number, width: number, height: number, x: number, y: number): number;
28
+ MagickRotateImage(wand: number, background: number, degrees: number): number;
29
+ MagickFlipImage(wand: number): number;
30
+ MagickFlopImage(wand: number): number;
31
+ MagickTransposeImage(wand: number): number;
32
+ MagickTransverseImage(wand: number): number;
33
+ MagickBlurImage(wand: number, radius: number, sigma: number): number;
34
+ MagickGaussianBlurImage(wand: number, radius: number, sigma: number): number;
35
+ MagickSharpenImage(wand: number, radius: number, sigma: number): number;
36
+ MagickUnsharpMaskImage(wand: number, radius: number, sigma: number, gain: number, threshold: number): number;
37
+ MagickCompositeImage(wand: number, sourceWand: number, compose: number, clipToSelf: number, x: number, y: number): number;
38
+ MagickSetImageCompressionQuality(wand: number, quality: number): number;
39
+ MagickGetImageCompressionQuality(wand: number): number;
40
+ MagickStripImage(wand: number): number;
41
+ MagickAutoOrientImage(wand: number): number;
42
+ MagickAutoLevelImage(wand: number): number;
43
+ MagickNormalizeImage(wand: number): number;
44
+ MagickDeskewImage(wand: number, threshold: number): number;
45
+ MagickSetImageAlphaChannel(wand: number, alphaType: number): number;
46
+ MagickGetException(wand: number, severityPtr: number): string;
47
+ MagickClearException(wand: number): number;
48
+ MagickSetResourceLimit(type: number, limit: number): number;
49
+ MagickGetResourceLimit(type: number): number;
50
+ MagickSetSize(wand: number, width: number, height: number): number;
51
+ MagickSetDepth(wand: number, depth: number): number;
52
+ MagickGetNumberImages(wand: number): number;
53
+ MagickSetIteratorIndex(wand: number, index: number): number;
54
+ MagickResetIterator(wand: number): void;
55
+ MagickGetImageDepth(wand: number): number;
56
+ MagickSetImageDepth(wand: number, depth: number): number;
57
+ MagickGetImageColorspace(wand: number): number;
58
+ MagickSetImageColorspace(wand: number, colorspace: number): number;
59
+ MagickProfileImage(wand: number, name: string, profile: number, length: number): number;
60
+ MagickGetImageProfile(wand: number, name: string, lengthPtr: number): number;
61
+ MagickRemoveImageProfile(wand: number, name: string, lengthPtr: number): number;
62
+ wimagemagick_identify(blob: number, length: number, widthPtr: number, heightPtr: number, formatPtr: number, formatBufSize: number): number;
63
+ wimagemagick_convert(blob: number, length: number, format: string, quality: number, outLengthPtr: number): number;
64
+ wimagemagick_resize(blob: number, length: number, width: number, height: number, format: string, quality: number, outLengthPtr: number): number;
65
+ }
66
+ /** Create typed bindings for all exported MagickWand C functions. */
67
+ export declare function createBindings(module: WasmModule): MagickBindings;
68
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}