imagescript 3.2.1 → 3.4.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.
- package/README.md +35 -10
- package/THIRD_PARTY_NOTICES.md +298 -2
- package/dist/animation.d.ts +25 -8
- package/dist/animation.js +44 -13
- package/dist/codecs/av1/cdef.js +197 -0
- package/dist/codecs/av1/data.js +141 -0
- package/dist/codecs/av1/decode.js +1769 -0
- package/dist/codecs/av1/filmgrain.js +219 -0
- package/dist/codecs/av1/frame.js +114 -0
- package/dist/codecs/av1/ipred.js +491 -0
- package/dist/codecs/av1/itx.js +950 -0
- package/dist/codecs/av1/loopfilter.js +149 -0
- package/dist/codecs/av1/msac.js +161 -0
- package/dist/codecs/av1/obu.js +516 -0
- package/dist/codecs/av1/postfilter.js +28 -0
- package/dist/codecs/av1/restoration.js +193 -0
- package/dist/codecs/av1/tables.js +160 -0
- package/dist/codecs/avif.js +581 -0
- package/dist/codecs/bmp.js +317 -0
- package/dist/codecs/crc.js +5 -0
- package/dist/codecs/gif.js +10 -35
- package/dist/codecs/hdr.d.ts +25 -0
- package/dist/codecs/hdr.js +201 -0
- package/dist/codecs/ico.js +48 -0
- package/dist/codecs/jpeg.js +11 -28
- package/dist/codecs/jxl/bits.js +126 -0
- package/dist/codecs/jxl/blend.js +117 -0
- package/dist/codecs/jxl/color.js +116 -0
- package/dist/codecs/jxl/dct.js +404 -0
- package/dist/codecs/jxl/entropy.js +556 -0
- package/dist/codecs/jxl/features.js +325 -0
- package/dist/codecs/jxl/filters.js +119 -0
- package/dist/codecs/jxl/frame-header.js +195 -0
- package/dist/codecs/jxl/frame.js +319 -0
- package/dist/codecs/jxl/headers.js +249 -0
- package/dist/codecs/jxl/idct.js +484 -0
- package/dist/codecs/jxl/modular.js +688 -0
- package/dist/codecs/jxl/quant.js +219 -0
- package/dist/codecs/jxl/upsample.js +52 -0
- package/dist/codecs/jxl/vardct.js +472 -0
- package/dist/codecs/jxl.js +89 -0
- package/dist/codecs/netpbm.js +239 -0
- package/dist/codecs/png.js +22 -10
- package/dist/codecs/qoi.js +150 -0
- package/dist/codecs/tga.js +3 -1
- package/dist/codecs/tiff.js +7 -2
- package/dist/codecs/vp8-enc-dsp.js +932 -0
- package/dist/codecs/vp8-enc-tables.js +78 -0
- package/dist/codecs/vp8-enc.js +1930 -0
- package/dist/codecs/vp8.js +3 -1
- package/dist/codecs/vp8l.js +126 -58
- package/dist/codecs/webp.js +47 -11
- package/dist/codecs/zlib.js +81 -69
- package/dist/frame.d.ts +1 -0
- package/dist/frame.js +4 -2
- package/dist/gif.d.ts +1 -0
- package/dist/gif.js +2 -2
- package/dist/image-type.d.ts +15 -1
- package/dist/image-type.js +45 -2
- package/dist/image.d.ts +89 -13
- package/dist/image.js +266 -113
- package/dist/index.d.ts +3 -2
- package/dist/index.js +4 -4
- package/dist/render/bidi.js +350 -0
- package/dist/render/buffer.js +362 -0
- package/dist/render/color.js +164 -0
- package/dist/render/colr.js +523 -0
- package/dist/render/font.js +173 -241
- package/dist/render/hinting.js +38 -22
- package/dist/render/layout.js +1553 -0
- package/dist/render/linebreak.js +210 -0
- package/dist/render/segment.js +106 -0
- package/dist/render/shape.js +984 -0
- package/dist/render/shapers/arabic.js +284 -0
- package/dist/render/shapers/hangul.js +142 -0
- package/dist/render/shapers/hebrew.js +49 -0
- package/dist/render/shapers/index.js +52 -0
- package/dist/render/shapers/indic.js +579 -0
- package/dist/render/shapers/khmer.js +104 -0
- package/dist/render/shapers/machine.js +129 -0
- package/dist/render/shapers/myanmar.js +121 -0
- package/dist/render/shapers/syllabic.js +100 -0
- package/dist/render/shapers/thai.js +125 -0
- package/dist/render/shapers/use.js +235 -0
- package/dist/render/svg.js +102 -23
- package/dist/render/text.js +373 -103
- package/dist/render/unicode-data.js +63 -0
- package/dist/render/unicode.js +50 -0
- package/dist/text-layout.d.ts +4 -1
- package/dist/text-layout.js +2 -2
- package/dist/util/alpha.js +43 -0
- package/dist/util/blur.js +20 -33
- package/dist/util/bytes.js +40 -0
- package/dist/util/limits.js +34 -0
- package/dist/util/options.js +7 -0
- package/dist/util/resample.js +126 -7
- package/dist/util/rotate.js +43 -0
- package/dist/version.js +1 -1
- package/licenses/HarfBuzz.txt +42 -0
- package/licenses/Unicode-3.0.txt +39 -0
- package/package.json +25 -2
package/README.md
CHANGED
|
@@ -26,14 +26,29 @@ deno add jsr:@matmen/imagescript # Deno (npm:imagescript works too)
|
|
|
26
26
|
- JPEGs (baseline and progressive; grayscale, RGB, CMYK)
|
|
27
27
|
- TIFFs (strips and tiles; uncompressed, LZW, deflate, PackBits and JPEG compressed; BigTIFF)
|
|
28
28
|
- WebPs (lossy, lossless and with alpha; bit-exact with libwebp)
|
|
29
|
+
- BMPs (1-64 bit, with any channel masks, alpha, RLE4 and RLE8, embedded JPEGs and PNGs; also OS/2 bitmaps)
|
|
30
|
+
- ICOs and CURs (the largest image: bitmaps with their masks, or PNGs)
|
|
31
|
+
- QOIs
|
|
32
|
+
- Netpbm images: PBM, PGM, PPM (plain and raw, up to 16 bits), PAM and PFM
|
|
33
|
+
- Radiance HDRs (RGBE and XYZE, every orientation), tone mapped to sRGB like Reinhard's operator does (or clamped,
|
|
34
|
+
`toneMapping`)
|
|
29
35
|
- TGAs (color mapped, truecolor and greyscale; uncompressed and run length encoded)
|
|
36
|
+
- AVIFs (4:2:0, 4:2:2, 4:4:4 and monochrome, 8-12 bit; grids, alpha, crop, rotation and mirroring; the first frame
|
|
37
|
+
of image sequences; bit-exact with dav1d and libavif), HDR ones (PQ, HLG) tone mapped to sRGB
|
|
38
|
+
- JPEG XLs (Modular and VarDCT, lossless and lossy, every coding tool: progressive passes and LF frames, patches,
|
|
39
|
+
splines, noise, restoration filters, upsampling, JPEG recompression, layers and blending, alpha and spot colors,
|
|
40
|
+
CMYK; animations; within 1 of libjxl's djxl on the conformance suite), XYB ones as sRGB, HDR ones tone mapped to
|
|
41
|
+
sRGB
|
|
30
42
|
- JPEGs, TIFFs, PNGs and WebPs are rotated as their Exif (or, for PNGs, XMP) orientation says
|
|
31
|
-
-
|
|
43
|
+
- images larger than 268 megapixels (`maxPixels`) are rejected before decoding, so small files declaring huge images
|
|
44
|
+
can't exhaust the memory
|
|
45
|
+
- [Decoding animations](https://imagescript.matmen.dev/classes/Animation.html#decode) (GIF, APNG, WebP and JPEG XL) with all
|
|
32
46
|
frames, durations and disposal modes
|
|
33
47
|
- [Rendering SVGs](https://imagescript.matmen.dev/classes/Image.html#rendersvg) (shapes, paths, gradients, strokes, clip paths,
|
|
34
48
|
masks, CSS; no text, images or filters)
|
|
35
|
-
- [Rendering vector fonts](https://imagescript.matmen.dev/classes/Image.html#rendertext) (TrueType and OpenType, with
|
|
36
|
-
|
|
49
|
+
- [Rendering vector fonts](https://imagescript.matmen.dev/classes/Image.html#rendertext) (TrueType and OpenType, with
|
|
50
|
+
complex text shaping in every script, right to left and bidirectional text, outlines, TrueType hinting, fallback
|
|
51
|
+
fonts and color emoji)
|
|
37
52
|
- [Resizing](https://imagescript.matmen.dev/classes/Image.html#resize) (bilinear, bicubic, area averaging and nearest neighbor)
|
|
38
53
|
- Image manipulation functions ([crop](https://imagescript.matmen.dev/classes/Image.html#crop)
|
|
39
54
|
, [rotate](https://imagescript.matmen.dev/classes/Image.html#rotate)
|
|
@@ -50,10 +65,15 @@ deno add jsr:@matmen/imagescript # Deno (npm:imagescript works too)
|
|
|
50
65
|
, [dominantColor](https://imagescript.matmen.dev/classes/Image.html#dominantcolor), ...)
|
|
51
66
|
- Encoding images as [PNGs](https://imagescript.matmen.dev/classes/Image.html#encode) (smallest lossless color type)
|
|
52
67
|
, [JPEGs](https://imagescript.matmen.dev/classes/Image.html#encodejpeg)
|
|
53
|
-
, lossless [WebPs](https://imagescript.matmen.dev/classes/Image.html#encodewebp)
|
|
68
|
+
, lossless and lossy [WebPs](https://imagescript.matmen.dev/classes/Image.html#encodewebp) (lossy ones byte for
|
|
69
|
+
byte like libwebp's cwebp)
|
|
70
|
+
, [BMPs](https://imagescript.matmen.dev/classes/Image.html#encodebmp)
|
|
71
|
+
, [QOIs](https://imagescript.matmen.dev/classes/Image.html#encodeqoi)
|
|
72
|
+
, [Netpbm images](https://imagescript.matmen.dev/classes/Image.html#encodepnm) (PBM, PGM, PPM or PAM, whichever is
|
|
73
|
+
smallest)
|
|
54
74
|
and [TGAs](https://imagescript.matmen.dev/classes/Image.html#encodetga)
|
|
55
75
|
- Encoding animations as [GIF](https://imagescript.matmen.dev/classes/Animation.html#encodegif),
|
|
56
|
-
[APNG](https://imagescript.matmen.dev/classes/Animation.html#encodeapng) and lossless
|
|
76
|
+
[APNG](https://imagescript.matmen.dev/classes/Animation.html#encodeapng) and lossless or lossy
|
|
57
77
|
[WebP](https://imagescript.matmen.dev/classes/Animation.html#encodewebp), storing only what changes from frame to frame
|
|
58
78
|
|
|
59
79
|
---
|
|
@@ -78,9 +98,8 @@ const { Image } = require('imagescript');
|
|
|
78
98
|
All coordinates are 0-based, `(0, 0)` is the top left pixel.
|
|
79
99
|
|
|
80
100
|
A bigger example is the [README image generation](https://github.com/matmen/ImageScript/blob/master/tests/readme.js).
|
|
81
|
-
Upgrading from 1.x? Version 3 has breaking changes (0-based coordinates,
|
|
82
|
-
see the [changelog](https://github.com/matmen/ImageScript/blob/master/CHANGELOG.md).
|
|
83
|
-
`imagescript/v2` API.
|
|
101
|
+
Upgrading from 1.x? Version 3 has breaking changes (0-based coordinates, lossy WebP encoding as `encodeWebP({ quality })`,
|
|
102
|
+
Node.js 22.13+, ...), see the [changelog](https://github.com/matmen/ImageScript/blob/master/CHANGELOG.md).
|
|
84
103
|
|
|
85
104
|
[](https://github.com/matmen/ImageScript/blob/master/tests/readme.js)
|
|
86
105
|
|
|
@@ -100,8 +119,14 @@ The deflate/inflate implementation is derived from [fflate](https://github.com/1
|
|
|
100
119
|
The JPEG codec is based in part on the work of the Independent JPEG Group (libjpeg) and on
|
|
101
120
|
[pdf.js](https://github.com/mozilla/pdf.js), the glyph rasterizer is translated from
|
|
102
121
|
[font-rs](https://github.com/raphlinus/font-rs). The WebP codecs follow [RFC 9649](https://www.rfc-editor.org/rfc/rfc9649) and [RFC 6386](https://www.rfc-editor.org/rfc/rfc6386)
|
|
103
|
-
and reproduce [libwebp](https://chromium.googlesource.com/webm/libwebp)'s color conversion, the
|
|
104
|
-
|
|
122
|
+
and reproduce [libwebp](https://chromium.googlesource.com/webm/libwebp)'s color conversion, the lossy WebP encoder is
|
|
123
|
+
ported from libwebp's, the TrueType hinting follows
|
|
124
|
+
[FreeType](https://freetype.org)'s interpreter (portions of this software are copyright © 2026 The FreeType Project),
|
|
125
|
+
the text shaping is ported from [HarfBuzz](https://github.com/harfbuzz/harfbuzz) and uses data of the
|
|
126
|
+
[Unicode Character Database](https://www.unicode.org/ucd/). The AV1 decoder is ported from
|
|
127
|
+
[dav1d](https://code.videolan.org/videolan/dav1d), AVIFs are converted to RGB like
|
|
128
|
+
[libavif](https://github.com/AOMediaCodec/libavif) does, the JPEG XL decoder is ported from
|
|
129
|
+
[jxl-oxide](https://github.com/tirr-c/jxl-oxide) and [libjxl](https://github.com/libjxl/libjxl).
|
|
105
130
|
See [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) for their licenses.
|
|
106
131
|
|
|
107
132
|
---
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -12,8 +12,18 @@ following projects, under their own licenses. Each derived file says so in its h
|
|
|
12
12
|
| [font-rs](https://github.com/raphlinus/font-rs) by Raph Levien | `src/render/text.ts` (the `Rasterizer` class, also used for SVGs) | Apache-2.0 |
|
|
13
13
|
| [RFC 9649](https://www.rfc-editor.org/rfc/rfc9649) (WebP Image Format) | `src/codecs/vp8l.ts` (lossless bitstream, short distance code table), `src/codecs/webp.ts` (container) | BSD-3-Clause (Revised BSD) |
|
|
14
14
|
| [RFC 6386](https://www.rfc-editor.org/rfc/rfc6386) (VP8 Data Format and Decoding Guide, with the libvpx reference decoder) | `src/codecs/vp8-tables.ts` (probability and quantizer tables), `src/codecs/vp8.ts` (decoding procedures) | BSD-3-Clause |
|
|
15
|
-
| [libwebp](https://chromium.googlesource.com/webm/libwebp) | `src/codecs/vp8.ts` (YUV to RGB conversion, "fancy" chroma upsampling), `src/codecs/webp.ts` (animation frame blending) | BSD-3-Clause |
|
|
15
|
+
| [libwebp](https://chromium.googlesource.com/webm/libwebp) | `src/codecs/vp8.ts` (YUV to RGB conversion, "fancy" chroma upsampling), `src/codecs/webp.ts` (animation frame blending), `src/codecs/vp8-enc.ts`, `src/codecs/vp8-enc-dsp.ts` (the lossy encoder: RGB to YUV conversion, analysis, segments, rate-distortion optimized mode decisions, quantization, token probabilities, bitstream, alpha filtering), `src/codecs/vp8-enc-tables.ts` (its tables, generated from libwebp by `scripts/vp8-enc-tables.py`) | BSD-3-Clause |
|
|
16
|
+
| [dav1d](https://code.videolan.org/videolan/dav1d) by VideoLAN, the dav1d authors and Two Orioles | `src/codecs/av1/*` (the AV1 decoder: bitstream parsing, symbol decoding, prediction, inverse transforms, loop filters, film grain; the tables in `src/codecs/av1/data.ts`, generated from dav1d by `scripts/av1-tables.c`) | BSD-2-Clause |
|
|
17
|
+
| [libavif](https://github.com/AOMediaCodec/libavif) by Joe Drago | `src/codecs/avif.ts` (YUV to RGB conversion with bilinear chroma upsampling, alpha range expansion and unpremultiplication) | BSD-2-Clause |
|
|
18
|
+
| [jxl-oxide](https://github.com/tirr-c/jxl-oxide) by Wonwoo Choi | `src/codecs/jxl/*` (the JPEG XL decoder: bit reader, header and frame header fields, entropy decoding, VarDCT, dequantization matrices, transforms, restoration filters, upsampling, the parsing of patches, splines and noise) | MIT (or Apache-2.0) |
|
|
19
|
+
| [libjxl](https://github.com/libjxl/libjxl) by the JPEG XL Project Authors | `src/codecs/jxl/modular.ts` (Modular decoding: MA trees, predictors, the self-correcting predictor, transforms), `src/codecs/jxl/frame.ts` (the sections of frames, the order of the rendering stages, reference frames), `src/codecs/jxl/blend.ts`, `src/codecs/jxl/color.ts` (XYB to RGB), `src/codecs/jxl/features.ts` (rendering patches, splines and noise) | BSD-3-Clause |
|
|
20
|
+
| [JPEG XL conformance](https://github.com/libjxl/conformance) by the JPEG XL Project Authors | `tests/jxl/alpha-*.jxl`, `animation-spline.jxl`, `blendmodes.jxl`, `mul-no-extra-channels.jxl` (test files) | BSD-3-Clause |
|
|
16
21
|
| [FreeType](https://freetype.org) | `src/render/hinting.ts` (behavior and parts of the logic of the TrueType interpreter) | FreeType License |
|
|
22
|
+
| [QOI](https://github.com/phoboslab/qoi) by Dominic Szablewski | `src/codecs/qoi.ts` (the reference encoder's choices of operations) | MIT |
|
|
23
|
+
| [Pillow](https://github.com/python-pillow/Pillow) | `src/util/resample.ts` (filter coefficients, box, bilinear and bicubic filters) | MIT-CMU |
|
|
24
|
+
| [HarfBuzz](https://github.com/harfbuzz/harfbuzz) | `src/render/buffer.ts`, `src/render/layout.ts`, `src/render/shape.ts`, `src/render/shapers/*` (OpenType shaping: buffer, GSUB/GPOS, normalization, fallback positioning, the script shapers and syllable grammars), `scripts/unicode.js` (shaping category tables) | Old MIT |
|
|
25
|
+
| [Universal Shaping Engine data](https://github.com/harfbuzz/harfbuzz/tree/main/src/ms-use) by Microsoft | `scripts/ms-use` (category overrides, invalid vowel sequences), the tables generated from them in `src/render/unicode-data.ts` | MIT |
|
|
26
|
+
| [Unicode Character Database](https://www.unicode.org/ucd/) | `src/render/unicode-data.ts` (character properties, generated by `scripts/unicode.js`) | Unicode License v3 |
|
|
17
27
|
|
|
18
28
|
## fflate, Fast CRC32 in JavaScript
|
|
19
29
|
|
|
@@ -81,7 +91,8 @@ one decode function per scan type). The `Rasterizer` class in `src/render/text.t
|
|
|
81
91
|
|
|
82
92
|
The VP8 decoder follows the procedures of RFC 6386 and its reference decoder, its constant tables are extracted from
|
|
83
93
|
the RFC. To decode exactly like libwebp, the YUV to RGB conversion, the chroma upsampling and the blending of animation
|
|
84
|
-
frames reproduce libwebp's integer arithmetic.
|
|
94
|
+
frames reproduce libwebp's integer arithmetic. The lossy encoder is ported from libwebp's (version 1.6.0, its default
|
|
95
|
+
settings) and writes the same VP8 bitstreams as cwebp.
|
|
85
96
|
|
|
86
97
|
```
|
|
87
98
|
RFC 6386 reference decoder: Copyright (c) 2010, 2011, Google Inc. All rights reserved.
|
|
@@ -144,6 +155,138 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWIS
|
|
|
144
155
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
145
156
|
```
|
|
146
157
|
|
|
158
|
+
## dav1d
|
|
159
|
+
|
|
160
|
+
The AV1 decoder is ported from dav1d 1.5.1 and decodes exactly like it (the frames of its intra coding tools, with
|
|
161
|
+
every post filter and film grain); its tables are generated from dav1d's. The ported files are Copyright © 2018-2021,
|
|
162
|
+
VideoLAN and dav1d authors, and Copyright © 2018, Two Orioles, LLC, under dav1d's license. AV1 is covered by the
|
|
163
|
+
[Alliance for Open Media Patent License 1.0](https://aomedia.org/license/patent-license/).
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Copyright © 2018-2019, VideoLAN and dav1d authors
|
|
167
|
+
All rights reserved.
|
|
168
|
+
|
|
169
|
+
Redistribution and use in source and binary forms, with or without
|
|
170
|
+
modification, are permitted provided that the following conditions are met:
|
|
171
|
+
|
|
172
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
173
|
+
list of conditions and the following disclaimer.
|
|
174
|
+
|
|
175
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
176
|
+
this list of conditions and the following disclaimer in the documentation
|
|
177
|
+
and/or other materials provided with the distribution.
|
|
178
|
+
|
|
179
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
180
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
181
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
182
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
183
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
184
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
185
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
186
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
187
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
188
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## libavif
|
|
192
|
+
|
|
193
|
+
The conversion of decoded AVIFs to RGB reproduces libavif's reference conversion (in floating point, with bilinear
|
|
194
|
+
chroma upsampling), so the pixels are the ones libavif gives.
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
Copyright 2019 Joe Drago. All rights reserved.
|
|
198
|
+
|
|
199
|
+
Redistribution and use in source and binary forms, with or without
|
|
200
|
+
modification, are permitted provided that the following conditions are met:
|
|
201
|
+
|
|
202
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
203
|
+
list of conditions and the following disclaimer.
|
|
204
|
+
|
|
205
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
206
|
+
this list of conditions and the following disclaimer in the documentation
|
|
207
|
+
and/or other materials provided with the distribution.
|
|
208
|
+
|
|
209
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
210
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
211
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
212
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
213
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
214
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
215
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
216
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
217
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
218
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## jxl-oxide
|
|
222
|
+
|
|
223
|
+
The structure of the JPEG XL decoder and most of its parts are ported from jxl-oxide (which may be used under the MIT
|
|
224
|
+
or the Apache-2.0 license; the MIT license applies here).
|
|
225
|
+
|
|
226
|
+
```
|
|
227
|
+
Copyright (c) Wonwoo Choi
|
|
228
|
+
|
|
229
|
+
Permission is hereby granted, free of charge, to any
|
|
230
|
+
person obtaining a copy of this software and associated
|
|
231
|
+
documentation files (the "Software"), to deal in the
|
|
232
|
+
Software without restriction, including without
|
|
233
|
+
limitation the rights to use, copy, modify, merge,
|
|
234
|
+
publish, distribute, sublicense, and/or sell copies of
|
|
235
|
+
the Software, and to permit persons to whom the Software
|
|
236
|
+
is furnished to do so, subject to the following
|
|
237
|
+
conditions:
|
|
238
|
+
|
|
239
|
+
The above copyright notice and this permission notice
|
|
240
|
+
shall be included in all copies or substantial portions
|
|
241
|
+
of the Software.
|
|
242
|
+
|
|
243
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
244
|
+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
245
|
+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
246
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
247
|
+
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
248
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
249
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
250
|
+
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
251
|
+
DEALINGS IN THE SOFTWARE.
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## libjxl, JPEG XL conformance
|
|
255
|
+
|
|
256
|
+
The Modular decoding, the rendering pipeline, blending, the XYB conversion and the rendering of patches, splines and
|
|
257
|
+
noise follow libjxl, the JPEG XL reference implementation; tests/jxl includes files of its conformance suite. JPEG XL
|
|
258
|
+
is covered by Google's patent grant for libjxl (the "Additional IP Rights Grant" in libjxl's PATENTS file).
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
Copyright (c) the JPEG XL Project Authors.
|
|
262
|
+
All rights reserved.
|
|
263
|
+
|
|
264
|
+
Redistribution and use in source and binary forms, with or without
|
|
265
|
+
modification, are permitted provided that the following conditions are met:
|
|
266
|
+
|
|
267
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
268
|
+
list of conditions and the following disclaimer.
|
|
269
|
+
|
|
270
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
271
|
+
this list of conditions and the following disclaimer in the documentation
|
|
272
|
+
and/or other materials provided with the distribution.
|
|
273
|
+
|
|
274
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
275
|
+
contributors may be used to endorse or promote products derived from
|
|
276
|
+
this software without specific prior written permission.
|
|
277
|
+
|
|
278
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
279
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
280
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
281
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
282
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
283
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
284
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
285
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
286
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
287
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
288
|
+
```
|
|
289
|
+
|
|
147
290
|
## FreeType
|
|
148
291
|
|
|
149
292
|
Portions of this software are copyright © 2026 The FreeType Project (https://freetype.org). All rights reserved.
|
|
@@ -154,3 +297,156 @@ Where the specification leaves details open, its behavior and parts of its logic
|
|
|
154
297
|
interpolation of untouched points (IUP), the handling of near-perpendicular freedom and projection vectors, and the
|
|
155
298
|
tolerance of invalid references. FreeType is used under the FreeType License, included as
|
|
156
299
|
[licenses/FTL.txt](licenses/FTL.txt).
|
|
300
|
+
|
|
301
|
+
## QOI
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
MIT License
|
|
305
|
+
|
|
306
|
+
Copyright (c) 2021, 2022 Dominic Szablewski
|
|
307
|
+
|
|
308
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
309
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
310
|
+
in the Software without restriction, including without limitation the rights
|
|
311
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
312
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
313
|
+
furnished to do so, subject to the following conditions:
|
|
314
|
+
|
|
315
|
+
The above copyright notice and this permission notice shall be included in all
|
|
316
|
+
copies or substantial portions of the Software.
|
|
317
|
+
|
|
318
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
319
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
320
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
321
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
322
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
323
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
324
|
+
SOFTWARE.
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
## Pillow
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
The Python Imaging Library (PIL) is
|
|
331
|
+
|
|
332
|
+
Copyright © 1997-2011 by Secret Labs AB
|
|
333
|
+
Copyright © 1995-2011 by Fredrik Lundh and contributors
|
|
334
|
+
|
|
335
|
+
Pillow is the friendly PIL fork. It is
|
|
336
|
+
|
|
337
|
+
Copyright © 2010 by Jeffrey 'Alex' Clark and contributors
|
|
338
|
+
|
|
339
|
+
Like PIL, Pillow is licensed under the open source MIT-CMU License:
|
|
340
|
+
|
|
341
|
+
By obtaining, using, and/or copying this software and/or its associated
|
|
342
|
+
documentation, you agree that you have read, understood, and will comply
|
|
343
|
+
with the following terms and conditions:
|
|
344
|
+
|
|
345
|
+
Permission to use, copy, modify and distribute this software and its
|
|
346
|
+
documentation for any purpose and without fee is hereby granted,
|
|
347
|
+
provided that the above copyright notice appears in all copies, and that
|
|
348
|
+
both that copyright notice and this permission notice appear in supporting
|
|
349
|
+
documentation, and that the name of Secret Labs AB or the author not be
|
|
350
|
+
used in advertising or publicity pertaining to distribution of the software
|
|
351
|
+
without specific, written prior permission.
|
|
352
|
+
|
|
353
|
+
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
354
|
+
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
|
355
|
+
IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL,
|
|
356
|
+
INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
357
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
358
|
+
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
359
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
The resampling in `src/util/resample.ts` computes its filter coefficients as Pillow's `precompute_coeffs` does (the
|
|
363
|
+
filter stretched by the downscaling factor, the source range rounded around each output pixel's center, the weights
|
|
364
|
+
normalized) and uses Pillow's box, bilinear and bicubic (a = -0.5) filter functions. The integer passes, the fast
|
|
365
|
+
paths and the premultiplied alpha handling are ImageScript's own.
|
|
366
|
+
|
|
367
|
+
## Unicode Character Database
|
|
368
|
+
|
|
369
|
+
Copyright © 1991-2026 Unicode, Inc.
|
|
370
|
+
|
|
371
|
+
`src/render/unicode-data.ts` is generated by `scripts/unicode.js` from data files of the Unicode Character Database
|
|
372
|
+
(character properties for the bidirectional algorithm, line breaking, text segmentation and shaping). They are used
|
|
373
|
+
under the Unicode License v3, included as [licenses/Unicode-3.0.txt](licenses/Unicode-3.0.txt). The bidirectional
|
|
374
|
+
algorithm (`src/render/bidi.ts`) and the line breaking (`src/render/linebreak.ts`) are written after UAX #9 and
|
|
375
|
+
UAX #14.
|
|
376
|
+
|
|
377
|
+
## HarfBuzz
|
|
378
|
+
|
|
379
|
+
The shaping engine is ported from HarfBuzz 14.6.0; its license is included as
|
|
380
|
+
[licenses/HarfBuzz.txt](licenses/HarfBuzz.txt). The copyright holders of the ported files are listed in the headers
|
|
381
|
+
of the files derived from them.
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
HarfBuzz is licensed under the so-called "Old MIT" license. Details follow.
|
|
385
|
+
For parts of HarfBuzz that are licensed under different licenses see individual
|
|
386
|
+
files names COPYING in subdirectories where applicable.
|
|
387
|
+
|
|
388
|
+
Copyright © 2010-2022 Google, Inc.
|
|
389
|
+
Copyright © 2015-2020 Ebrahim Byagowi
|
|
390
|
+
Copyright © 2019,2020 Facebook, Inc.
|
|
391
|
+
Copyright © 2012,2015 Mozilla Foundation
|
|
392
|
+
Copyright © 2011 Codethink Limited
|
|
393
|
+
Copyright © 2008,2010 Nokia Corporation and/or its subsidiary(-ies)
|
|
394
|
+
Copyright © 2009 Keith Stribley
|
|
395
|
+
Copyright © 2011 Martin Hosken and SIL International
|
|
396
|
+
Copyright © 2007 Chris Wilson
|
|
397
|
+
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
|
398
|
+
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
|
399
|
+
Copyright © 1998-2005 David Turner and Werner Lemberg
|
|
400
|
+
Copyright © 2016 Igalia S.L.
|
|
401
|
+
Copyright © 2022 Matthias Clasen
|
|
402
|
+
Copyright © 2018,2021 Khaled Hosny
|
|
403
|
+
Copyright © 2018,2019,2020 Adobe, Inc
|
|
404
|
+
Copyright © 2013-2015 Alexei Podtelezhnikov
|
|
405
|
+
|
|
406
|
+
For full copyright notices consult the individual files in the package.
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
Permission is hereby granted, without written agreement and without
|
|
410
|
+
license or royalty fees, to use, copy, modify, and distribute this
|
|
411
|
+
software and its documentation for any purpose, provided that the
|
|
412
|
+
above copyright notice and the following two paragraphs appear in
|
|
413
|
+
all copies of this software.
|
|
414
|
+
|
|
415
|
+
IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
|
416
|
+
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
417
|
+
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
|
418
|
+
IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
|
419
|
+
DAMAGE.
|
|
420
|
+
|
|
421
|
+
THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
|
422
|
+
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
423
|
+
FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
|
424
|
+
ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
|
425
|
+
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
## Universal Shaping Engine data
|
|
429
|
+
|
|
430
|
+
```
|
|
431
|
+
MIT License
|
|
432
|
+
|
|
433
|
+
Copyright (c) Microsoft Corporation.
|
|
434
|
+
|
|
435
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
436
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
437
|
+
in the Software without restriction, including without limitation the rights
|
|
438
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
439
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
440
|
+
furnished to do so, subject to the following conditions:
|
|
441
|
+
|
|
442
|
+
The above copyright notice and this permission notice shall be included in all
|
|
443
|
+
copies or substantial portions of the Software.
|
|
444
|
+
|
|
445
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
446
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
447
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
448
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
449
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
450
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
451
|
+
SOFTWARE
|
|
452
|
+
```
|
package/dist/animation.d.ts
CHANGED
|
@@ -11,8 +11,14 @@ export interface AnimationOptions {
|
|
|
11
11
|
export interface AnimationDecodeOptions {
|
|
12
12
|
/** Whether to stop decoding after the first frame. Default: `false` */
|
|
13
13
|
onlyFirstFrame?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* The most pixels to decode, of all frames together (every frame is a full canvas): larger animations throw a
|
|
16
|
+
* RangeError before anything that size is allocated, so small files declaring huge animations (decompression
|
|
17
|
+
* bombs) can't exhaust the memory. Default: `268402689` (16383², like sharp), `Infinity` for no limit
|
|
18
|
+
*/
|
|
19
|
+
maxPixels?: number;
|
|
14
20
|
}
|
|
15
|
-
/**
|
|
21
|
+
/** The options all animation encoders have */
|
|
16
22
|
export interface AnimationEncodeOptions {
|
|
17
23
|
/** Metadata to include, see {@link Metadata} */
|
|
18
24
|
metadata?: Metadata;
|
|
@@ -23,6 +29,16 @@ export interface AnimationEncodeOptions {
|
|
|
23
29
|
*/
|
|
24
30
|
optimize?: boolean;
|
|
25
31
|
}
|
|
32
|
+
/** Options of {@link Animation.encodeWebP} */
|
|
33
|
+
export interface WebPAnimationEncodeOptions extends AnimationEncodeOptions {
|
|
34
|
+
/**
|
|
35
|
+
* Lossy frames (0-100, like libwebp's quality: 75 is its default), much smaller than lossless ones. Without it the
|
|
36
|
+
* frames are lossless
|
|
37
|
+
*/
|
|
38
|
+
quality?: number;
|
|
39
|
+
/** How much effort lossy frames take (0-6), see {@link WebPEncodeOptions.effort}. Default: `4` */
|
|
40
|
+
effort?: number;
|
|
41
|
+
}
|
|
26
42
|
/** Options of {@link Animation.encodeGIF} */
|
|
27
43
|
export interface GIFEncodeOptions extends AnimationEncodeOptions {
|
|
28
44
|
/** 1-100, scales the palette size from 8 colors (1) to 256 colors (90 and above). Default: `95` */
|
|
@@ -68,6 +84,7 @@ export declare class Animation extends Array<Frame> {
|
|
|
68
84
|
get height(): number;
|
|
69
85
|
/** The animation's duration (in ms) */
|
|
70
86
|
get duration(): number;
|
|
87
|
+
/** A short description for debugging, e.g. `Animation<64x64x1000ms>` */
|
|
71
88
|
toString(): string;
|
|
72
89
|
/**
|
|
73
90
|
* Returns a new animation of the same class containing a range of this one's frames
|
|
@@ -119,20 +136,20 @@ export declare class Animation extends Array<Frame> {
|
|
|
119
136
|
*/
|
|
120
137
|
encodeAPNG(compression?: number): Promise<Uint8Array>;
|
|
121
138
|
/**
|
|
122
|
-
* Encodes the animation as lossless
|
|
123
|
-
* before, identical frames are merged (unless the `optimize` option is false): the file
|
|
124
|
-
* animation, but doesn't necessarily decode to the same frames
|
|
125
|
-
* @param options See {@link
|
|
139
|
+
* Encodes the animation as animated WebP, lossless or (with a quality) lossy. Each frame is stored as the area that
|
|
140
|
+
* changed since the frame before, identical frames are merged (unless the `optimize` option is false): the file
|
|
141
|
+
* shows the same animation, but doesn't necessarily decode to the same frames
|
|
142
|
+
* @param options See {@link WebPAnimationEncodeOptions}
|
|
126
143
|
*/
|
|
127
|
-
encodeWebP({ metadata, optimize }?:
|
|
144
|
+
encodeWebP({ metadata, optimize, quality, effort }?: WebPAnimationEncodeOptions): Promise<Uint8Array>;
|
|
128
145
|
/**
|
|
129
|
-
* Decodes an animated GIF, APNG or
|
|
146
|
+
* Decodes an animated GIF, APNG, WebP or JPEG XL into fully composited frames (still images become a single frame)
|
|
130
147
|
* @param input The binary data to decode
|
|
131
148
|
* @param options See {@link AnimationDecodeOptions}
|
|
132
149
|
*/
|
|
133
150
|
static decode(input: BinaryData, options?: AnimationDecodeOptions): Promise<Animation>;
|
|
134
151
|
/**
|
|
135
|
-
* Decodes an animated GIF, APNG or
|
|
152
|
+
* Decodes an animated GIF, APNG, WebP or JPEG XL into fully composited frames (still images become a single frame)
|
|
136
153
|
* @param input The binary data to decode
|
|
137
154
|
* @param onlyExtractFirstFrame Whether to stop decoding after the first frame
|
|
138
155
|
*/
|
package/dist/animation.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as gifCodec from "./codecs/gif.js";
|
|
2
2
|
import * as png from "./codecs/png.js";
|
|
3
3
|
import * as webp from "./codecs/webp.js";
|
|
4
|
+
import * as jxl from "./codecs/jxl.js";
|
|
4
5
|
import { view } from "./util/mem.js";
|
|
5
6
|
import { Image } from "./image.js";
|
|
6
7
|
import { Frame } from "./frame.js";
|
|
7
8
|
import { ImageType } from "./image-type.js";
|
|
8
9
|
import { optimize } from "./util/optimize.js";
|
|
9
10
|
import { resolveMetadata, pngText, exifData, gifComments } from "./metadata.js";
|
|
10
|
-
import { isOptions } from "./util/options.js";
|
|
11
|
+
import { isOptions, finite } from "./util/options.js";
|
|
12
|
+
import { MAX_PIXELS, decoding } from "./util/limits.js";
|
|
11
13
|
const toPlays = (loopCount) => loopCount < 0 ? 0 : loopCount + 1;
|
|
12
14
|
const fromPlays = (plays) => plays === 0 ? -1 : plays - 1;
|
|
13
15
|
function canvasFrames(width, height, frames) {
|
|
@@ -27,7 +29,7 @@ export class Animation extends Array {
|
|
|
27
29
|
for (let i = 0; i < this.length; i++)
|
|
28
30
|
if (!(this[i] instanceof Frame))
|
|
29
31
|
throw new TypeError(`Frame ${i} is not an instance of Frame`);
|
|
30
|
-
if (loopCount < -1
|
|
32
|
+
if (finite(loopCount, 'loop count') < -1)
|
|
31
33
|
throw new RangeError('Invalid loop count');
|
|
32
34
|
this.loopCount = loopCount;
|
|
33
35
|
}
|
|
@@ -73,7 +75,6 @@ export class Animation extends Array {
|
|
|
73
75
|
return new Class(Array.prototype.slice.call(this, start, end), this.loopCount);
|
|
74
76
|
}
|
|
75
77
|
resize(width, height, modeOrOptions) {
|
|
76
|
-
const mode = (isOptions(modeOrOptions) ? modeOrOptions.mode : modeOrOptions) ?? Image.RESIZE_BILINEAR;
|
|
77
78
|
const originalWidth = this.width, originalHeight = this.height;
|
|
78
79
|
if (width === Image.RESIZE_AUTO && height === Image.RESIZE_AUTO)
|
|
79
80
|
throw new Error('RESIZE_AUTO can only be used for either width or height, not for both');
|
|
@@ -85,7 +86,7 @@ export class Animation extends Array {
|
|
|
85
86
|
for (const frame of this) {
|
|
86
87
|
const left = Math.round(frame.xOffset * sx), top = Math.round(frame.yOffset * sy);
|
|
87
88
|
const right = Math.round((frame.xOffset + frame.width) * sx), bottom = Math.round((frame.yOffset + frame.height) * sy);
|
|
88
|
-
Image.prototype.resize.call(frame, Math.max(1, right - left), Math.max(1, bottom - top),
|
|
89
|
+
Image.prototype.resize.call(frame, Math.max(1, right - left), Math.max(1, bottom - top), modeOrOptions);
|
|
89
90
|
frame.xOffset = left;
|
|
90
91
|
frame.yOffset = top;
|
|
91
92
|
}
|
|
@@ -123,12 +124,19 @@ export class Animation extends Array {
|
|
|
123
124
|
: this.__apngFrames__().map(({ blend: _, ...f }) => f);
|
|
124
125
|
return png.encodeAnimation(frames, this.width, this.height, toPlays(this.loopCount), compression, pngText(resolveMetadata(metadata)));
|
|
125
126
|
}
|
|
126
|
-
async encodeWebP({ metadata = {}, optimize = true } = {}) {
|
|
127
|
+
async encodeWebP({ metadata = {}, optimize = true, quality, effort = 4 } = {}) {
|
|
127
128
|
this.__validate__();
|
|
128
129
|
if (!this.length)
|
|
129
130
|
throw new Error('An animation needs at least one frame');
|
|
131
|
+
if (quality !== undefined) {
|
|
132
|
+
const q = finite(quality, 'quality');
|
|
133
|
+
if (q < 0 || q > 100)
|
|
134
|
+
throw new RangeError(`quality must be 0-100, not ${q}`);
|
|
135
|
+
if (!Number.isInteger(effort) || effort < 0 || effort > 6)
|
|
136
|
+
throw new RangeError(`effort must be an integer 0-6, not ${effort}`);
|
|
137
|
+
}
|
|
130
138
|
const frames = optimize ? this.__optimized__({ replace: true, even: true, alpha: 'frame' }) : this.__webpFrames__();
|
|
131
|
-
return webp.encodeAnimation(frames, this.width, this.height, toPlays(this.loopCount), exifData(resolveMetadata(metadata)));
|
|
139
|
+
return webp.encodeAnimation(frames, this.width, this.height, toPlays(this.loopCount), exifData(resolveMetadata(metadata)), quality, effort);
|
|
132
140
|
}
|
|
133
141
|
__webpFrames__() {
|
|
134
142
|
const width = this.width, height = this.height;
|
|
@@ -170,27 +178,50 @@ export class Animation extends Array {
|
|
|
170
178
|
}));
|
|
171
179
|
}
|
|
172
180
|
static async decode(input, onlyFirstFrameOrOptions = false) {
|
|
173
|
-
|
|
181
|
+
return decoding(() => Animation.__decode__(input, onlyFirstFrameOrOptions));
|
|
182
|
+
}
|
|
183
|
+
static async __decode__(input, onlyFirstFrameOrOptions) {
|
|
184
|
+
const { onlyFirstFrame: onlyExtractFirstFrame = false, maxPixels = MAX_PIXELS } = isOptions(onlyFirstFrameOrOptions) ? onlyFirstFrameOrOptions : { onlyFirstFrame: onlyFirstFrameOrOptions };
|
|
174
185
|
const data = view(input);
|
|
175
186
|
const type = ImageType.getType(data);
|
|
176
187
|
if (type === 'gif')
|
|
177
|
-
return Animation.__fromGIF__(data, onlyExtractFirstFrame, Animation);
|
|
188
|
+
return Animation.__fromGIF__(data, onlyExtractFirstFrame, Animation, maxPixels);
|
|
178
189
|
if (type === 'webp') {
|
|
179
|
-
const decoded = webp.decodeAnimation(data, onlyExtractFirstFrame);
|
|
190
|
+
const decoded = webp.decodeAnimation(data, onlyExtractFirstFrame, maxPixels);
|
|
180
191
|
const frames = canvasFrames(decoded.width, decoded.height, webp.composite(decoded));
|
|
181
192
|
return new Animation(frames, fromPlays(decoded.loopCount));
|
|
182
193
|
}
|
|
194
|
+
if (type === 'png' && !png.isAnimated(data)) {
|
|
195
|
+
const image = await Image.decode(data, { maxPixels, applyOrientation: false });
|
|
196
|
+
return new Animation(canvasFrames(image.width, image.height, [{ pixels: image.bitmap, duration: 0 }]), -1);
|
|
197
|
+
}
|
|
183
198
|
if (type === 'png') {
|
|
184
|
-
const decoded = await png.decodeAnimation(data, onlyExtractFirstFrame);
|
|
199
|
+
const decoded = await png.decodeAnimation(data, onlyExtractFirstFrame, maxPixels);
|
|
185
200
|
const frames = canvasFrames(decoded.width, decoded.height, png.compositeAnimation(decoded));
|
|
186
201
|
return new Animation(frames, decoded.frames.length > 1 ? fromPlays(decoded.plays) : -1);
|
|
187
202
|
}
|
|
203
|
+
if (type === 'jxl') {
|
|
204
|
+
const frames = [];
|
|
205
|
+
let loopCount = -1;
|
|
206
|
+
for (const decoded of jxl.frames(data, maxPixels)) {
|
|
207
|
+
const frame = new Frame(decoded.width, decoded.height, decoded.duration, 0, 0, Frame.DISPOSAL_BACKGROUND);
|
|
208
|
+
frame.bitmap = decoded.pixels;
|
|
209
|
+
frames.push(frame.__orient__(decoded.orientation));
|
|
210
|
+
loopCount = fromPlays(decoded.loopCount);
|
|
211
|
+
if (onlyExtractFirstFrame)
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
return new Animation(frames, frames.length > 1 ? loopCount : -1);
|
|
215
|
+
}
|
|
188
216
|
if (type)
|
|
189
|
-
return new Animation([Frame.from(await Image.decode(data), 0)]);
|
|
217
|
+
return new Animation([Frame.from(await Image.decode(data, { maxPixels }), 0)]);
|
|
190
218
|
throw new Error('Unsupported image type');
|
|
191
219
|
}
|
|
192
|
-
static __fromGIF__(data, onlyExtractFirstFrame, Class) {
|
|
193
|
-
|
|
220
|
+
static __fromGIF__(data, onlyExtractFirstFrame, Class, maxPixels = MAX_PIXELS) {
|
|
221
|
+
return decoding(() => Animation.__gifFrames__(data, onlyExtractFirstFrame, Class, maxPixels));
|
|
222
|
+
}
|
|
223
|
+
static __gifFrames__(data, onlyExtractFirstFrame, Class, maxPixels) {
|
|
224
|
+
const decoded = gifCodec.decode(data, onlyExtractFirstFrame, maxPixels);
|
|
194
225
|
const frames = gifCodec.composite(decoded).map(({ pixels, delay }) => ({ pixels, duration: 10 * delay }));
|
|
195
226
|
return new Class(canvasFrames(decoded.width, decoded.height, frames), decoded.loopCount);
|
|
196
227
|
}
|