cross-image 0.2.3 → 0.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/LICENSE +21 -21
- package/README.md +292 -74
- package/esm/mod.d.ts +6 -4
- package/esm/mod.js +4 -2
- package/esm/src/formats/apng.d.ts +17 -5
- package/esm/src/formats/apng.js +104 -9
- package/esm/src/formats/ascii.d.ts +13 -3
- package/esm/src/formats/ascii.js +25 -1
- package/esm/src/formats/avif.d.ts +96 -0
- package/esm/src/formats/avif.js +607 -0
- package/esm/src/formats/bmp.d.ts +13 -3
- package/esm/src/formats/bmp.js +75 -2
- package/esm/src/formats/dng.d.ts +14 -2
- package/esm/src/formats/dng.js +27 -5
- package/esm/src/formats/gif.d.ts +18 -5
- package/esm/src/formats/gif.js +160 -14
- package/esm/src/formats/heic.d.ts +96 -0
- package/esm/src/formats/heic.js +608 -0
- package/esm/src/formats/ico.d.ts +13 -3
- package/esm/src/formats/ico.js +32 -4
- package/esm/src/formats/jpeg.d.ts +10 -3
- package/esm/src/formats/jpeg.js +99 -11
- package/esm/src/formats/pam.d.ts +13 -3
- package/esm/src/formats/pam.js +68 -2
- package/esm/src/formats/pcx.d.ts +13 -3
- package/esm/src/formats/pcx.js +47 -2
- package/esm/src/formats/png.d.ts +15 -3
- package/esm/src/formats/png.js +89 -2
- package/esm/src/formats/png_base.js +2 -5
- package/esm/src/formats/ppm.d.ts +13 -3
- package/esm/src/formats/ppm.js +36 -2
- package/esm/src/formats/tiff.d.ts +14 -18
- package/esm/src/formats/tiff.js +219 -20
- package/esm/src/formats/webp.d.ts +10 -3
- package/esm/src/formats/webp.js +103 -8
- package/esm/src/image.d.ts +20 -3
- package/esm/src/image.js +65 -21
- package/esm/src/types.d.ts +74 -4
- package/esm/src/utils/gif_decoder.d.ts +4 -1
- package/esm/src/utils/gif_decoder.js +91 -65
- package/esm/src/utils/image_processing.js +144 -70
- package/esm/src/utils/jpeg_decoder.d.ts +17 -4
- package/esm/src/utils/jpeg_decoder.js +448 -83
- package/esm/src/utils/jpeg_encoder.d.ts +15 -1
- package/esm/src/utils/jpeg_encoder.js +263 -24
- package/esm/src/utils/resize.js +51 -20
- package/esm/src/utils/tiff_deflate.d.ts +18 -0
- package/esm/src/utils/tiff_deflate.js +27 -0
- package/esm/src/utils/tiff_packbits.d.ts +24 -0
- package/esm/src/utils/tiff_packbits.js +90 -0
- package/esm/src/utils/webp_decoder.d.ts +3 -1
- package/esm/src/utils/webp_decoder.js +144 -63
- package/esm/src/utils/webp_encoder.js +5 -11
- package/package.json +18 -1
- package/script/mod.d.ts +6 -4
- package/script/mod.js +7 -3
- package/script/src/formats/apng.d.ts +17 -5
- package/script/src/formats/apng.js +104 -9
- package/script/src/formats/ascii.d.ts +13 -3
- package/script/src/formats/ascii.js +25 -1
- package/script/src/formats/avif.d.ts +96 -0
- package/script/src/formats/avif.js +611 -0
- package/script/src/formats/bmp.d.ts +13 -3
- package/script/src/formats/bmp.js +75 -2
- package/script/src/formats/dng.d.ts +14 -2
- package/script/src/formats/dng.js +27 -5
- package/script/src/formats/gif.d.ts +18 -5
- package/script/src/formats/gif.js +160 -14
- package/script/src/formats/heic.d.ts +96 -0
- package/script/src/formats/heic.js +612 -0
- package/script/src/formats/ico.d.ts +13 -3
- package/script/src/formats/ico.js +32 -4
- package/script/src/formats/jpeg.d.ts +10 -3
- package/script/src/formats/jpeg.js +99 -11
- package/script/src/formats/pam.d.ts +13 -3
- package/script/src/formats/pam.js +68 -2
- package/script/src/formats/pcx.d.ts +13 -3
- package/script/src/formats/pcx.js +47 -2
- package/script/src/formats/png.d.ts +15 -3
- package/script/src/formats/png.js +89 -2
- package/script/src/formats/png_base.js +2 -5
- package/script/src/formats/ppm.d.ts +13 -3
- package/script/src/formats/ppm.js +36 -2
- package/script/src/formats/tiff.d.ts +14 -18
- package/script/src/formats/tiff.js +219 -20
- package/script/src/formats/webp.d.ts +10 -3
- package/script/src/formats/webp.js +103 -8
- package/script/src/image.d.ts +20 -3
- package/script/src/image.js +64 -20
- package/script/src/types.d.ts +74 -4
- package/script/src/utils/gif_decoder.d.ts +4 -1
- package/script/src/utils/gif_decoder.js +91 -65
- package/script/src/utils/image_processing.js +144 -70
- package/script/src/utils/jpeg_decoder.d.ts +17 -4
- package/script/src/utils/jpeg_decoder.js +448 -83
- package/script/src/utils/jpeg_encoder.d.ts +15 -1
- package/script/src/utils/jpeg_encoder.js +263 -24
- package/script/src/utils/resize.js +51 -20
- package/script/src/utils/tiff_deflate.d.ts +18 -0
- package/script/src/utils/tiff_deflate.js +31 -0
- package/script/src/utils/tiff_packbits.d.ts +24 -0
- package/script/src/utils/tiff_packbits.js +94 -0
- package/script/src/utils/webp_decoder.d.ts +3 -1
- package/script/src/utils/webp_decoder.js +144 -63
- package/script/src/utils/webp_encoder.js +5 -11
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 @cross
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 @cross
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# @cross/image
|
|
2
2
|
|
|
3
|
-
A pure JavaScript, dependency-free, cross-runtime image processing library for
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
dependencies.
|
|
3
|
+
A pure JavaScript, dependency-free, cross-runtime image processing library for Deno, Node.js, and
|
|
4
|
+
Bun. Decode, encode, manipulate, and process images in multiple formats including PNG, JPEG, WebP,
|
|
5
|
+
GIF, and more—all without native dependencies.
|
|
7
6
|
|
|
8
7
|
📚 **[Full Documentation](https://cross-image.56k.guru/)**
|
|
9
8
|
|
|
@@ -12,12 +11,11 @@ dependencies.
|
|
|
12
11
|
- 🚀 **Pure JavaScript** - No native dependencies
|
|
13
12
|
- 🔌 **Pluggable formats** - Easy to extend with custom formats
|
|
14
13
|
- 📦 **Cross-runtime** - Works on Deno, Node.js (18+), and Bun
|
|
15
|
-
- 🎨 **Multiple formats** - PNG, APNG, JPEG, WebP, GIF, TIFF, BMP, ICO, DNG,
|
|
16
|
-
|
|
14
|
+
- 🎨 **Multiple formats** - PNG, APNG, JPEG, WebP, GIF, TIFF, BMP, ICO, DNG, PAM, PPM, PCX, ASCII,
|
|
15
|
+
HEIC, and AVIF support
|
|
17
16
|
- ✂️ **Image manipulation** - Resize, crop, composite, and more
|
|
18
|
-
- 🎛️ **Image processing** - Chainable filters including `brightness`,
|
|
19
|
-
`
|
|
20
|
-
more
|
|
17
|
+
- 🎛️ **Image processing** - Chainable filters including `brightness`, `contrast`, `saturation`,
|
|
18
|
+
`hue`, `exposure`, `blur`, `sharpen`, `sepia`, and more
|
|
21
19
|
- 🖌️ **Drawing operations** - Create, fill, and manipulate pixels
|
|
22
20
|
- 🧩 **Multi-frame** - Decode/encode animated GIFs, APNGs and multi-page TIFFs
|
|
23
21
|
- 🔧 **Simple API** - Easy to use, intuitive interface
|
|
@@ -55,7 +53,7 @@ import { Image } from "cross-image";
|
|
|
55
53
|
### Deno
|
|
56
54
|
|
|
57
55
|
```ts
|
|
58
|
-
import { Image } from "
|
|
56
|
+
import { Image } from "jsr:@cross/image";
|
|
59
57
|
|
|
60
58
|
// Decode an image (auto-detects format)
|
|
61
59
|
const data = await Deno.readFile("input.png");
|
|
@@ -102,33 +100,231 @@ const jpeg = await image.encode("jpeg");
|
|
|
102
100
|
await writeFile("output.jpg", jpeg);
|
|
103
101
|
```
|
|
104
102
|
|
|
103
|
+
### Bun
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { Image } from "cross-image";
|
|
107
|
+
|
|
108
|
+
// Read an image (auto-detects format)
|
|
109
|
+
const data = await Bun.file("input.png").arrayBuffer();
|
|
110
|
+
const image = await Image.decode(new Uint8Array(data));
|
|
111
|
+
|
|
112
|
+
console.log(`Image size: ${image.width}x${image.height}`);
|
|
113
|
+
|
|
114
|
+
// Resize the image and save
|
|
115
|
+
image.resize({ width: 800, height: 600 });
|
|
116
|
+
const jpeg = await image.encode("jpeg");
|
|
117
|
+
await Bun.write("output.jpg", jpeg);
|
|
118
|
+
```
|
|
119
|
+
|
|
105
120
|
## Supported Formats
|
|
106
121
|
|
|
107
|
-
| Format | Pure-JS
|
|
108
|
-
| ------ |
|
|
109
|
-
| PNG | ✅ Full
|
|
110
|
-
| APNG | ✅ Full
|
|
111
|
-
| BMP | ✅ Full
|
|
112
|
-
| ICO | ✅ Full
|
|
113
|
-
| GIF | ✅ Full
|
|
114
|
-
| DNG | ✅ Full
|
|
115
|
-
| PAM | ✅ Full
|
|
116
|
-
| PPM | ✅ Full
|
|
117
|
-
| PCX | ✅ Full
|
|
118
|
-
| ASCII | ✅ Full
|
|
119
|
-
| JPEG | ⚠️ Baseline | Pure-JS baseline DCT
|
|
120
|
-
| WebP | ⚠️ Lossless
|
|
121
|
-
| TIFF | ⚠️ Basic
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
| Format | Pure-JS | Notes |
|
|
123
|
+
| ------ | ------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
124
|
+
| PNG | ✅ Full | Complete pure-JS implementation |
|
|
125
|
+
| APNG | ✅ Full | Animated PNG with multi-frame |
|
|
126
|
+
| BMP | ✅ Full | Complete pure-JS implementation |
|
|
127
|
+
| ICO | ✅ Full | Windows Icon format |
|
|
128
|
+
| GIF | ✅ Full | Animated GIF with multi-frame |
|
|
129
|
+
| DNG | ✅ Full | Linear DNG (Uncompressed RGBA) |
|
|
130
|
+
| PAM | ✅ Full | Netpbm PAM format |
|
|
131
|
+
| PPM | ✅ Full | Netpbm PPM format (P3/P6) |
|
|
132
|
+
| PCX | ✅ Full | ZSoft PCX (RLE compressed) |
|
|
133
|
+
| ASCII | ✅ Full | Text-based ASCII art |
|
|
134
|
+
| JPEG | ⚠️ Baseline & Progressive | Pure-JS baseline & progressive DCT: decode with spectral selection; encode with 2-scan (DC+AC) |
|
|
135
|
+
| WebP | ⚠️ Lossless | Pure-JS lossless VP8L |
|
|
136
|
+
| TIFF | ⚠️ Basic | Pure-JS uncompressed, LZW, PackBits, & Deflate; grayscale & RGB/RGBA |
|
|
137
|
+
| HEIC | 🔌 Runtime | Requires ImageDecoder/OffscreenCanvas API support |
|
|
138
|
+
| AVIF | 🔌 Runtime | Requires ImageDecoder/OffscreenCanvas API support |
|
|
139
|
+
|
|
140
|
+
See the [full format support documentation](https://cross-image.56k.guru/formats/) for detailed
|
|
141
|
+
compatibility information.
|
|
142
|
+
|
|
143
|
+
## Advanced Usage
|
|
144
|
+
|
|
145
|
+
Most users should stick to the `Image` API (`Image.decode`, `image.encode`, etc.).
|
|
146
|
+
|
|
147
|
+
If you need to work with format handlers directly (e.g. `new PNGFormat()`) or register your own
|
|
148
|
+
`ImageFormat` implementation via `Image.registerFormat(...)`, see the API reference section
|
|
149
|
+
“Exported Format Classes”:
|
|
150
|
+
|
|
151
|
+
- https://cross-image.56k.guru/api/
|
|
152
|
+
|
|
153
|
+
## JPEG Tolerant Decoding
|
|
154
|
+
|
|
155
|
+
The JPEG decoder includes a tolerant decoding mode (enabled by default) that gracefully handles
|
|
156
|
+
partially corrupted images or complex encoding patterns from mobile phone cameras. When enabled, the
|
|
157
|
+
decoder will continue processing even if some blocks fail to decode, filling failed blocks with
|
|
158
|
+
neutral values.
|
|
159
|
+
|
|
160
|
+
**Features:**
|
|
161
|
+
|
|
162
|
+
- **Enabled by default** - Handles real-world JPEGs from various devices
|
|
163
|
+
- **Progressive JPEG support** - Decodes both baseline and progressive JPEGs
|
|
164
|
+
- **Configurable** - Can be disabled for strict validation
|
|
165
|
+
- **Fault-tolerant** - Recovers partial image data instead of failing completely
|
|
166
|
+
- **Zero configuration** - Works automatically with the standard `Image.decode()` API
|
|
167
|
+
|
|
168
|
+
**When to use:**
|
|
169
|
+
|
|
170
|
+
- Mobile phone JPEGs with complex encoding patterns
|
|
171
|
+
- Progressive JPEG images from web sources
|
|
172
|
+
- Images from various camera manufacturers
|
|
173
|
+
- Partially corrupted JPEG files
|
|
174
|
+
- Production applications requiring maximum compatibility
|
|
175
|
+
|
|
176
|
+
**Example:**
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { Image } from "jsr:@cross/image";
|
|
180
|
+
|
|
181
|
+
const data = await Deno.readFile("mobile-photo.jpg");
|
|
182
|
+
// Default behavior - tolerant decoding enabled
|
|
183
|
+
const image = await Image.decode(data);
|
|
184
|
+
|
|
185
|
+
// Strict mode - fail fast on decode errors
|
|
186
|
+
const strictImage = await Image.decode(data, { tolerantDecoding: false });
|
|
187
|
+
|
|
188
|
+
// Optional: receive warnings during partial decode (pure-JS decoder paths)
|
|
189
|
+
const imageWithWarnings = await Image.decode(data, {
|
|
190
|
+
tolerantDecoding: true,
|
|
191
|
+
runtimeDecoding: "never",
|
|
192
|
+
onWarning: (message, details) => {
|
|
193
|
+
console.log(`JPEG Warning: ${message}`, details);
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Note:** When using `Image.decode()`, the library automatically tries runtime-optimized decoders
|
|
199
|
+
(ImageDecoder API) first, falling back to the pure JS decoder with tolerant mode for maximum
|
|
200
|
+
compatibility.
|
|
201
|
+
|
|
202
|
+
## Fault-Tolerant Decoding for Other Formats
|
|
203
|
+
|
|
204
|
+
In addition to JPEG, @cross/image provides fault-tolerant decoding for several other formats that
|
|
205
|
+
commonly encounter corruption or complex encoding patterns:
|
|
206
|
+
|
|
207
|
+
### GIF Fault-Tolerant Decoding
|
|
208
|
+
|
|
209
|
+
The GIF decoder supports frame-level tolerance for animated GIFs. When enabled (default), corrupted
|
|
210
|
+
frames are skipped instead of causing complete decode failure.
|
|
211
|
+
|
|
212
|
+
**Features:**
|
|
213
|
+
|
|
214
|
+
- **Enabled by default** - Handles multi-frame GIFs with some corrupted frames
|
|
215
|
+
- **Frame-level recovery** - Skips bad frames, preserves good ones
|
|
216
|
+
- **LZW decompression errors** - Continues past compression errors
|
|
217
|
+
|
|
218
|
+
**Example:**
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import { Image } from "jsr:@cross/image";
|
|
222
|
+
|
|
223
|
+
const data = await Deno.readFile("animated.gif");
|
|
224
|
+
|
|
225
|
+
// Tolerant mode (default) - skips corrupted frames
|
|
226
|
+
const tolerantFrames = await Image.decodeFrames(data);
|
|
227
|
+
|
|
228
|
+
// Strict mode - throws on first corrupted frame
|
|
229
|
+
const strictFrames = await Image.decodeFrames(data, {
|
|
230
|
+
tolerantDecoding: false,
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
// Optional: receive warnings when frames are skipped
|
|
234
|
+
const framesWithWarnings = await Image.decodeFrames(data, {
|
|
235
|
+
tolerantDecoding: true,
|
|
236
|
+
runtimeDecoding: "never",
|
|
237
|
+
onWarning: (message, details) => {
|
|
238
|
+
console.log(`GIF Warning: ${message}`, details);
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### WebP Fault-Tolerant Decoding (VP8L Lossless)
|
|
244
|
+
|
|
245
|
+
The WebP VP8L (lossless) decoder supports pixel-level tolerance. When enabled (default), decoding
|
|
246
|
+
errors result in gray pixels for remaining data instead of complete failure.
|
|
247
|
+
|
|
248
|
+
**Features:**
|
|
249
|
+
|
|
250
|
+
- **Enabled by default** - Handles VP8L images with Huffman/LZ77 errors
|
|
251
|
+
- **Pixel-level recovery** - Fills remaining pixels with neutral gray
|
|
252
|
+
- **Huffman decode errors** - Continues past invalid codes
|
|
253
|
+
|
|
254
|
+
**Example:**
|
|
255
|
+
|
|
256
|
+
```typescript
|
|
257
|
+
import { Image } from "jsr:@cross/image";
|
|
258
|
+
|
|
259
|
+
const data = await Deno.readFile("image.webp");
|
|
260
|
+
|
|
261
|
+
// Tolerant mode (default) - fills bad pixels with gray
|
|
262
|
+
const tolerantImage = await Image.decode(data);
|
|
263
|
+
|
|
264
|
+
// Strict mode - throws on first decode error
|
|
265
|
+
const strictImage = await Image.decode(data, { tolerantDecoding: false });
|
|
266
|
+
|
|
267
|
+
// Optional: receive warnings during partial decode
|
|
268
|
+
const imageWithWarnings = await Image.decode(data, {
|
|
269
|
+
tolerantDecoding: true,
|
|
270
|
+
runtimeDecoding: "never",
|
|
271
|
+
onWarning: (message, details) => {
|
|
272
|
+
console.log(`WebP Warning: ${message}`, details);
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
void imageWithWarnings;
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### When to Use Fault-Tolerant Modes
|
|
279
|
+
|
|
280
|
+
**Use tolerant decoding (default) when:**
|
|
281
|
+
|
|
282
|
+
- Processing user-uploaded images from various sources
|
|
283
|
+
- Building production applications requiring maximum compatibility
|
|
284
|
+
- Handling images from mobile devices or cameras
|
|
285
|
+
- Recovering data from partially corrupted files
|
|
286
|
+
- Batch processing where some failures are acceptable
|
|
287
|
+
|
|
288
|
+
**Use strict decoding when:**
|
|
289
|
+
|
|
290
|
+
- Validating image file integrity
|
|
291
|
+
- Quality control in professional workflows
|
|
292
|
+
- Detecting file corruption explicitly
|
|
293
|
+
- Testing image encoder implementations
|
|
294
|
+
|
|
295
|
+
### Warning Callbacks
|
|
296
|
+
|
|
297
|
+
Decoding APIs accept an optional `onWarning` callback that gets invoked when non-fatal issues occur
|
|
298
|
+
during decoding. This is useful for logging, monitoring, or debugging decoding issues without using
|
|
299
|
+
`console` methods.
|
|
300
|
+
|
|
301
|
+
**Example:**
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
import { Image } from "jsr:@cross/image";
|
|
305
|
+
|
|
306
|
+
const data = await Deno.readFile("input.webp");
|
|
307
|
+
|
|
308
|
+
const image = await Image.decode(data, {
|
|
309
|
+
tolerantDecoding: true,
|
|
310
|
+
runtimeDecoding: "never",
|
|
311
|
+
onWarning: (message, details) => {
|
|
312
|
+
// Log to your preferred logging system
|
|
313
|
+
myLogger.warn(message, details);
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
void image;
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
The callback receives:
|
|
320
|
+
|
|
321
|
+
- `message`: A human-readable description of the warning
|
|
322
|
+
- `details`: Optional additional context (usually the error object)
|
|
126
323
|
|
|
127
324
|
## Metadata Support
|
|
128
325
|
|
|
129
|
-
@cross/image provides comprehensive EXIF 3.0 compliant metadata support for
|
|
130
|
-
|
|
131
|
-
compatibility markers.
|
|
326
|
+
@cross/image provides comprehensive EXIF 3.0 compliant metadata support for image files, including
|
|
327
|
+
camera information, GPS coordinates, and InteropIFD compatibility markers.
|
|
132
328
|
|
|
133
329
|
### Supported Metadata Fields
|
|
134
330
|
|
|
@@ -165,15 +361,14 @@ The library implements the EXIF 3.0 specification with:
|
|
|
165
361
|
|
|
166
362
|
- **50+ Exif Sub-IFD tags** for comprehensive camera metadata
|
|
167
363
|
- **30+ IFD0 tags** for image information
|
|
168
|
-
- **InteropIFD support** for format compatibility (R98/sRGB, R03/Adobe RGB,
|
|
169
|
-
THM/thumbnail)
|
|
364
|
+
- **InteropIFD support** for format compatibility (R98/sRGB, R03/Adobe RGB, THM/thumbnail)
|
|
170
365
|
- **GPS IFD** with proper coordinate conversion
|
|
171
366
|
- All EXIF data types (BYTE, ASCII, SHORT, LONG, RATIONAL, etc.)
|
|
172
367
|
|
|
173
368
|
### Example Usage
|
|
174
369
|
|
|
175
370
|
```typescript
|
|
176
|
-
import { Image } from "
|
|
371
|
+
import { Image } from "jsr:@cross/image";
|
|
177
372
|
|
|
178
373
|
// Load an image
|
|
179
374
|
const data = await Deno.readFile("photo.jpg");
|
|
@@ -208,6 +403,41 @@ console.log(loaded.metadata?.cameraMake); // "Canon"
|
|
|
208
403
|
console.log(loaded.getPosition()); // { latitude: 40.7128, longitude: -74.0060 }
|
|
209
404
|
```
|
|
210
405
|
|
|
406
|
+
### Extracting Metadata Without Decoding
|
|
407
|
+
|
|
408
|
+
For quickly reading metadata from images without the overhead of decoding pixel data, use
|
|
409
|
+
`Image.extractMetadata()`. This is particularly useful for:
|
|
410
|
+
|
|
411
|
+
- Reading EXIF data from large images or photos
|
|
412
|
+
- Extracting metadata from images with unsupported compression
|
|
413
|
+
- Building image catalogs or galleries
|
|
414
|
+
- Processing metadata in batch operations
|
|
415
|
+
|
|
416
|
+
```typescript
|
|
417
|
+
import { Image } from "jsr:@cross/image";
|
|
418
|
+
|
|
419
|
+
// Extract metadata without decoding pixels
|
|
420
|
+
const data = await Deno.readFile("large-photo.jpg");
|
|
421
|
+
const metadata = await Image.extractMetadata(data);
|
|
422
|
+
|
|
423
|
+
console.log(metadata?.cameraMake); // "Canon"
|
|
424
|
+
console.log(metadata?.iso); // 800
|
|
425
|
+
console.log(metadata?.exposureTime); // 0.004
|
|
426
|
+
|
|
427
|
+
// Works with auto-detection
|
|
428
|
+
const metadata2 = await Image.extractMetadata(data); // Detects JPEG
|
|
429
|
+
|
|
430
|
+
// Or specify format explicitly
|
|
431
|
+
const metadata3 = await Image.extractMetadata(data, "jpeg");
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
This method is significantly faster than full decode when you only need metadata, as it:
|
|
435
|
+
|
|
436
|
+
- Skips pixel data decompression
|
|
437
|
+
- Only parses metadata chunks/markers
|
|
438
|
+
- Returns `undefined` for unsupported formats
|
|
439
|
+
- Works with JPEG, PNG, WebP, TIFF, HEIC, and AVIF formats
|
|
440
|
+
|
|
211
441
|
### Format-Specific Support
|
|
212
442
|
|
|
213
443
|
Use `Image.getSupportedMetadata(format)` to check which fields are supported:
|
|
@@ -217,41 +447,41 @@ Image.getSupportedMetadata("jpeg"); // Full camera metadata + GPS (21 fields)
|
|
|
217
447
|
Image.getSupportedMetadata("tiff"); // Comprehensive EXIF + GPS + InteropIFD (23+ fields)
|
|
218
448
|
Image.getSupportedMetadata("png"); // DateTime, GPS, DPI, basic text (9 fields)
|
|
219
449
|
Image.getSupportedMetadata("webp"); // Enhanced XMP + GPS (15 fields - includes camera metadata!)
|
|
450
|
+
Image.getSupportedMetadata("heic"); // Full camera metadata + GPS (19 fields)
|
|
451
|
+
Image.getSupportedMetadata("avif"); // Full camera metadata + GPS (19 fields)
|
|
220
452
|
```
|
|
221
453
|
|
|
222
454
|
**Format Highlights:**
|
|
223
455
|
|
|
224
|
-
- **JPEG**: Most comprehensive EXIF support, including all camera settings and
|
|
225
|
-
GPS
|
|
456
|
+
- **JPEG**: Most comprehensive EXIF support, including all camera settings and GPS
|
|
226
457
|
- **TIFF**: Full EXIF 3.0 support with IFD structure, InteropIFD compatibility
|
|
227
|
-
- **WebP**: Enhanced XMP implementation with Dublin Core, EXIF, and TIFF
|
|
228
|
-
namespaces
|
|
458
|
+
- **WebP**: Enhanced XMP implementation with Dublin Core, EXIF, and TIFF namespaces
|
|
229
459
|
- **PNG**: Basic EXIF support via eXIf chunk plus GPS coordinates
|
|
460
|
+
- **HEIC**: Full EXIF metadata extraction including camera settings, GPS, and image info
|
|
461
|
+
(runtime-dependent encoding)
|
|
462
|
+
- **AVIF**: Full EXIF metadata extraction including camera settings, GPS, and image info
|
|
463
|
+
(runtime-dependent encoding)
|
|
230
464
|
|
|
231
465
|
## Documentation
|
|
232
466
|
|
|
233
|
-
- **[API Reference](https://cross-image.56k.guru/api/)** - Complete API
|
|
234
|
-
|
|
235
|
-
- **[
|
|
236
|
-
|
|
237
|
-
-
|
|
238
|
-
manipulation,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
- [Color Adjustments](https://cross-image.56k.guru/processing/color-adjustments/) -
|
|
244
|
-
Brightness, contrast, saturation, and more
|
|
245
|
-
- **[Examples](https://cross-image.56k.guru/examples/)** - Practical examples
|
|
246
|
-
for common tasks
|
|
467
|
+
- **[API Reference](https://cross-image.56k.guru/api/)** - Complete API documentation
|
|
468
|
+
- **[Format Support](https://cross-image.56k.guru/formats/)** - Supported formats and specifications
|
|
469
|
+
- **[Image Processing](https://cross-image.56k.guru/processing/)** - Filters, manipulation, and
|
|
470
|
+
color adjustments
|
|
471
|
+
- [Filters](https://cross-image.56k.guru/processing/filters/) - Blur, sharpen, and noise reduction
|
|
472
|
+
- [Manipulation](https://cross-image.56k.guru/processing/manipulation/) - Resize, crop, composite,
|
|
473
|
+
and draw
|
|
474
|
+
- [Color Adjustments](https://cross-image.56k.guru/processing/color-adjustments/) - Brightness,
|
|
475
|
+
contrast, saturation, and more
|
|
476
|
+
- **[Examples](https://cross-image.56k.guru/examples/)** - Practical examples for common tasks
|
|
247
477
|
- [Decoding & Encoding](https://cross-image.56k.guru/examples/decoding-encoding/) -
|
|
248
478
|
Format-specific examples
|
|
249
|
-
- [Using Filters](https://cross-image.56k.guru/examples/filters/) - Filter
|
|
250
|
-
|
|
251
|
-
- [Manipulation](https://cross-image.56k.guru/examples/manipulation/) -
|
|
252
|
-
|
|
253
|
-
- [Multi-Frame Images](https://cross-image.56k.guru/examples/multi-frame/) -
|
|
254
|
-
|
|
479
|
+
- [Using Filters](https://cross-image.56k.guru/examples/filters/) - Filter workflows and
|
|
480
|
+
techniques
|
|
481
|
+
- [Manipulation](https://cross-image.56k.guru/examples/manipulation/) - Resizing, cropping, and
|
|
482
|
+
compositing
|
|
483
|
+
- [Multi-Frame Images](https://cross-image.56k.guru/examples/multi-frame/) - Animated GIFs, APNGs,
|
|
484
|
+
and TIFFs
|
|
255
485
|
- **[JPEG Implementation](https://cross-image.56k.guru/implementation/jpeg-implementation/)** -
|
|
256
486
|
Technical details for JPEG
|
|
257
487
|
- **[WebP Implementation](https://cross-image.56k.guru/implementation/webp-implementation/)** -
|
|
@@ -261,24 +491,12 @@ Image.getSupportedMetadata("webp"); // Enhanced XMP + GPS (15 fields - includes
|
|
|
261
491
|
|
|
262
492
|
## Development
|
|
263
493
|
|
|
264
|
-
### Running Tests
|
|
265
|
-
|
|
266
494
|
```bash
|
|
267
|
-
deno
|
|
495
|
+
deno task precommit
|
|
268
496
|
```
|
|
269
497
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
```bash
|
|
273
|
-
deno fmt --check
|
|
274
|
-
deno lint
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### Type Checking
|
|
278
|
-
|
|
279
|
-
```bash
|
|
280
|
-
deno check mod.ts
|
|
281
|
-
```
|
|
498
|
+
CI validates cross-runtime compatibility (Deno, Bun, Node). See CONTRIBUTING.md for contributor
|
|
499
|
+
workflow details.
|
|
282
500
|
|
|
283
501
|
## License
|
|
284
502
|
|
package/esm/mod.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```ts
|
|
10
|
-
* import { Image } from "
|
|
10
|
+
* import { Image } from "jsr:@cross/image";
|
|
11
11
|
*
|
|
12
12
|
* // Decode an image
|
|
13
13
|
* const data = await Deno.readFile("input.png");
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* ```ts
|
|
29
|
-
* import { Image } from "
|
|
29
|
+
* import { Image } from "jsr:@cross/image";
|
|
30
30
|
*
|
|
31
31
|
* // Create a blank canvas
|
|
32
32
|
* const canvas = Image.create(400, 300, 255, 255, 255);
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
* ```
|
|
44
44
|
*/
|
|
45
45
|
export { Image } from "./src/image.js";
|
|
46
|
-
export type {
|
|
46
|
+
export type { ASCIIEncoderOptions, FrameMetadata, ImageData, ImageDecoderOptions, ImageFormat, ImageFrame, ImageMetadata, JPEGEncoderOptions, MultiFrameImageData, ResizeOptions, TIFFEncoderOptions, WebPEncoderOptions, } from "./src/types.js";
|
|
47
47
|
export { PNGFormat } from "./src/formats/png.js";
|
|
48
48
|
export { APNGFormat } from "./src/formats/apng.js";
|
|
49
49
|
export { JPEGFormat } from "./src/formats/jpeg.js";
|
|
50
50
|
export { WebPFormat } from "./src/formats/webp.js";
|
|
51
51
|
export { GIFFormat } from "./src/formats/gif.js";
|
|
52
|
-
export {
|
|
52
|
+
export { TIFFFormat } from "./src/formats/tiff.js";
|
|
53
53
|
export { BMPFormat } from "./src/formats/bmp.js";
|
|
54
54
|
export { ICOFormat } from "./src/formats/ico.js";
|
|
55
55
|
export { DNGFormat } from "./src/formats/dng.js";
|
|
@@ -57,4 +57,6 @@ export { PAMFormat } from "./src/formats/pam.js";
|
|
|
57
57
|
export { PCXFormat } from "./src/formats/pcx.js";
|
|
58
58
|
export { PPMFormat } from "./src/formats/ppm.js";
|
|
59
59
|
export { ASCIIFormat } from "./src/formats/ascii.js";
|
|
60
|
+
export { HEICFormat } from "./src/formats/heic.js";
|
|
61
|
+
export { AVIFFormat } from "./src/formats/avif.js";
|
|
60
62
|
//# sourceMappingURL=mod.d.ts.map
|
package/esm/mod.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```ts
|
|
10
|
-
* import { Image } from "
|
|
10
|
+
* import { Image } from "jsr:@cross/image";
|
|
11
11
|
*
|
|
12
12
|
* // Decode an image
|
|
13
13
|
* const data = await Deno.readFile("input.png");
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* ```ts
|
|
29
|
-
* import { Image } from "
|
|
29
|
+
* import { Image } from "jsr:@cross/image";
|
|
30
30
|
*
|
|
31
31
|
* // Create a blank canvas
|
|
32
32
|
* const canvas = Image.create(400, 300, 255, 255, 255);
|
|
@@ -56,3 +56,5 @@ export { PAMFormat } from "./src/formats/pam.js";
|
|
|
56
56
|
export { PCXFormat } from "./src/formats/pcx.js";
|
|
57
57
|
export { PPMFormat } from "./src/formats/ppm.js";
|
|
58
58
|
export { ASCIIFormat } from "./src/formats/ascii.js";
|
|
59
|
+
export { HEICFormat } from "./src/formats/heic.js";
|
|
60
|
+
export { AVIFFormat } from "./src/formats/avif.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImageData, ImageFormat, MultiFrameImageData } from "../types.js";
|
|
1
|
+
import type { ImageData, ImageDecoderOptions, ImageFormat, ImageMetadata, MultiFrameImageData } from "../types.js";
|
|
2
2
|
import { PNGBase } from "./png_base.js";
|
|
3
3
|
/**
|
|
4
4
|
* APNG (Animated PNG) format handler
|
|
@@ -26,25 +26,37 @@ export declare class APNGFormat extends PNGBase implements ImageFormat {
|
|
|
26
26
|
* @param data Raw APNG image data
|
|
27
27
|
* @returns Decoded image data with RGBA pixels of first frame
|
|
28
28
|
*/
|
|
29
|
-
decode(data: Uint8Array): Promise<ImageData>;
|
|
29
|
+
decode(data: Uint8Array, settings?: ImageDecoderOptions): Promise<ImageData>;
|
|
30
30
|
/**
|
|
31
31
|
* Decode all frames from APNG image
|
|
32
32
|
* @param data Raw APNG image data
|
|
33
33
|
* @returns Decoded multi-frame image data
|
|
34
34
|
*/
|
|
35
|
-
decodeFrames(data: Uint8Array): Promise<MultiFrameImageData>;
|
|
35
|
+
decodeFrames(data: Uint8Array, _settings?: ImageDecoderOptions): Promise<MultiFrameImageData>;
|
|
36
36
|
/**
|
|
37
37
|
* Encode RGBA image data to APNG format (single frame)
|
|
38
38
|
* @param imageData Image data to encode
|
|
39
39
|
* @returns Encoded APNG image bytes
|
|
40
40
|
*/
|
|
41
|
-
encode(imageData: ImageData): Promise<Uint8Array>;
|
|
41
|
+
encode(imageData: ImageData, _options?: unknown): Promise<Uint8Array>;
|
|
42
42
|
/**
|
|
43
43
|
* Encode multi-frame image data to APNG format
|
|
44
44
|
* @param imageData Multi-frame image data to encode
|
|
45
45
|
* @returns Encoded APNG image bytes
|
|
46
46
|
*/
|
|
47
|
-
encodeFrames(imageData: MultiFrameImageData): Promise<Uint8Array>;
|
|
47
|
+
encodeFrames(imageData: MultiFrameImageData, _options?: unknown): Promise<Uint8Array>;
|
|
48
48
|
private decodeFrameData;
|
|
49
|
+
/**
|
|
50
|
+
* Get the list of metadata fields supported by APNG format
|
|
51
|
+
* Includes all PNG fields plus frame count
|
|
52
|
+
*/
|
|
53
|
+
getSupportedMetadata(): Array<keyof ImageMetadata>;
|
|
54
|
+
/**
|
|
55
|
+
* Extract metadata from APNG data without fully decoding the pixel data
|
|
56
|
+
* This quickly parses PNG chunks to extract metadata including frame count
|
|
57
|
+
* @param data Raw APNG data
|
|
58
|
+
* @returns Extracted metadata or undefined
|
|
59
|
+
*/
|
|
60
|
+
extractMetadata(data: Uint8Array): Promise<ImageMetadata | undefined>;
|
|
49
61
|
}
|
|
50
62
|
//# sourceMappingURL=apng.d.ts.map
|