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.
- package/README.md +333 -289
- package/esm/mod.d.ts +2 -0
- package/esm/mod.js +2 -0
- package/esm/src/formats/apng.d.ts +13 -1
- package/esm/src/formats/apng.js +97 -0
- package/esm/src/formats/ascii.d.ts +11 -1
- package/esm/src/formats/ascii.js +24 -0
- package/esm/src/formats/avif.d.ts +96 -0
- package/esm/src/formats/avif.js +607 -0
- package/esm/src/formats/bmp.d.ts +11 -1
- package/esm/src/formats/bmp.js +73 -0
- package/esm/src/formats/dng.d.ts +13 -1
- package/esm/src/formats/dng.js +26 -4
- package/esm/src/formats/gif.d.ts +15 -2
- package/esm/src/formats/gif.js +146 -4
- package/esm/src/formats/heic.d.ts +96 -0
- package/esm/src/formats/heic.js +608 -0
- package/esm/src/formats/ico.d.ts +11 -1
- package/esm/src/formats/ico.js +28 -0
- package/esm/src/formats/jpeg.d.ts +7 -0
- package/esm/src/formats/jpeg.js +76 -0
- package/esm/src/formats/pam.d.ts +11 -1
- package/esm/src/formats/pam.js +66 -0
- package/esm/src/formats/pcx.d.ts +11 -1
- package/esm/src/formats/pcx.js +45 -0
- package/esm/src/formats/png.d.ts +13 -1
- package/esm/src/formats/png.js +87 -0
- package/esm/src/formats/ppm.d.ts +11 -1
- package/esm/src/formats/ppm.js +34 -0
- package/esm/src/formats/tiff.d.ts +7 -0
- package/esm/src/formats/tiff.js +134 -0
- package/esm/src/formats/webp.d.ts +7 -0
- package/esm/src/formats/webp.js +92 -0
- package/esm/src/image.d.ts +9 -0
- package/esm/src/image.js +28 -0
- package/esm/src/types.d.ts +18 -0
- package/package.json +18 -1
- package/script/mod.d.ts +2 -0
- package/script/mod.js +5 -1
- package/script/src/formats/apng.d.ts +13 -1
- package/script/src/formats/apng.js +97 -0
- package/script/src/formats/ascii.d.ts +11 -1
- package/script/src/formats/ascii.js +24 -0
- package/script/src/formats/avif.d.ts +96 -0
- package/script/src/formats/avif.js +611 -0
- package/script/src/formats/bmp.d.ts +11 -1
- package/script/src/formats/bmp.js +73 -0
- package/script/src/formats/dng.d.ts +13 -1
- package/script/src/formats/dng.js +26 -4
- package/script/src/formats/gif.d.ts +15 -2
- package/script/src/formats/gif.js +146 -4
- package/script/src/formats/heic.d.ts +96 -0
- package/script/src/formats/heic.js +612 -0
- package/script/src/formats/ico.d.ts +11 -1
- package/script/src/formats/ico.js +28 -0
- package/script/src/formats/jpeg.d.ts +7 -0
- package/script/src/formats/jpeg.js +76 -0
- package/script/src/formats/pam.d.ts +11 -1
- package/script/src/formats/pam.js +66 -0
- package/script/src/formats/pcx.d.ts +11 -1
- package/script/src/formats/pcx.js +45 -0
- package/script/src/formats/png.d.ts +13 -1
- package/script/src/formats/png.js +87 -0
- package/script/src/formats/ppm.d.ts +11 -1
- package/script/src/formats/ppm.js +34 -0
- package/script/src/formats/tiff.d.ts +7 -0
- package/script/src/formats/tiff.js +134 -0
- package/script/src/formats/webp.d.ts +7 -0
- package/script/src/formats/webp.js +92 -0
- package/script/src/image.d.ts +9 -0
- package/script/src/image.js +28 -0
- 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;
|
package/script/src/image.d.ts
CHANGED
|
@@ -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.
|
package/script/src/image.js
CHANGED
|
@@ -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
|
});
|
package/script/src/types.d.ts
CHANGED
|
@@ -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
|