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.
Files changed (105) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +292 -74
  3. package/esm/mod.d.ts +6 -4
  4. package/esm/mod.js +4 -2
  5. package/esm/src/formats/apng.d.ts +17 -5
  6. package/esm/src/formats/apng.js +104 -9
  7. package/esm/src/formats/ascii.d.ts +13 -3
  8. package/esm/src/formats/ascii.js +25 -1
  9. package/esm/src/formats/avif.d.ts +96 -0
  10. package/esm/src/formats/avif.js +607 -0
  11. package/esm/src/formats/bmp.d.ts +13 -3
  12. package/esm/src/formats/bmp.js +75 -2
  13. package/esm/src/formats/dng.d.ts +14 -2
  14. package/esm/src/formats/dng.js +27 -5
  15. package/esm/src/formats/gif.d.ts +18 -5
  16. package/esm/src/formats/gif.js +160 -14
  17. package/esm/src/formats/heic.d.ts +96 -0
  18. package/esm/src/formats/heic.js +608 -0
  19. package/esm/src/formats/ico.d.ts +13 -3
  20. package/esm/src/formats/ico.js +32 -4
  21. package/esm/src/formats/jpeg.d.ts +10 -3
  22. package/esm/src/formats/jpeg.js +99 -11
  23. package/esm/src/formats/pam.d.ts +13 -3
  24. package/esm/src/formats/pam.js +68 -2
  25. package/esm/src/formats/pcx.d.ts +13 -3
  26. package/esm/src/formats/pcx.js +47 -2
  27. package/esm/src/formats/png.d.ts +15 -3
  28. package/esm/src/formats/png.js +89 -2
  29. package/esm/src/formats/png_base.js +2 -5
  30. package/esm/src/formats/ppm.d.ts +13 -3
  31. package/esm/src/formats/ppm.js +36 -2
  32. package/esm/src/formats/tiff.d.ts +14 -18
  33. package/esm/src/formats/tiff.js +219 -20
  34. package/esm/src/formats/webp.d.ts +10 -3
  35. package/esm/src/formats/webp.js +103 -8
  36. package/esm/src/image.d.ts +20 -3
  37. package/esm/src/image.js +65 -21
  38. package/esm/src/types.d.ts +74 -4
  39. package/esm/src/utils/gif_decoder.d.ts +4 -1
  40. package/esm/src/utils/gif_decoder.js +91 -65
  41. package/esm/src/utils/image_processing.js +144 -70
  42. package/esm/src/utils/jpeg_decoder.d.ts +17 -4
  43. package/esm/src/utils/jpeg_decoder.js +448 -83
  44. package/esm/src/utils/jpeg_encoder.d.ts +15 -1
  45. package/esm/src/utils/jpeg_encoder.js +263 -24
  46. package/esm/src/utils/resize.js +51 -20
  47. package/esm/src/utils/tiff_deflate.d.ts +18 -0
  48. package/esm/src/utils/tiff_deflate.js +27 -0
  49. package/esm/src/utils/tiff_packbits.d.ts +24 -0
  50. package/esm/src/utils/tiff_packbits.js +90 -0
  51. package/esm/src/utils/webp_decoder.d.ts +3 -1
  52. package/esm/src/utils/webp_decoder.js +144 -63
  53. package/esm/src/utils/webp_encoder.js +5 -11
  54. package/package.json +18 -1
  55. package/script/mod.d.ts +6 -4
  56. package/script/mod.js +7 -3
  57. package/script/src/formats/apng.d.ts +17 -5
  58. package/script/src/formats/apng.js +104 -9
  59. package/script/src/formats/ascii.d.ts +13 -3
  60. package/script/src/formats/ascii.js +25 -1
  61. package/script/src/formats/avif.d.ts +96 -0
  62. package/script/src/formats/avif.js +611 -0
  63. package/script/src/formats/bmp.d.ts +13 -3
  64. package/script/src/formats/bmp.js +75 -2
  65. package/script/src/formats/dng.d.ts +14 -2
  66. package/script/src/formats/dng.js +27 -5
  67. package/script/src/formats/gif.d.ts +18 -5
  68. package/script/src/formats/gif.js +160 -14
  69. package/script/src/formats/heic.d.ts +96 -0
  70. package/script/src/formats/heic.js +612 -0
  71. package/script/src/formats/ico.d.ts +13 -3
  72. package/script/src/formats/ico.js +32 -4
  73. package/script/src/formats/jpeg.d.ts +10 -3
  74. package/script/src/formats/jpeg.js +99 -11
  75. package/script/src/formats/pam.d.ts +13 -3
  76. package/script/src/formats/pam.js +68 -2
  77. package/script/src/formats/pcx.d.ts +13 -3
  78. package/script/src/formats/pcx.js +47 -2
  79. package/script/src/formats/png.d.ts +15 -3
  80. package/script/src/formats/png.js +89 -2
  81. package/script/src/formats/png_base.js +2 -5
  82. package/script/src/formats/ppm.d.ts +13 -3
  83. package/script/src/formats/ppm.js +36 -2
  84. package/script/src/formats/tiff.d.ts +14 -18
  85. package/script/src/formats/tiff.js +219 -20
  86. package/script/src/formats/webp.d.ts +10 -3
  87. package/script/src/formats/webp.js +103 -8
  88. package/script/src/image.d.ts +20 -3
  89. package/script/src/image.js +64 -20
  90. package/script/src/types.d.ts +74 -4
  91. package/script/src/utils/gif_decoder.d.ts +4 -1
  92. package/script/src/utils/gif_decoder.js +91 -65
  93. package/script/src/utils/image_processing.js +144 -70
  94. package/script/src/utils/jpeg_decoder.d.ts +17 -4
  95. package/script/src/utils/jpeg_decoder.js +448 -83
  96. package/script/src/utils/jpeg_encoder.d.ts +15 -1
  97. package/script/src/utils/jpeg_encoder.js +263 -24
  98. package/script/src/utils/resize.js +51 -20
  99. package/script/src/utils/tiff_deflate.d.ts +18 -0
  100. package/script/src/utils/tiff_deflate.js +31 -0
  101. package/script/src/utils/tiff_packbits.d.ts +24 -0
  102. package/script/src/utils/tiff_packbits.js +94 -0
  103. package/script/src/utils/webp_decoder.d.ts +3 -1
  104. package/script/src/utils/webp_decoder.js +144 -63
  105. 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
- Deno, Node.js, and Bun. Decode, encode, manipulate, and process images in
5
- multiple formats including PNG, JPEG, WebP, GIF, and more—all without native
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
- PAM, PPM, PCX and ASCII support
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
- `contrast`, `saturation`, `hue`, `exposure`, `blur`, `sharpen`, `sepia`, and
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 "@cross/image";
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 | Notes |
108
- | ------ | ----------- | -------------------------------------- |
109
- | PNG | ✅ Full | Complete pure-JS implementation |
110
- | APNG | ✅ Full | Animated PNG with multi-frame |
111
- | BMP | ✅ Full | Complete pure-JS implementation |
112
- | ICO | ✅ Full | Windows Icon format |
113
- | GIF | ✅ Full | Animated GIF with multi-frame |
114
- | DNG | ✅ Full | Linear DNG (Uncompressed RGBA) |
115
- | PAM | ✅ Full | Netpbm PAM format |
116
- | PPM | ✅ Full | Netpbm PPM format (P3/P6) |
117
- | PCX | ✅ Full | ZSoft PCX (RLE compressed) |
118
- | ASCII | ✅ Full | Text-based ASCII art |
119
- | JPEG | ⚠️ Baseline | Pure-JS baseline DCT only |
120
- | WebP | ⚠️ Lossless | Pure-JS lossless VP8L |
121
- | TIFF | ⚠️ Basic | Pure-JS uncompressed, LZW, & grayscale |
122
-
123
- See the
124
- [full format support documentation](https://cross-image.56k.guru/formats/) for
125
- detailed compatibility information.
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
- image files, including camera information, GPS coordinates, and InteropIFD
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 "@cross/image";
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
- documentation
235
- - **[Format Support](https://cross-image.56k.guru/formats/)** - Supported
236
- formats and specifications
237
- - **[Image Processing](https://cross-image.56k.guru/processing/)** - Filters,
238
- manipulation, and color adjustments
239
- - [Filters](https://cross-image.56k.guru/processing/filters/) - Blur, sharpen,
240
- and noise reduction
241
- - [Manipulation](https://cross-image.56k.guru/processing/manipulation/) -
242
- Resize, crop, composite, and draw
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
- workflows and techniques
251
- - [Manipulation](https://cross-image.56k.guru/examples/manipulation/) -
252
- Resizing, cropping, and compositing
253
- - [Multi-Frame Images](https://cross-image.56k.guru/examples/multi-frame/) -
254
- Animated GIFs, APNGs, and TIFFs
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 test -A
495
+ deno task precommit
268
496
  ```
269
497
 
270
- ### Linting and Formatting
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 "@cross/image";
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 "@cross/image";
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 { ASCIIOptions, FrameMetadata, ImageData, ImageFormat, ImageFrame, ImageMetadata, MultiFrameImageData, ResizeOptions, WebPEncodeOptions, } from "./src/types.js";
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 { type TIFFEncodeOptions, TIFFFormat } from "./src/formats/tiff.js";
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 "@cross/image";
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 "@cross/image";
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