cross-image 0.2.2 → 0.2.4

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 (88) hide show
  1. package/README.md +333 -168
  2. package/esm/mod.d.ts +2 -0
  3. package/esm/mod.js +2 -0
  4. package/esm/src/formats/apng.d.ts +13 -1
  5. package/esm/src/formats/apng.js +97 -0
  6. package/esm/src/formats/ascii.d.ts +11 -1
  7. package/esm/src/formats/ascii.js +24 -0
  8. package/esm/src/formats/avif.d.ts +96 -0
  9. package/esm/src/formats/avif.js +607 -0
  10. package/esm/src/formats/bmp.d.ts +11 -1
  11. package/esm/src/formats/bmp.js +73 -0
  12. package/esm/src/formats/dng.d.ts +13 -1
  13. package/esm/src/formats/dng.js +26 -4
  14. package/esm/src/formats/gif.d.ts +15 -2
  15. package/esm/src/formats/gif.js +146 -4
  16. package/esm/src/formats/heic.d.ts +96 -0
  17. package/esm/src/formats/heic.js +608 -0
  18. package/esm/src/formats/ico.d.ts +11 -1
  19. package/esm/src/formats/ico.js +28 -0
  20. package/esm/src/formats/jpeg.d.ts +19 -1
  21. package/esm/src/formats/jpeg.js +709 -4
  22. package/esm/src/formats/pam.d.ts +11 -1
  23. package/esm/src/formats/pam.js +66 -0
  24. package/esm/src/formats/pcx.d.ts +11 -1
  25. package/esm/src/formats/pcx.js +45 -0
  26. package/esm/src/formats/png.d.ts +13 -1
  27. package/esm/src/formats/png.js +87 -0
  28. package/esm/src/formats/png_base.d.ts +8 -0
  29. package/esm/src/formats/png_base.js +176 -3
  30. package/esm/src/formats/ppm.d.ts +11 -1
  31. package/esm/src/formats/ppm.js +34 -0
  32. package/esm/src/formats/tiff.d.ts +13 -1
  33. package/esm/src/formats/tiff.js +165 -0
  34. package/esm/src/formats/webp.d.ts +16 -2
  35. package/esm/src/formats/webp.js +303 -62
  36. package/esm/src/image.d.ts +60 -0
  37. package/esm/src/image.js +253 -5
  38. package/esm/src/types.d.ts +59 -1
  39. package/esm/src/utils/image_processing.d.ts +55 -0
  40. package/esm/src/utils/image_processing.js +210 -0
  41. package/esm/src/utils/metadata/xmp.d.ts +52 -0
  42. package/esm/src/utils/metadata/xmp.js +325 -0
  43. package/esm/src/utils/resize.d.ts +4 -0
  44. package/esm/src/utils/resize.js +74 -0
  45. package/package.json +18 -1
  46. package/script/mod.d.ts +2 -0
  47. package/script/mod.js +5 -1
  48. package/script/src/formats/apng.d.ts +13 -1
  49. package/script/src/formats/apng.js +97 -0
  50. package/script/src/formats/ascii.d.ts +11 -1
  51. package/script/src/formats/ascii.js +24 -0
  52. package/script/src/formats/avif.d.ts +96 -0
  53. package/script/src/formats/avif.js +611 -0
  54. package/script/src/formats/bmp.d.ts +11 -1
  55. package/script/src/formats/bmp.js +73 -0
  56. package/script/src/formats/dng.d.ts +13 -1
  57. package/script/src/formats/dng.js +26 -4
  58. package/script/src/formats/gif.d.ts +15 -2
  59. package/script/src/formats/gif.js +146 -4
  60. package/script/src/formats/heic.d.ts +96 -0
  61. package/script/src/formats/heic.js +612 -0
  62. package/script/src/formats/ico.d.ts +11 -1
  63. package/script/src/formats/ico.js +28 -0
  64. package/script/src/formats/jpeg.d.ts +19 -1
  65. package/script/src/formats/jpeg.js +709 -4
  66. package/script/src/formats/pam.d.ts +11 -1
  67. package/script/src/formats/pam.js +66 -0
  68. package/script/src/formats/pcx.d.ts +11 -1
  69. package/script/src/formats/pcx.js +45 -0
  70. package/script/src/formats/png.d.ts +13 -1
  71. package/script/src/formats/png.js +87 -0
  72. package/script/src/formats/png_base.d.ts +8 -0
  73. package/script/src/formats/png_base.js +176 -3
  74. package/script/src/formats/ppm.d.ts +11 -1
  75. package/script/src/formats/ppm.js +34 -0
  76. package/script/src/formats/tiff.d.ts +13 -1
  77. package/script/src/formats/tiff.js +165 -0
  78. package/script/src/formats/webp.d.ts +16 -2
  79. package/script/src/formats/webp.js +303 -62
  80. package/script/src/image.d.ts +60 -0
  81. package/script/src/image.js +251 -3
  82. package/script/src/types.d.ts +59 -1
  83. package/script/src/utils/image_processing.d.ts +55 -0
  84. package/script/src/utils/image_processing.js +216 -0
  85. package/script/src/utils/metadata/xmp.d.ts +52 -0
  86. package/script/src/utils/metadata/xmp.js +333 -0
  87. package/script/src/utils/resize.d.ts +4 -0
  88. package/script/src/utils/resize.js +75 -0
package/README.md CHANGED
@@ -1,168 +1,333 @@
1
- # @cross/image
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.
7
-
8
- 📚 **[Full Documentation](https://cross-image.56k.guru/)**
9
-
10
- ## Features
11
-
12
- - 🚀 **Pure JavaScript** - No native dependencies
13
- - 🔌 **Pluggable formats** - Easy to extend with custom formats
14
- - 📦 **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
17
- - ✂️ **Image manipulation** - Resize, crop, composite, and more
18
- - 🎛️ **Image processing** - Chainable filters including `brightness`,
19
- `contrast`, `saturation`, `exposure`, `blur`, `sharpen`, `sepia`, and more
20
- - 🖌️ **Drawing operations** - Create, fill, and manipulate pixels
21
- - 🧩 **Multi-frame** - Decode/encode animated GIFs, APNGs and multi-page TIFFs
22
- - 🔧 **Simple API** - Easy to use, intuitive interface
23
-
24
- ## Installation
25
-
26
- ### Deno
27
-
28
- ```ts
29
- import { Image } from "jsr:@cross/image";
30
- ```
31
-
32
- ### Node.js
33
-
34
- ```bash
35
- npx jsr add @cross/image
36
- ```
37
-
38
- ```ts
39
- import { Image } from "@cross/image";
40
- ```
41
-
42
- ### Bun
43
-
44
- ```bash
45
- bunx jsr add @cross/image
46
- ```
47
-
48
- ```ts
49
- import { Image } from "@cross/image";
50
- ```
51
-
52
- ## Quick Start
53
-
54
- ### Deno
55
-
56
- ```ts
57
- import { Image } from "@cross/image";
58
-
59
- // Decode an image (auto-detects format)
60
- const data = await Deno.readFile("input.png");
61
- const image = await Image.decode(data);
62
-
63
- console.log(`Image size: ${image.width}x${image.height}`);
64
-
65
- // Create a new blank image
66
- const canvas = Image.create(800, 600, 255, 255, 255); // white background
67
-
68
- // Composite the loaded image on top
69
- canvas.composite(image, 50, 50);
70
-
71
- // Apply image processing filters
72
- canvas
73
- .brightness(0.1)
74
- .contrast(0.2)
75
- .saturation(-0.1)
76
- .blur(1)
77
- .sharpen(0.3);
78
-
79
- // Encode in a different format
80
- const jpeg = await canvas.encode("jpeg");
81
- await Deno.writeFile("output.jpg", jpeg);
82
- ```
83
-
84
- ### Node.js
85
-
86
- ```ts
87
- import { Image } from "cross-image";
88
- import { readFile, writeFile } from "node:fs/promises";
89
-
90
- // Read an image (auto-detects format)
91
- const data = await readFile("input.png");
92
- const image = await Image.decode(data);
93
-
94
- console.log(`Image size: ${image.width}x${image.height}`);
95
-
96
- // Resize the image
97
- image.resize({ width: 800, height: 600 });
98
-
99
- // Save in a different format
100
- const jpeg = await image.encode("jpeg");
101
- await writeFile("output.jpg", jpeg);
102
- ```
103
-
104
- ## Supported Formats
105
-
106
- | Format | Pure-JS | Notes |
107
- | ------ | ----------- | -------------------------------------- |
108
- | PNG | Full | Complete pure-JS implementation |
109
- | APNG | ✅ Full | Animated PNG with multi-frame |
110
- | BMP | ✅ Full | Complete pure-JS implementation |
111
- | ICO | ✅ Full | Windows Icon format |
112
- | GIF | ✅ Full | Animated GIF with multi-frame |
113
- | DNG | ✅ Full | Linear DNG (Uncompressed RGBA) |
114
- | PAM | ✅ Full | Netpbm PAM format |
115
- | PPM | ✅ Full | Netpbm PPM format (P3/P6) |
116
- | PCX | ✅ Full | ZSoft PCX (RLE compressed) |
117
- | ASCII | ✅ Full | Text-based ASCII art |
118
- | JPEG | ⚠️ Baseline | Pure-JS baseline DCT only |
119
- | WebP | ⚠️ Lossless | Pure-JS lossless VP8L |
120
- | TIFF | ⚠️ Basic | Pure-JS uncompressed, LZW, & grayscale |
121
-
122
- See the
123
- [full format support documentation](https://cross-image.56k.guru/formats/) for
124
- detailed compatibility information.
125
-
126
- ## Documentation
127
-
128
- - **[API Reference](https://cross-image.56k.guru/api/)** - Complete API
129
- documentation
130
- - **[Examples](https://cross-image.56k.guru/examples/)** - Usage examples for
131
- common tasks
132
- - **[Format Support](https://cross-image.56k.guru/formats/)** - Supported
133
- formats and specifications
134
- - **[JPEG Implementation](https://cross-image.56k.guru/implementation/jpeg-implementation/)** -
135
- Technical details for JPEG
136
- - **[WebP Implementation](https://cross-image.56k.guru/implementation/webp-implementation/)** -
137
- Technical details for WebP
138
- - **[TIFF Implementation](https://cross-image.56k.guru/implementation/tiff-implementation/)** -
139
- Technical details for TIFF
140
-
141
- ## Development
142
-
143
- ### Running Tests
144
-
145
- ```bash
146
- deno test -A
147
- ```
148
-
149
- ### Linting and Formatting
150
-
151
- ```bash
152
- deno fmt --check
153
- deno lint
154
- ```
155
-
156
- ### Type Checking
157
-
158
- ```bash
159
- deno check mod.ts
160
- ```
161
-
162
- ## License
163
-
164
- MIT License - see LICENSE file for details.
165
-
166
- ## Contributing
167
-
168
- Contributions are welcome! Please feel free to submit a Pull Request.
1
+ # @cross/image
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.
7
+
8
+ 📚 **[Full Documentation](https://cross-image.56k.guru/)**
9
+
10
+ ## Features
11
+
12
+ - 🚀 **Pure JavaScript** - No native dependencies
13
+ - 🔌 **Pluggable formats** - Easy to extend with custom formats
14
+ - 📦 **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, ASCII, HEIC, and AVIF support
17
+ - ✂️ **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
21
+ - 🖌️ **Drawing operations** - Create, fill, and manipulate pixels
22
+ - 🧩 **Multi-frame** - Decode/encode animated GIFs, APNGs and multi-page TIFFs
23
+ - 🔧 **Simple API** - Easy to use, intuitive interface
24
+
25
+ ## Installation
26
+
27
+ ### Deno
28
+
29
+ ```ts
30
+ import { Image } from "jsr:@cross/image";
31
+ ```
32
+
33
+ ### Node.js
34
+
35
+ ```bash
36
+ npm install cross-image
37
+ ```
38
+
39
+ ```ts
40
+ import { Image } from "cross-image";
41
+ ```
42
+
43
+ ### Bun
44
+
45
+ ```bash
46
+ npm install cross-image
47
+ ```
48
+
49
+ ```ts
50
+ import { Image } from "cross-image";
51
+ ```
52
+
53
+ ## Quick Start
54
+
55
+ ### Deno
56
+
57
+ ```ts
58
+ import { Image } from "@cross/image";
59
+
60
+ // Decode an image (auto-detects format)
61
+ const data = await Deno.readFile("input.png");
62
+ const image = await Image.decode(data);
63
+
64
+ console.log(`Image size: ${image.width}x${image.height}`);
65
+
66
+ // Create a new blank image
67
+ const canvas = Image.create(800, 600, 255, 255, 255); // white background
68
+
69
+ // Composite the loaded image on top
70
+ canvas.composite(image, 50, 50);
71
+
72
+ // Apply image processing filters
73
+ canvas
74
+ .brightness(0.1)
75
+ .contrast(0.2)
76
+ .saturation(-0.1)
77
+ .blur(1)
78
+ .sharpen(0.3);
79
+
80
+ // Encode in a different format
81
+ const jpeg = await canvas.encode("jpeg");
82
+ await Deno.writeFile("output.jpg", jpeg);
83
+ ```
84
+
85
+ ### Node.js
86
+
87
+ ```ts
88
+ import { Image } from "cross-image";
89
+ import { readFile, writeFile } from "node:fs/promises";
90
+
91
+ // Read an image (auto-detects format)
92
+ const data = await readFile("input.png");
93
+ const image = await Image.decode(data);
94
+
95
+ console.log(`Image size: ${image.width}x${image.height}`);
96
+
97
+ // Resize the image
98
+ image.resize({ width: 800, height: 600 });
99
+
100
+ // Save in a different format
101
+ const jpeg = await image.encode("jpeg");
102
+ await writeFile("output.jpg", jpeg);
103
+ ```
104
+
105
+ ## Supported Formats
106
+
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
+ | HEIC | 🔌 Runtime | Requires ImageDecoder/OffscreenCanvas API support |
123
+ | AVIF | 🔌 Runtime | Requires ImageDecoder/OffscreenCanvas API support |
124
+
125
+ See the
126
+ [full format support documentation](https://cross-image.56k.guru/formats/) for
127
+ detailed compatibility information.
128
+
129
+ ## Metadata Support
130
+
131
+ @cross/image provides comprehensive EXIF 3.0 compliant metadata support for
132
+ image files, including camera information, GPS coordinates, and InteropIFD
133
+ compatibility markers.
134
+
135
+ ### Supported Metadata Fields
136
+
137
+ **Basic Metadata:**
138
+
139
+ - `title`, `description`, `author`, `copyright`
140
+ - `creationDate` - Date/time image was created
141
+
142
+ **Camera Settings (JPEG, TIFF, WebP via XMP):**
143
+
144
+ - `cameraMake`, `cameraModel` - Camera manufacturer and model
145
+ - `lensMake`, `lensModel` - Lens information
146
+ - `iso` - ISO speed rating
147
+ - `exposureTime` - Shutter speed in seconds
148
+ - `fNumber` - Aperture (f-number)
149
+ - `focalLength` - Focal length in mm
150
+ - `flash`, `whiteBalance` - Capture settings
151
+ - `orientation` - Image orientation (1=normal, 3=180°, 6=90°CW, 8=90°CCW)
152
+ - `software` - Software used
153
+ - `userComment` - User notes
154
+
155
+ **GPS Coordinates (All EXIF formats: JPEG, PNG, WebP, TIFF):**
156
+
157
+ - `latitude`, `longitude` - GPS coordinates in decimal degrees
158
+ - Full microsecond precision with DMS (degrees-minutes-seconds) conversion
159
+
160
+ **DPI (JPEG, PNG, TIFF):**
161
+
162
+ - `dpiX`, `dpiY` - Dots per inch for printing
163
+
164
+ ### EXIF 3.0 Specification Compliance
165
+
166
+ The library implements the EXIF 3.0 specification with:
167
+
168
+ - **50+ Exif Sub-IFD tags** for comprehensive camera metadata
169
+ - **30+ IFD0 tags** for image information
170
+ - **InteropIFD support** for format compatibility (R98/sRGB, R03/Adobe RGB,
171
+ THM/thumbnail)
172
+ - **GPS IFD** with proper coordinate conversion
173
+ - All EXIF data types (BYTE, ASCII, SHORT, LONG, RATIONAL, etc.)
174
+
175
+ ### Example Usage
176
+
177
+ ```typescript
178
+ import { Image } from "@cross/image";
179
+
180
+ // Load an image
181
+ const data = await Deno.readFile("photo.jpg");
182
+ const image = await Image.decode(data);
183
+
184
+ // Set metadata
185
+ image.setMetadata({
186
+ author: "Jane Photographer",
187
+ copyright: "© 2024",
188
+ cameraMake: "Canon",
189
+ cameraModel: "EOS R5",
190
+ iso: 800,
191
+ exposureTime: 0.004, // 1/250s
192
+ fNumber: 2.8,
193
+ focalLength: 50,
194
+ });
195
+
196
+ // Set GPS coordinates
197
+ image.setPosition(40.7128, -74.0060); // NYC
198
+
199
+ // Check what metadata a format supports
200
+ const jpegSupports = Image.getSupportedMetadata("jpeg");
201
+ console.log(jpegSupports); // Includes ISO, camera info, GPS, etc.
202
+
203
+ // Save with metadata
204
+ const jpeg = await image.save("jpeg");
205
+ await Deno.writeFile("output.jpg", jpeg);
206
+
207
+ // Metadata is preserved on reload!
208
+ const loaded = await Image.decode(jpeg);
209
+ console.log(loaded.metadata?.cameraMake); // "Canon"
210
+ console.log(loaded.getPosition()); // { latitude: 40.7128, longitude: -74.0060 }
211
+ ```
212
+
213
+ ### Extracting Metadata Without Decoding
214
+
215
+ For quickly reading metadata from images without the overhead of decoding pixel
216
+ data, use `Image.extractMetadata()`. This is particularly useful for:
217
+
218
+ - Reading EXIF data from large images or photos
219
+ - Extracting metadata from images with unsupported compression
220
+ - Building image catalogs or galleries
221
+ - Processing metadata in batch operations
222
+
223
+ ```typescript
224
+ import { Image } from "@cross/image";
225
+
226
+ // Extract metadata without decoding pixels
227
+ const data = await Deno.readFile("large-photo.jpg");
228
+ const metadata = await Image.extractMetadata(data);
229
+
230
+ console.log(metadata?.cameraMake); // "Canon"
231
+ console.log(metadata?.iso); // 800
232
+ console.log(metadata?.exposureTime); // 0.004
233
+
234
+ // Works with auto-detection
235
+ const metadata2 = await Image.extractMetadata(data); // Detects JPEG
236
+
237
+ // Or specify format explicitly
238
+ const metadata3 = await Image.extractMetadata(data, "jpeg");
239
+ ```
240
+
241
+ This method is significantly faster than full decode when you only need
242
+ metadata, as it:
243
+
244
+ - Skips pixel data decompression
245
+ - Only parses metadata chunks/markers
246
+ - Returns `undefined` for unsupported formats
247
+ - Works with JPEG, PNG, WebP, TIFF, HEIC, and AVIF formats
248
+
249
+ ### Format-Specific Support
250
+
251
+ Use `Image.getSupportedMetadata(format)` to check which fields are supported:
252
+
253
+ ```typescript
254
+ Image.getSupportedMetadata("jpeg"); // Full camera metadata + GPS (21 fields)
255
+ Image.getSupportedMetadata("tiff"); // Comprehensive EXIF + GPS + InteropIFD (23+ fields)
256
+ Image.getSupportedMetadata("png"); // DateTime, GPS, DPI, basic text (9 fields)
257
+ Image.getSupportedMetadata("webp"); // Enhanced XMP + GPS (15 fields - includes camera metadata!)
258
+ Image.getSupportedMetadata("heic"); // Full camera metadata + GPS (19 fields)
259
+ Image.getSupportedMetadata("avif"); // Full camera metadata + GPS (19 fields)
260
+ ```
261
+
262
+ **Format Highlights:**
263
+
264
+ - **JPEG**: Most comprehensive EXIF support, including all camera settings and
265
+ GPS
266
+ - **TIFF**: Full EXIF 3.0 support with IFD structure, InteropIFD compatibility
267
+ - **WebP**: Enhanced XMP implementation with Dublin Core, EXIF, and TIFF
268
+ namespaces
269
+ - **PNG**: Basic EXIF support via eXIf chunk plus GPS coordinates
270
+ - **HEIC**: Full EXIF metadata extraction including camera settings, GPS, and
271
+ image info (runtime-dependent encoding)
272
+ - **AVIF**: Full EXIF metadata extraction including camera settings, GPS, and
273
+ image info (runtime-dependent encoding)
274
+
275
+ ## Documentation
276
+
277
+ - **[API Reference](https://cross-image.56k.guru/api/)** - Complete API
278
+ documentation
279
+ - **[Format Support](https://cross-image.56k.guru/formats/)** - Supported
280
+ formats and specifications
281
+ - **[Image Processing](https://cross-image.56k.guru/processing/)** - Filters,
282
+ manipulation, and color adjustments
283
+ - [Filters](https://cross-image.56k.guru/processing/filters/) - Blur, sharpen,
284
+ and noise reduction
285
+ - [Manipulation](https://cross-image.56k.guru/processing/manipulation/) -
286
+ Resize, crop, composite, and draw
287
+ - [Color Adjustments](https://cross-image.56k.guru/processing/color-adjustments/) -
288
+ Brightness, contrast, saturation, and more
289
+ - **[Examples](https://cross-image.56k.guru/examples/)** - Practical examples
290
+ for common tasks
291
+ - [Decoding & Encoding](https://cross-image.56k.guru/examples/decoding-encoding/) -
292
+ Format-specific examples
293
+ - [Using Filters](https://cross-image.56k.guru/examples/filters/) - Filter
294
+ workflows and techniques
295
+ - [Manipulation](https://cross-image.56k.guru/examples/manipulation/) -
296
+ Resizing, cropping, and compositing
297
+ - [Multi-Frame Images](https://cross-image.56k.guru/examples/multi-frame/) -
298
+ Animated GIFs, APNGs, and TIFFs
299
+ - **[JPEG Implementation](https://cross-image.56k.guru/implementation/jpeg-implementation/)** -
300
+ Technical details for JPEG
301
+ - **[WebP Implementation](https://cross-image.56k.guru/implementation/webp-implementation/)** -
302
+ Technical details for WebP
303
+ - **[TIFF Implementation](https://cross-image.56k.guru/implementation/tiff-implementation/)** -
304
+ Technical details for TIFF
305
+
306
+ ## Development
307
+
308
+ ### Running Tests
309
+
310
+ ```bash
311
+ deno test -A
312
+ ```
313
+
314
+ ### Linting and Formatting
315
+
316
+ ```bash
317
+ deno fmt --check
318
+ deno lint
319
+ ```
320
+
321
+ ### Type Checking
322
+
323
+ ```bash
324
+ deno check mod.ts
325
+ ```
326
+
327
+ ## License
328
+
329
+ MIT License - see LICENSE file for details.
330
+
331
+ ## Contributing
332
+
333
+ Contributions are welcome! Please feel free to submit a Pull Request.
package/esm/mod.d.ts CHANGED
@@ -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
@@ -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, ImageFormat, ImageMetadata, MultiFrameImageData } from "../types.js";
2
2
  import { PNGBase } from "./png_base.js";
3
3
  /**
4
4
  * APNG (Animated PNG) format handler
@@ -46,5 +46,17 @@ export declare class APNGFormat extends PNGBase implements ImageFormat {
46
46
  */
47
47
  encodeFrames(imageData: MultiFrameImageData): 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
@@ -361,4 +361,101 @@ export class APNGFormat extends PNGBase {
361
361
  const rgba = this.unfilterAndConvert(decompressed, width, height, bitDepth, colorType);
362
362
  return rgba;
363
363
  }
364
+ /**
365
+ * Get the list of metadata fields supported by APNG format
366
+ * Includes all PNG fields plus frame count
367
+ */
368
+ getSupportedMetadata() {
369
+ return [
370
+ ...super.getSupportedMetadata(),
371
+ "frameCount", // acTL chunk
372
+ ];
373
+ }
374
+ /**
375
+ * Extract metadata from APNG data without fully decoding the pixel data
376
+ * This quickly parses PNG chunks to extract metadata including frame count
377
+ * @param data Raw APNG data
378
+ * @returns Extracted metadata or undefined
379
+ */
380
+ extractMetadata(data) {
381
+ if (!this.canDecode(data)) {
382
+ return Promise.resolve(undefined);
383
+ }
384
+ let pos = 8; // Skip PNG signature
385
+ let width = 0;
386
+ let height = 0;
387
+ let frameCount = 0;
388
+ const metadata = {
389
+ format: "apng",
390
+ compression: "deflate",
391
+ };
392
+ // Parse chunks for metadata only
393
+ while (pos < data.length) {
394
+ if (pos + 8 > data.length)
395
+ break;
396
+ const length = this.readUint32(data, pos);
397
+ pos += 4;
398
+ const type = String.fromCharCode(data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
399
+ pos += 4;
400
+ if (pos + length + 4 > data.length)
401
+ break;
402
+ const chunkData = data.slice(pos, pos + length);
403
+ pos += length;
404
+ pos += 4; // Skip CRC
405
+ if (type === "IHDR") {
406
+ width = this.readUint32(chunkData, 0);
407
+ height = this.readUint32(chunkData, 4);
408
+ // Parse bit depth and color type from IHDR
409
+ if (chunkData.length >= 9) {
410
+ metadata.bitDepth = chunkData[8];
411
+ const colorTypeCode = chunkData[9];
412
+ // PNG color types: 0=grayscale, 2=rgb, 3=indexed, 4=grayscale+alpha, 6=rgba
413
+ switch (colorTypeCode) {
414
+ case 0:
415
+ metadata.colorType = "grayscale";
416
+ break;
417
+ case 2:
418
+ metadata.colorType = "rgb";
419
+ break;
420
+ case 3:
421
+ metadata.colorType = "indexed";
422
+ break;
423
+ case 4:
424
+ metadata.colorType = "grayscale-alpha";
425
+ break;
426
+ case 6:
427
+ metadata.colorType = "rgba";
428
+ break;
429
+ }
430
+ }
431
+ }
432
+ else if (type === "acTL") {
433
+ // Animation control chunk - contains frame count
434
+ if (chunkData.length >= 4) {
435
+ frameCount = this.readUint32(chunkData, 0);
436
+ metadata.frameCount = frameCount;
437
+ }
438
+ }
439
+ else if (type === "pHYs") {
440
+ // Physical pixel dimensions
441
+ this.parsePhysChunk(chunkData, metadata, width, height);
442
+ }
443
+ else if (type === "tEXt") {
444
+ // Text chunk
445
+ this.parseTextChunk(chunkData, metadata);
446
+ }
447
+ else if (type === "iTXt") {
448
+ // International text chunk
449
+ this.parseITxtChunk(chunkData, metadata);
450
+ }
451
+ else if (type === "eXIf") {
452
+ // EXIF chunk
453
+ this.parseExifChunk(chunkData, metadata);
454
+ }
455
+ else if (type === "IEND") {
456
+ break;
457
+ }
458
+ }
459
+ return Promise.resolve(Object.keys(metadata).length > 0 ? metadata : undefined);
460
+ }
364
461
  }
@@ -1,4 +1,4 @@
1
- import type { ASCIIOptions, ImageData, ImageFormat } from "../types.js";
1
+ import type { ASCIIOptions, ImageData, ImageFormat, ImageMetadata } from "../types.js";
2
2
  /**
3
3
  * ASCII format handler
4
4
  * Converts images to ASCII art text representation
@@ -34,5 +34,15 @@ export declare class ASCIIFormat implements ImageFormat {
34
34
  * Parse options from the options line
35
35
  */
36
36
  private parseOptions;
37
+ /**
38
+ * Get the list of metadata fields supported by ASCII format
39
+ */
40
+ getSupportedMetadata(): Array<keyof ImageMetadata>;
41
+ /**
42
+ * Extract metadata from ASCII art data without fully decoding
43
+ * @param data Raw ASCII art data
44
+ * @returns Extracted metadata or undefined
45
+ */
46
+ extractMetadata(data: Uint8Array): Promise<ImageMetadata | undefined>;
37
47
  }
38
48
  //# sourceMappingURL=ascii.d.ts.map