cross-image 0.2.3 → 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 (72) hide show
  1. package/README.md +333 -289
  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 +7 -0
  21. package/esm/src/formats/jpeg.js +76 -0
  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/ppm.d.ts +11 -1
  29. package/esm/src/formats/ppm.js +34 -0
  30. package/esm/src/formats/tiff.d.ts +7 -0
  31. package/esm/src/formats/tiff.js +134 -0
  32. package/esm/src/formats/webp.d.ts +7 -0
  33. package/esm/src/formats/webp.js +92 -0
  34. package/esm/src/image.d.ts +9 -0
  35. package/esm/src/image.js +28 -0
  36. package/esm/src/types.d.ts +18 -0
  37. package/package.json +18 -1
  38. package/script/mod.d.ts +2 -0
  39. package/script/mod.js +5 -1
  40. package/script/src/formats/apng.d.ts +13 -1
  41. package/script/src/formats/apng.js +97 -0
  42. package/script/src/formats/ascii.d.ts +11 -1
  43. package/script/src/formats/ascii.js +24 -0
  44. package/script/src/formats/avif.d.ts +96 -0
  45. package/script/src/formats/avif.js +611 -0
  46. package/script/src/formats/bmp.d.ts +11 -1
  47. package/script/src/formats/bmp.js +73 -0
  48. package/script/src/formats/dng.d.ts +13 -1
  49. package/script/src/formats/dng.js +26 -4
  50. package/script/src/formats/gif.d.ts +15 -2
  51. package/script/src/formats/gif.js +146 -4
  52. package/script/src/formats/heic.d.ts +96 -0
  53. package/script/src/formats/heic.js +612 -0
  54. package/script/src/formats/ico.d.ts +11 -1
  55. package/script/src/formats/ico.js +28 -0
  56. package/script/src/formats/jpeg.d.ts +7 -0
  57. package/script/src/formats/jpeg.js +76 -0
  58. package/script/src/formats/pam.d.ts +11 -1
  59. package/script/src/formats/pam.js +66 -0
  60. package/script/src/formats/pcx.d.ts +11 -1
  61. package/script/src/formats/pcx.js +45 -0
  62. package/script/src/formats/png.d.ts +13 -1
  63. package/script/src/formats/png.js +87 -0
  64. package/script/src/formats/ppm.d.ts +11 -1
  65. package/script/src/formats/ppm.js +34 -0
  66. package/script/src/formats/tiff.d.ts +7 -0
  67. package/script/src/formats/tiff.js +134 -0
  68. package/script/src/formats/webp.d.ts +7 -0
  69. package/script/src/formats/webp.js +92 -0
  70. package/script/src/image.d.ts +9 -0
  71. package/script/src/image.js +28 -0
  72. package/script/src/types.d.ts +18 -0
@@ -603,5 +603,97 @@ class WebPFormat {
603
603
  "focalLength",
604
604
  ];
605
605
  }
606
+ /**
607
+ * Extract metadata from WebP data without fully decoding the pixel data
608
+ * This quickly parses RIFF chunks to extract EXIF and XMP metadata
609
+ * @param data Raw WebP data
610
+ * @returns Extracted metadata or undefined
611
+ */
612
+ extractMetadata(data) {
613
+ if (!this.canDecode(data)) {
614
+ return Promise.resolve(undefined);
615
+ }
616
+ const metadata = {
617
+ format: "webp",
618
+ frameCount: 1,
619
+ bitDepth: 8,
620
+ };
621
+ let pos = 12; // Skip "RIFF" + size + "WEBP"
622
+ const readUint32LE = (data, offset) => {
623
+ return data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) |
624
+ (data[offset + 3] << 24);
625
+ };
626
+ const readUint16LE = (data, offset) => {
627
+ return data[offset] | (data[offset + 1] << 8);
628
+ };
629
+ // Parse chunks for metadata
630
+ while (pos + 8 <= data.length) {
631
+ const chunkType = String.fromCharCode(data[pos], data[pos + 1], data[pos + 2], data[pos + 3]);
632
+ const chunkSize = readUint32LE(data, pos + 4);
633
+ pos += 8;
634
+ // Stop if we've gone past the end
635
+ if (pos + chunkSize > data.length)
636
+ break;
637
+ const chunkData = data.slice(pos, pos + chunkSize);
638
+ if (chunkType === "VP8 ") {
639
+ // Lossy VP8 chunk
640
+ metadata.compression = "vp8";
641
+ metadata.colorType = "rgb";
642
+ }
643
+ else if (chunkType === "VP8L") {
644
+ // Lossless VP8L chunk
645
+ metadata.compression = "vp8l";
646
+ metadata.colorType = "rgba";
647
+ }
648
+ else if (chunkType === "VP8X") {
649
+ // Extended format chunk - contains animation info
650
+ if (chunkData.length >= 10) {
651
+ const flags = chunkData[0];
652
+ const _hasAnimation = (flags & 0x02) !== 0;
653
+ const hasAlpha = (flags & 0x10) !== 0;
654
+ if (hasAlpha) {
655
+ metadata.colorType = "rgba";
656
+ }
657
+ else {
658
+ metadata.colorType = "rgb";
659
+ }
660
+ // Animation is handled in ANIM chunk
661
+ }
662
+ }
663
+ else if (chunkType === "ANIM") {
664
+ // Animation parameters chunk
665
+ if (chunkData.length >= 6) {
666
+ // Background color at bytes 0-3
667
+ // Loop count at bytes 4-5
668
+ const _loopCount = readUint16LE(chunkData, 4);
669
+ // Note: Frame count is not directly in ANIM chunk, need to count ANMF chunks
670
+ // Reset frame count to 0 to start counting ANMF frames
671
+ metadata.frameCount = 0;
672
+ }
673
+ }
674
+ else if (chunkType === "ANMF") {
675
+ // Animation frame - count frames
676
+ if (metadata.frameCount !== undefined) {
677
+ metadata.frameCount++;
678
+ }
679
+ else {
680
+ metadata.frameCount = 1;
681
+ }
682
+ }
683
+ else if (chunkType === "EXIF") {
684
+ // EXIF metadata chunk
685
+ this.parseEXIF(chunkData, metadata);
686
+ }
687
+ else if (chunkType === "XMP ") {
688
+ // XMP metadata chunk
689
+ this.parseXMP(chunkData, metadata);
690
+ }
691
+ pos += chunkSize;
692
+ // Chunks are padded to even length
693
+ if (chunkSize % 2 === 1)
694
+ pos++;
695
+ }
696
+ return Promise.resolve(Object.keys(metadata).length > 0 ? metadata : undefined);
697
+ }
606
698
  }
607
699
  exports.WebPFormat = WebPFormat;
@@ -85,6 +85,15 @@ export declare class Image {
85
85
  * @returns Array of supported metadata field names, or undefined if format doesn't support metadata
86
86
  */
87
87
  static getSupportedMetadata(format: string): Array<keyof ImageMetadata> | undefined;
88
+ /**
89
+ * Extract metadata from image data without fully decoding the pixel data
90
+ * This is useful for quickly reading EXIF, XMP, or other metadata from images
91
+ * that may have unsupported features or compression methods
92
+ * @param data Raw image data
93
+ * @param format Optional format hint (e.g., "png", "jpeg", "webp")
94
+ * @returns Metadata extracted from the image, or undefined if extraction fails or format is unsupported
95
+ */
96
+ static extractMetadata(data: Uint8Array, format?: string): Promise<ImageMetadata | undefined>;
88
97
  /**
89
98
  * Read an image from bytes
90
99
  * @deprecated Use `decode()` instead. This method will be removed in a future version.
@@ -16,6 +16,8 @@ const pam_js_1 = require("./formats/pam.js");
16
16
  const pcx_js_1 = require("./formats/pcx.js");
17
17
  const ppm_js_1 = require("./formats/ppm.js");
18
18
  const ascii_js_1 = require("./formats/ascii.js");
19
+ const heic_js_1 = require("./formats/heic.js");
20
+ const avif_js_1 = require("./formats/avif.js");
19
21
  const security_js_1 = require("./utils/security.js");
20
22
  /**
21
23
  * Main Image class for reading, manipulating, and saving images
@@ -196,6 +198,30 @@ class Image {
196
198
  }
197
199
  return formatHandler.getSupportedMetadata?.();
198
200
  }
201
+ /**
202
+ * Extract metadata from image data without fully decoding the pixel data
203
+ * This is useful for quickly reading EXIF, XMP, or other metadata from images
204
+ * that may have unsupported features or compression methods
205
+ * @param data Raw image data
206
+ * @param format Optional format hint (e.g., "png", "jpeg", "webp")
207
+ * @returns Metadata extracted from the image, or undefined if extraction fails or format is unsupported
208
+ */
209
+ static async extractMetadata(data, format) {
210
+ // Try specified format first
211
+ if (format) {
212
+ const handler = Image.formats.find((f) => f.name === format);
213
+ if (handler && handler.canDecode(data) && handler.extractMetadata) {
214
+ return await handler.extractMetadata(data);
215
+ }
216
+ }
217
+ // Auto-detect format
218
+ for (const handler of Image.formats) {
219
+ if (handler.canDecode(data) && handler.extractMetadata) {
220
+ return await handler.extractMetadata(data);
221
+ }
222
+ }
223
+ return undefined;
224
+ }
199
225
  /**
200
226
  * Read an image from bytes
201
227
  * @deprecated Use `decode()` instead. This method will be removed in a future version.
@@ -845,5 +871,7 @@ Object.defineProperty(Image, "formats", {
845
871
  new pcx_js_1.PCXFormat(),
846
872
  new ppm_js_1.PPMFormat(),
847
873
  new ascii_js_1.ASCIIFormat(),
874
+ new heic_js_1.HEICFormat(),
875
+ new avif_js_1.AVIFFormat(),
848
876
  ]
849
877
  });
@@ -50,6 +50,16 @@ export interface ImageMetadata {
50
50
  software?: string;
51
51
  /** User comment / notes */
52
52
  userComment?: string;
53
+ /** Image file format (e.g., "png", "jpeg", "gif", "webp", "tiff") */
54
+ format?: string;
55
+ /** Compression algorithm used (e.g., "deflate", "lzw", "dct", "vp8", "vp8l", "none") */
56
+ compression?: string;
57
+ /** Number of frames in multi-frame images (e.g., animated GIFs, APNGs, multi-page TIFFs) */
58
+ frameCount?: number;
59
+ /** Bit depth per channel (e.g., 8, 16) */
60
+ bitDepth?: number;
61
+ /** Color type (e.g., "grayscale", "rgb", "rgba", "indexed", "grayscale-alpha") */
62
+ colorType?: string;
53
63
  /** Custom metadata fields */
54
64
  custom?: Record<string, string | number | boolean>;
55
65
  }
@@ -203,5 +213,13 @@ export interface ImageFormat {
203
213
  * @returns Array of metadata field names that can be persisted
204
214
  */
205
215
  getSupportedMetadata?(): Array<keyof ImageMetadata>;
216
+ /**
217
+ * Extract metadata from image data without fully decoding the pixel data
218
+ * This is useful for quickly reading EXIF, XMP, or other metadata from images
219
+ * that may have unsupported features or compression methods
220
+ * @param data Raw image data
221
+ * @returns Metadata extracted from the image, or undefined if extraction fails
222
+ */
223
+ extractMetadata?(data: Uint8Array): Promise<ImageMetadata | undefined>;
206
224
  }
207
225
  //# sourceMappingURL=types.d.ts.map