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/package.json CHANGED
@@ -1,20 +1,34 @@
1
1
  {
2
2
  "name": "cross-image",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "A pure JavaScript, dependency-free, cross-runtime image processing library for Deno, Node.js, and Bun.",
5
5
  "keywords": [
6
6
  "image",
7
7
  "image-processing",
8
+ "image-manipulation",
9
+ "image-resize",
10
+ "image-decode",
11
+ "image-encode",
8
12
  "png",
13
+ "apng",
9
14
  "jpeg",
10
15
  "webp",
11
16
  "gif",
12
17
  "tiff",
13
18
  "bmp",
19
+ "ico",
14
20
  "dng",
21
+ "heic",
22
+ "avif",
15
23
  "pam",
24
+ "ppm",
16
25
  "pcx",
26
+ "ascii-art",
27
+ "metadata",
28
+ "exif",
17
29
  "cross-runtime",
30
+ "pure-javascript",
31
+ "no-dependencies",
18
32
  "deno",
19
33
  "node",
20
34
  "bun"
@@ -37,5 +51,8 @@
37
51
  }
38
52
  },
39
53
  "scripts": {},
54
+ "engines": {
55
+ "node": ">=18.0.0"
56
+ },
40
57
  "_generatedBy": "dnt@dev"
41
58
  }
package/script/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/script/mod.js CHANGED
@@ -44,7 +44,7 @@
44
44
  * ```
45
45
  */
46
46
  Object.defineProperty(exports, "__esModule", { value: true });
47
- exports.ASCIIFormat = exports.PPMFormat = exports.PCXFormat = exports.PAMFormat = exports.DNGFormat = exports.ICOFormat = exports.BMPFormat = exports.TIFFFormat = exports.GIFFormat = exports.WebPFormat = exports.JPEGFormat = exports.APNGFormat = exports.PNGFormat = exports.Image = void 0;
47
+ exports.AVIFFormat = exports.HEICFormat = exports.ASCIIFormat = exports.PPMFormat = exports.PCXFormat = exports.PAMFormat = exports.DNGFormat = exports.ICOFormat = exports.BMPFormat = exports.TIFFFormat = exports.GIFFormat = exports.WebPFormat = exports.JPEGFormat = exports.APNGFormat = exports.PNGFormat = exports.Image = void 0;
48
48
  var image_js_1 = require("./src/image.js");
49
49
  Object.defineProperty(exports, "Image", { enumerable: true, get: function () { return image_js_1.Image; } });
50
50
  var png_js_1 = require("./src/formats/png.js");
@@ -73,3 +73,7 @@ var ppm_js_1 = require("./src/formats/ppm.js");
73
73
  Object.defineProperty(exports, "PPMFormat", { enumerable: true, get: function () { return ppm_js_1.PPMFormat; } });
74
74
  var ascii_js_1 = require("./src/formats/ascii.js");
75
75
  Object.defineProperty(exports, "ASCIIFormat", { enumerable: true, get: function () { return ascii_js_1.ASCIIFormat; } });
76
+ var heic_js_1 = require("./src/formats/heic.js");
77
+ Object.defineProperty(exports, "HEICFormat", { enumerable: true, get: function () { return heic_js_1.HEICFormat; } });
78
+ var avif_js_1 = require("./src/formats/avif.js");
79
+ Object.defineProperty(exports, "AVIFFormat", { enumerable: true, get: function () { return avif_js_1.AVIFFormat; } });
@@ -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
@@ -364,5 +364,102 @@ class APNGFormat extends png_base_js_1.PNGBase {
364
364
  const rgba = this.unfilterAndConvert(decompressed, width, height, bitDepth, colorType);
365
365
  return rgba;
366
366
  }
367
+ /**
368
+ * Get the list of metadata fields supported by APNG format
369
+ * Includes all PNG fields plus frame count
370
+ */
371
+ getSupportedMetadata() {
372
+ return [
373
+ ...super.getSupportedMetadata(),
374
+ "frameCount", // acTL chunk
375
+ ];
376
+ }
377
+ /**
378
+ * Extract metadata from APNG data without fully decoding the pixel data
379
+ * This quickly parses PNG chunks to extract metadata including frame count
380
+ * @param data Raw APNG data
381
+ * @returns Extracted metadata or undefined
382
+ */
383
+ extractMetadata(data) {
384
+ if (!this.canDecode(data)) {
385
+ return Promise.resolve(undefined);
386
+ }
387
+ let pos = 8; // Skip PNG signature
388
+ let width = 0;
389
+ let height = 0;
390
+ let frameCount = 0;
391
+ const metadata = {
392
+ format: "apng",
393
+ compression: "deflate",
394
+ };
395
+ // Parse chunks for metadata only
396
+ while (pos < data.length) {
397
+ if (pos + 8 > data.length)
398
+ break;
399
+ const length = this.readUint32(data, pos);
400
+ pos += 4;
401
+ const type = String.fromCharCode(data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
402
+ pos += 4;
403
+ if (pos + length + 4 > data.length)
404
+ break;
405
+ const chunkData = data.slice(pos, pos + length);
406
+ pos += length;
407
+ pos += 4; // Skip CRC
408
+ if (type === "IHDR") {
409
+ width = this.readUint32(chunkData, 0);
410
+ height = this.readUint32(chunkData, 4);
411
+ // Parse bit depth and color type from IHDR
412
+ if (chunkData.length >= 9) {
413
+ metadata.bitDepth = chunkData[8];
414
+ const colorTypeCode = chunkData[9];
415
+ // PNG color types: 0=grayscale, 2=rgb, 3=indexed, 4=grayscale+alpha, 6=rgba
416
+ switch (colorTypeCode) {
417
+ case 0:
418
+ metadata.colorType = "grayscale";
419
+ break;
420
+ case 2:
421
+ metadata.colorType = "rgb";
422
+ break;
423
+ case 3:
424
+ metadata.colorType = "indexed";
425
+ break;
426
+ case 4:
427
+ metadata.colorType = "grayscale-alpha";
428
+ break;
429
+ case 6:
430
+ metadata.colorType = "rgba";
431
+ break;
432
+ }
433
+ }
434
+ }
435
+ else if (type === "acTL") {
436
+ // Animation control chunk - contains frame count
437
+ if (chunkData.length >= 4) {
438
+ frameCount = this.readUint32(chunkData, 0);
439
+ metadata.frameCount = frameCount;
440
+ }
441
+ }
442
+ else if (type === "pHYs") {
443
+ // Physical pixel dimensions
444
+ this.parsePhysChunk(chunkData, metadata, width, height);
445
+ }
446
+ else if (type === "tEXt") {
447
+ // Text chunk
448
+ this.parseTextChunk(chunkData, metadata);
449
+ }
450
+ else if (type === "iTXt") {
451
+ // International text chunk
452
+ this.parseITxtChunk(chunkData, metadata);
453
+ }
454
+ else if (type === "eXIf") {
455
+ // EXIF chunk
456
+ this.parseExifChunk(chunkData, metadata);
457
+ }
458
+ else if (type === "IEND") {
459
+ break;
460
+ }
461
+ }
462
+ return Promise.resolve(Object.keys(metadata).length > 0 ? metadata : undefined);
463
+ }
367
464
  }
368
465
  exports.APNGFormat = APNGFormat;
@@ -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
@@ -186,5 +186,29 @@ class ASCIIFormat {
186
186
  }
187
187
  return options;
188
188
  }
189
+ /**
190
+ * Get the list of metadata fields supported by ASCII format
191
+ */
192
+ getSupportedMetadata() {
193
+ return []; // ASCII art doesn't support metadata preservation
194
+ }
195
+ /**
196
+ * Extract metadata from ASCII art data without fully decoding
197
+ * @param data Raw ASCII art data
198
+ * @returns Extracted metadata or undefined
199
+ */
200
+ extractMetadata(data) {
201
+ if (!this.canDecode(data)) {
202
+ return Promise.resolve(undefined);
203
+ }
204
+ const metadata = {
205
+ format: "ascii",
206
+ compression: "none",
207
+ frameCount: 1,
208
+ bitDepth: 1, // ASCII is 1-bit (character or no character)
209
+ colorType: "grayscale",
210
+ };
211
+ return Promise.resolve(metadata);
212
+ }
189
213
  }
190
214
  exports.ASCIIFormat = ASCIIFormat;
@@ -0,0 +1,96 @@
1
+ import type { ImageData, ImageFormat, ImageMetadata } from "../types.js";
2
+ /**
3
+ * AVIF format handler
4
+ * Supports AVIF images using runtime APIs (ImageDecoder/OffscreenCanvas)
5
+ * Note: Pure JavaScript encode/decode is not supported due to complexity
6
+ */
7
+ export declare class AVIFFormat implements ImageFormat {
8
+ /** Format name identifier */
9
+ readonly name = "avif";
10
+ /** MIME type for AVIF images */
11
+ readonly mimeType = "image/avif";
12
+ /**
13
+ * Check if the given data is an AVIF image
14
+ * @param data Raw image data to check
15
+ * @returns true if data has AVIF signature
16
+ */
17
+ canDecode(data: Uint8Array): boolean;
18
+ /**
19
+ * Decode AVIF image data to RGBA
20
+ * Uses runtime APIs (ImageDecoder) for decoding
21
+ * @param data Raw AVIF image data
22
+ * @returns Decoded image data with RGBA pixels
23
+ */
24
+ decode(data: Uint8Array): Promise<ImageData>;
25
+ /**
26
+ * Encode RGBA image data to AVIF format
27
+ * Uses runtime APIs (OffscreenCanvas) for encoding
28
+ *
29
+ * Note: Metadata injection is not currently implemented. Metadata may be lost during encoding
30
+ * as it would require parsing and modifying the ISOBMFF container structure.
31
+ *
32
+ * @param imageData Image data to encode
33
+ * @returns Encoded AVIF image bytes
34
+ */
35
+ encode(imageData: ImageData): Promise<Uint8Array>;
36
+ /**
37
+ * Decode using runtime APIs
38
+ * @param data Raw AVIF data
39
+ * @returns Decoded image dimensions and pixel data
40
+ */
41
+ private decodeUsingRuntime;
42
+ /**
43
+ * Parse EXIF metadata from AVIF data
44
+ *
45
+ * Note: This is a simplified implementation that searches for EXIF headers linearly.
46
+ * A full implementation would require navigating the ISOBMFF box structure to find
47
+ * the 'meta' box and then the 'Exif' item. This simplified approach may not work
48
+ * in all cases but is suitable for basic metadata extraction when runtime APIs are
49
+ * not available or as a fallback.
50
+ *
51
+ * @param data Raw AVIF data
52
+ * @param metadata Metadata object to populate
53
+ */
54
+ private parseEXIF;
55
+ /**
56
+ * Parse TIFF-formatted EXIF data
57
+ * @param data EXIF data in TIFF format
58
+ * @param metadata Metadata object to populate
59
+ */
60
+ private parseTIFFExif;
61
+ /**
62
+ * Parse Exif Sub-IFD for camera settings
63
+ * @param data EXIF data
64
+ * @param exifIfdOffset Offset to Exif Sub-IFD
65
+ * @param littleEndian Byte order
66
+ * @param metadata Metadata object to populate
67
+ */
68
+ private parseExifSubIFD;
69
+ /**
70
+ * Parse GPS IFD for location data
71
+ * @param data EXIF data
72
+ * @param gpsIfdOffset Offset to GPS IFD
73
+ * @param littleEndian Byte order
74
+ * @param metadata Metadata object to populate
75
+ */
76
+ private parseGPSIFD;
77
+ /**
78
+ * Read a rational value (numerator/denominator)
79
+ * @param data Data buffer
80
+ * @param offset Offset to rational
81
+ * @param littleEndian Byte order
82
+ * @returns Decimal value
83
+ */
84
+ private readRational;
85
+ /**
86
+ * Get the list of metadata fields supported by AVIF format
87
+ */
88
+ getSupportedMetadata(): Array<keyof ImageMetadata>;
89
+ /**
90
+ * Extract metadata from AVIF data without fully decoding the pixel data
91
+ * @param data Raw AVIF data
92
+ * @returns Extracted metadata or undefined
93
+ */
94
+ extractMetadata(data: Uint8Array): Promise<ImageMetadata | undefined>;
95
+ }
96
+ //# sourceMappingURL=avif.d.ts.map