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.
- package/README.md +333 -168
- 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 +19 -1
- package/esm/src/formats/jpeg.js +709 -4
- 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/png_base.d.ts +8 -0
- package/esm/src/formats/png_base.js +176 -3
- package/esm/src/formats/ppm.d.ts +11 -1
- package/esm/src/formats/ppm.js +34 -0
- package/esm/src/formats/tiff.d.ts +13 -1
- package/esm/src/formats/tiff.js +165 -0
- package/esm/src/formats/webp.d.ts +16 -2
- package/esm/src/formats/webp.js +303 -62
- package/esm/src/image.d.ts +60 -0
- package/esm/src/image.js +253 -5
- package/esm/src/types.d.ts +59 -1
- package/esm/src/utils/image_processing.d.ts +55 -0
- package/esm/src/utils/image_processing.js +210 -0
- package/esm/src/utils/metadata/xmp.d.ts +52 -0
- package/esm/src/utils/metadata/xmp.js +325 -0
- package/esm/src/utils/resize.d.ts +4 -0
- package/esm/src/utils/resize.js +74 -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 +19 -1
- package/script/src/formats/jpeg.js +709 -4
- 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/png_base.d.ts +8 -0
- package/script/src/formats/png_base.js +176 -3
- package/script/src/formats/ppm.d.ts +11 -1
- package/script/src/formats/ppm.js +34 -0
- package/script/src/formats/tiff.d.ts +13 -1
- package/script/src/formats/tiff.js +165 -0
- package/script/src/formats/webp.d.ts +16 -2
- package/script/src/formats/webp.js +303 -62
- package/script/src/image.d.ts +60 -0
- package/script/src/image.js +251 -3
- package/script/src/types.d.ts +59 -1
- package/script/src/utils/image_processing.d.ts +55 -0
- package/script/src/utils/image_processing.js +216 -0
- package/script/src/utils/metadata/xmp.d.ts +52 -0
- package/script/src/utils/metadata/xmp.js +333 -0
- package/script/src/utils/resize.d.ts +4 -0
- package/script/src/utils/resize.js +75 -0
|
@@ -9,6 +9,7 @@ exports.adjustBrightness = adjustBrightness;
|
|
|
9
9
|
exports.adjustContrast = adjustContrast;
|
|
10
10
|
exports.adjustExposure = adjustExposure;
|
|
11
11
|
exports.adjustSaturation = adjustSaturation;
|
|
12
|
+
exports.adjustHue = adjustHue;
|
|
12
13
|
exports.invert = invert;
|
|
13
14
|
exports.grayscale = grayscale;
|
|
14
15
|
exports.fillRect = fillRect;
|
|
@@ -18,6 +19,11 @@ exports.gaussianBlur = gaussianBlur;
|
|
|
18
19
|
exports.sharpen = sharpen;
|
|
19
20
|
exports.sepia = sepia;
|
|
20
21
|
exports.medianFilter = medianFilter;
|
|
22
|
+
exports.rotate90 = rotate90;
|
|
23
|
+
exports.rotate180 = rotate180;
|
|
24
|
+
exports.rotate270 = rotate270;
|
|
25
|
+
exports.flipHorizontal = flipHorizontal;
|
|
26
|
+
exports.flipVertical = flipVertical;
|
|
21
27
|
/**
|
|
22
28
|
* Composite one image on top of another at a specified position
|
|
23
29
|
* @param base Base image data (RGBA)
|
|
@@ -147,6 +153,99 @@ function adjustSaturation(data, amount) {
|
|
|
147
153
|
}
|
|
148
154
|
return result;
|
|
149
155
|
}
|
|
156
|
+
/**
|
|
157
|
+
* Convert RGB to HSL color space
|
|
158
|
+
* @param r Red component (0-255)
|
|
159
|
+
* @param g Green component (0-255)
|
|
160
|
+
* @param b Blue component (0-255)
|
|
161
|
+
* @returns HSL values: [h (0-360), s (0-1), l (0-1)]
|
|
162
|
+
*/
|
|
163
|
+
function rgbToHsl(r, g, b) {
|
|
164
|
+
r /= 255;
|
|
165
|
+
g /= 255;
|
|
166
|
+
b /= 255;
|
|
167
|
+
const max = Math.max(r, g, b);
|
|
168
|
+
const min = Math.min(r, g, b);
|
|
169
|
+
const delta = max - min;
|
|
170
|
+
let h = 0;
|
|
171
|
+
let s = 0;
|
|
172
|
+
const l = (max + min) / 2;
|
|
173
|
+
if (delta !== 0) {
|
|
174
|
+
s = l > 0.5 ? delta / (2 - max - min) : delta / (max + min);
|
|
175
|
+
if (max === r) {
|
|
176
|
+
h = ((g - b) / delta + (g < b ? 6 : 0)) / 6;
|
|
177
|
+
}
|
|
178
|
+
else if (max === g) {
|
|
179
|
+
h = ((b - r) / delta + 2) / 6;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
h = ((r - g) / delta + 4) / 6;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return [h * 360, s, l];
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Convert HSL to RGB color space
|
|
189
|
+
* @param h Hue (0-360)
|
|
190
|
+
* @param s Saturation (0-1)
|
|
191
|
+
* @param l Lightness (0-1)
|
|
192
|
+
* @returns RGB values: [r (0-255), g (0-255), b (0-255)]
|
|
193
|
+
*/
|
|
194
|
+
function hslToRgb(h, s, l) {
|
|
195
|
+
h = h / 360;
|
|
196
|
+
let r, g, b;
|
|
197
|
+
if (s === 0) {
|
|
198
|
+
r = g = b = l; // Achromatic
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
const hue2rgb = (p, q, t) => {
|
|
202
|
+
if (t < 0)
|
|
203
|
+
t += 1;
|
|
204
|
+
if (t > 1)
|
|
205
|
+
t -= 1;
|
|
206
|
+
if (t < 1 / 6)
|
|
207
|
+
return p + (q - p) * 6 * t;
|
|
208
|
+
if (t < 1 / 2)
|
|
209
|
+
return q;
|
|
210
|
+
if (t < 2 / 3)
|
|
211
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
212
|
+
return p;
|
|
213
|
+
};
|
|
214
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
215
|
+
const p = 2 * l - q;
|
|
216
|
+
r = hue2rgb(p, q, h + 1 / 3);
|
|
217
|
+
g = hue2rgb(p, q, h);
|
|
218
|
+
b = hue2rgb(p, q, h - 1 / 3);
|
|
219
|
+
}
|
|
220
|
+
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Adjust hue of an image by rotating the hue wheel
|
|
224
|
+
* @param data Image data (RGBA)
|
|
225
|
+
* @param degrees Hue rotation in degrees (any value accepted, wraps at 360)
|
|
226
|
+
* @returns New image data with adjusted hue
|
|
227
|
+
*/
|
|
228
|
+
function adjustHue(data, degrees) {
|
|
229
|
+
const result = new Uint8Array(data.length);
|
|
230
|
+
// Normalize rotation to -180 to 180 range
|
|
231
|
+
const rotation = ((degrees % 360) + 360) % 360;
|
|
232
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
233
|
+
const r = data[i];
|
|
234
|
+
const g = data[i + 1];
|
|
235
|
+
const b = data[i + 2];
|
|
236
|
+
// Convert to HSL
|
|
237
|
+
const [h, s, l] = rgbToHsl(r, g, b);
|
|
238
|
+
// Rotate hue
|
|
239
|
+
const newH = (h + rotation) % 360;
|
|
240
|
+
// Convert back to RGB
|
|
241
|
+
const [newR, newG, newB] = hslToRgb(newH, s, l);
|
|
242
|
+
result[i] = newR;
|
|
243
|
+
result[i + 1] = newG;
|
|
244
|
+
result[i + 2] = newB;
|
|
245
|
+
result[i + 3] = data[i + 3]; // Preserve alpha
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
150
249
|
/**
|
|
151
250
|
* Invert colors of an image
|
|
152
251
|
* @param data Image data (RGBA)
|
|
@@ -475,3 +574,120 @@ function medianFilter(data, width, height, radius = 1) {
|
|
|
475
574
|
}
|
|
476
575
|
return result;
|
|
477
576
|
}
|
|
577
|
+
/**
|
|
578
|
+
* Rotate image 90 degrees clockwise
|
|
579
|
+
* @param data Image data (RGBA)
|
|
580
|
+
* @param width Image width
|
|
581
|
+
* @param height Image height
|
|
582
|
+
* @returns Rotated image data with swapped dimensions
|
|
583
|
+
*/
|
|
584
|
+
function rotate90(data, width, height) {
|
|
585
|
+
const result = new Uint8Array(data.length);
|
|
586
|
+
const newWidth = height;
|
|
587
|
+
const newHeight = width;
|
|
588
|
+
for (let y = 0; y < height; y++) {
|
|
589
|
+
for (let x = 0; x < width; x++) {
|
|
590
|
+
const srcIdx = (y * width + x) * 4;
|
|
591
|
+
const dstX = height - 1 - y;
|
|
592
|
+
const dstY = x;
|
|
593
|
+
const dstIdx = (dstY * newWidth + dstX) * 4;
|
|
594
|
+
result[dstIdx] = data[srcIdx];
|
|
595
|
+
result[dstIdx + 1] = data[srcIdx + 1];
|
|
596
|
+
result[dstIdx + 2] = data[srcIdx + 2];
|
|
597
|
+
result[dstIdx + 3] = data[srcIdx + 3];
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
return { data: result, width: newWidth, height: newHeight };
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Rotate image 180 degrees
|
|
604
|
+
* @param data Image data (RGBA)
|
|
605
|
+
* @param width Image width
|
|
606
|
+
* @param height Image height
|
|
607
|
+
* @returns Rotated image data with same dimensions
|
|
608
|
+
*/
|
|
609
|
+
function rotate180(data, width, height) {
|
|
610
|
+
const result = new Uint8Array(data.length);
|
|
611
|
+
for (let y = 0; y < height; y++) {
|
|
612
|
+
for (let x = 0; x < width; x++) {
|
|
613
|
+
const srcIdx = (y * width + x) * 4;
|
|
614
|
+
const dstX = width - 1 - x;
|
|
615
|
+
const dstY = height - 1 - y;
|
|
616
|
+
const dstIdx = (dstY * width + dstX) * 4;
|
|
617
|
+
result[dstIdx] = data[srcIdx];
|
|
618
|
+
result[dstIdx + 1] = data[srcIdx + 1];
|
|
619
|
+
result[dstIdx + 2] = data[srcIdx + 2];
|
|
620
|
+
result[dstIdx + 3] = data[srcIdx + 3];
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
return result;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Rotate image 270 degrees clockwise (or 90 degrees counter-clockwise)
|
|
627
|
+
* @param data Image data (RGBA)
|
|
628
|
+
* @param width Image width
|
|
629
|
+
* @param height Image height
|
|
630
|
+
* @returns Rotated image data with swapped dimensions
|
|
631
|
+
*/
|
|
632
|
+
function rotate270(data, width, height) {
|
|
633
|
+
const result = new Uint8Array(data.length);
|
|
634
|
+
const newWidth = height;
|
|
635
|
+
const newHeight = width;
|
|
636
|
+
for (let y = 0; y < height; y++) {
|
|
637
|
+
for (let x = 0; x < width; x++) {
|
|
638
|
+
const srcIdx = (y * width + x) * 4;
|
|
639
|
+
const dstX = y;
|
|
640
|
+
const dstY = width - 1 - x;
|
|
641
|
+
const dstIdx = (dstY * newWidth + dstX) * 4;
|
|
642
|
+
result[dstIdx] = data[srcIdx];
|
|
643
|
+
result[dstIdx + 1] = data[srcIdx + 1];
|
|
644
|
+
result[dstIdx + 2] = data[srcIdx + 2];
|
|
645
|
+
result[dstIdx + 3] = data[srcIdx + 3];
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return { data: result, width: newWidth, height: newHeight };
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Flip image horizontally (mirror)
|
|
652
|
+
* @param data Image data (RGBA)
|
|
653
|
+
* @param width Image width
|
|
654
|
+
* @param height Image height
|
|
655
|
+
* @returns Flipped image data
|
|
656
|
+
*/
|
|
657
|
+
function flipHorizontal(data, width, height) {
|
|
658
|
+
const result = new Uint8Array(data.length);
|
|
659
|
+
for (let y = 0; y < height; y++) {
|
|
660
|
+
for (let x = 0; x < width; x++) {
|
|
661
|
+
const srcIdx = (y * width + x) * 4;
|
|
662
|
+
const dstX = width - 1 - x;
|
|
663
|
+
const dstIdx = (y * width + dstX) * 4;
|
|
664
|
+
result[dstIdx] = data[srcIdx];
|
|
665
|
+
result[dstIdx + 1] = data[srcIdx + 1];
|
|
666
|
+
result[dstIdx + 2] = data[srcIdx + 2];
|
|
667
|
+
result[dstIdx + 3] = data[srcIdx + 3];
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
return result;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Flip image vertically
|
|
674
|
+
* @param data Image data (RGBA)
|
|
675
|
+
* @param width Image width
|
|
676
|
+
* @param height Image height
|
|
677
|
+
* @returns Flipped image data
|
|
678
|
+
*/
|
|
679
|
+
function flipVertical(data, width, height) {
|
|
680
|
+
const result = new Uint8Array(data.length);
|
|
681
|
+
for (let y = 0; y < height; y++) {
|
|
682
|
+
for (let x = 0; x < width; x++) {
|
|
683
|
+
const srcIdx = (y * width + x) * 4;
|
|
684
|
+
const dstY = height - 1 - y;
|
|
685
|
+
const dstIdx = (dstY * width + x) * 4;
|
|
686
|
+
result[dstIdx] = data[srcIdx];
|
|
687
|
+
result[dstIdx + 1] = data[srcIdx + 1];
|
|
688
|
+
result[dstIdx + 2] = data[srcIdx + 2];
|
|
689
|
+
result[dstIdx + 3] = data[srcIdx + 3];
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return result;
|
|
693
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XMP (Extensible Metadata Platform) parsing and writing utilities
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for reading and writing XMP metadata in image files.
|
|
5
|
+
* It supports Dublin Core, EXIF, and Photoshop namespaces.
|
|
6
|
+
*/
|
|
7
|
+
import type { ImageMetadata } from "../../types.js";
|
|
8
|
+
/**
|
|
9
|
+
* XMP namespace URIs
|
|
10
|
+
*/
|
|
11
|
+
export declare const XMP_NAMESPACES: {
|
|
12
|
+
readonly RDF: "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
|
|
13
|
+
readonly DC: "http://purl.org/dc/elements/1.1/";
|
|
14
|
+
readonly XMP: "http://ns.adobe.com/xap/1.0/";
|
|
15
|
+
readonly EXIF: "http://ns.adobe.com/exif/1.0/";
|
|
16
|
+
readonly TIFF: "http://ns.adobe.com/tiff/1.0/";
|
|
17
|
+
readonly PHOTOSHOP: "http://ns.adobe.com/photoshop/1.0/";
|
|
18
|
+
readonly XMP_RIGHTS: "http://ns.adobe.com/xap/1.0/rights/";
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* XMP Dublin Core field mapping to ImageMetadata
|
|
22
|
+
*/
|
|
23
|
+
export interface XMPFieldMapping {
|
|
24
|
+
xmpPath: string;
|
|
25
|
+
metadataKey: keyof ImageMetadata;
|
|
26
|
+
namespace: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Supported XMP fields and their mappings
|
|
30
|
+
*/
|
|
31
|
+
export declare const XMP_FIELD_MAPPINGS: XMPFieldMapping[];
|
|
32
|
+
/**
|
|
33
|
+
* Escape XML special characters
|
|
34
|
+
*/
|
|
35
|
+
export declare function escapeXML(str: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Unescape XML special characters
|
|
38
|
+
*/
|
|
39
|
+
export declare function unescapeXML(str: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Parse XMP metadata from XML string
|
|
42
|
+
*/
|
|
43
|
+
export declare function parseXMP(xmpStr: string): Partial<ImageMetadata>;
|
|
44
|
+
/**
|
|
45
|
+
* Create XMP packet from metadata
|
|
46
|
+
*/
|
|
47
|
+
export declare function createXMP(metadata: Partial<ImageMetadata>): string;
|
|
48
|
+
/**
|
|
49
|
+
* Get list of supported XMP metadata fields
|
|
50
|
+
*/
|
|
51
|
+
export declare function getSupportedXMPFields(): Array<keyof ImageMetadata>;
|
|
52
|
+
//# sourceMappingURL=xmp.d.ts.map
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* XMP (Extensible Metadata Platform) parsing and writing utilities
|
|
4
|
+
*
|
|
5
|
+
* This module provides utilities for reading and writing XMP metadata in image files.
|
|
6
|
+
* It supports Dublin Core, EXIF, and Photoshop namespaces.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.XMP_FIELD_MAPPINGS = exports.XMP_NAMESPACES = void 0;
|
|
10
|
+
exports.escapeXML = escapeXML;
|
|
11
|
+
exports.unescapeXML = unescapeXML;
|
|
12
|
+
exports.parseXMP = parseXMP;
|
|
13
|
+
exports.createXMP = createXMP;
|
|
14
|
+
exports.getSupportedXMPFields = getSupportedXMPFields;
|
|
15
|
+
/**
|
|
16
|
+
* XMP namespace URIs
|
|
17
|
+
*/
|
|
18
|
+
exports.XMP_NAMESPACES = {
|
|
19
|
+
RDF: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
|
20
|
+
DC: "http://purl.org/dc/elements/1.1/",
|
|
21
|
+
XMP: "http://ns.adobe.com/xap/1.0/",
|
|
22
|
+
EXIF: "http://ns.adobe.com/exif/1.0/",
|
|
23
|
+
TIFF: "http://ns.adobe.com/tiff/1.0/",
|
|
24
|
+
PHOTOSHOP: "http://ns.adobe.com/photoshop/1.0/",
|
|
25
|
+
XMP_RIGHTS: "http://ns.adobe.com/xap/1.0/rights/",
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Supported XMP fields and their mappings
|
|
29
|
+
*/
|
|
30
|
+
exports.XMP_FIELD_MAPPINGS = [
|
|
31
|
+
// Dublin Core
|
|
32
|
+
{ xmpPath: "dc:title", metadataKey: "title", namespace: exports.XMP_NAMESPACES.DC },
|
|
33
|
+
{
|
|
34
|
+
xmpPath: "dc:description",
|
|
35
|
+
metadataKey: "description",
|
|
36
|
+
namespace: exports.XMP_NAMESPACES.DC,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
xmpPath: "dc:creator",
|
|
40
|
+
metadataKey: "author",
|
|
41
|
+
namespace: exports.XMP_NAMESPACES.DC,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
xmpPath: "dc:rights",
|
|
45
|
+
metadataKey: "copyright",
|
|
46
|
+
namespace: exports.XMP_NAMESPACES.DC,
|
|
47
|
+
},
|
|
48
|
+
// EXIF namespace
|
|
49
|
+
{
|
|
50
|
+
xmpPath: "exif:DateTimeOriginal",
|
|
51
|
+
metadataKey: "creationDate",
|
|
52
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
xmpPath: "exif:ISOSpeedRatings",
|
|
56
|
+
metadataKey: "iso",
|
|
57
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
xmpPath: "exif:ExposureTime",
|
|
61
|
+
metadataKey: "exposureTime",
|
|
62
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
xmpPath: "exif:FNumber",
|
|
66
|
+
metadataKey: "fNumber",
|
|
67
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
xmpPath: "exif:FocalLength",
|
|
71
|
+
metadataKey: "focalLength",
|
|
72
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
xmpPath: "exif:Flash",
|
|
76
|
+
metadataKey: "flash",
|
|
77
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
xmpPath: "exif:WhiteBalance",
|
|
81
|
+
metadataKey: "whiteBalance",
|
|
82
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
xmpPath: "exif:UserComment",
|
|
86
|
+
metadataKey: "userComment",
|
|
87
|
+
namespace: exports.XMP_NAMESPACES.EXIF,
|
|
88
|
+
},
|
|
89
|
+
// TIFF namespace
|
|
90
|
+
{
|
|
91
|
+
xmpPath: "tiff:Make",
|
|
92
|
+
metadataKey: "cameraMake",
|
|
93
|
+
namespace: exports.XMP_NAMESPACES.TIFF,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
xmpPath: "tiff:Model",
|
|
97
|
+
metadataKey: "cameraModel",
|
|
98
|
+
namespace: exports.XMP_NAMESPACES.TIFF,
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
xmpPath: "tiff:Orientation",
|
|
102
|
+
metadataKey: "orientation",
|
|
103
|
+
namespace: exports.XMP_NAMESPACES.TIFF,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
xmpPath: "tiff:Software",
|
|
107
|
+
metadataKey: "software",
|
|
108
|
+
namespace: exports.XMP_NAMESPACES.TIFF,
|
|
109
|
+
},
|
|
110
|
+
// Photoshop namespace
|
|
111
|
+
{
|
|
112
|
+
xmpPath: "photoshop:Credit",
|
|
113
|
+
metadataKey: "author",
|
|
114
|
+
namespace: exports.XMP_NAMESPACES.PHOTOSHOP,
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
/**
|
|
118
|
+
* Escape XML special characters
|
|
119
|
+
*/
|
|
120
|
+
function escapeXML(str) {
|
|
121
|
+
return str
|
|
122
|
+
.replace(/&/g, "&")
|
|
123
|
+
.replace(/</g, "<")
|
|
124
|
+
.replace(/>/g, ">")
|
|
125
|
+
.replace(/"/g, """)
|
|
126
|
+
.replace(/'/g, "'");
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Unescape XML special characters
|
|
130
|
+
*/
|
|
131
|
+
function unescapeXML(str) {
|
|
132
|
+
return str
|
|
133
|
+
.replace(/</g, "<")
|
|
134
|
+
.replace(/>/g, ">")
|
|
135
|
+
.replace(/"/g, '"')
|
|
136
|
+
.replace(/'/g, "'")
|
|
137
|
+
.replace(/&/g, "&");
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Parse XMP metadata from XML string
|
|
141
|
+
*/
|
|
142
|
+
function parseXMP(xmpStr) {
|
|
143
|
+
const metadata = {};
|
|
144
|
+
try {
|
|
145
|
+
// Simple regex-based parsing for common fields
|
|
146
|
+
// Dublin Core - title (with dotall flag 's')
|
|
147
|
+
const titleMatch = xmpStr.match(/<dc:title[\s\S]*?<rdf:li[^>]*>([^<]+)<\/rdf:li>/);
|
|
148
|
+
if (titleMatch && titleMatch[1].trim()) {
|
|
149
|
+
metadata.title = unescapeXML(titleMatch[1].trim());
|
|
150
|
+
}
|
|
151
|
+
// Dublin Core - description
|
|
152
|
+
const descMatch = xmpStr.match(/<dc:description[\s\S]*?<rdf:li[^>]*>([^<]+)<\/rdf:li>/);
|
|
153
|
+
if (descMatch && descMatch[1].trim()) {
|
|
154
|
+
metadata.description = unescapeXML(descMatch[1].trim());
|
|
155
|
+
}
|
|
156
|
+
// Dublin Core - creator
|
|
157
|
+
const creatorMatch = xmpStr.match(/<dc:creator[\s\S]*?<rdf:li[^>]*>([^<]+)<\/rdf:li>/);
|
|
158
|
+
if (creatorMatch && creatorMatch[1].trim()) {
|
|
159
|
+
metadata.author = unescapeXML(creatorMatch[1].trim());
|
|
160
|
+
}
|
|
161
|
+
// Dublin Core - rights
|
|
162
|
+
const rightsMatch = xmpStr.match(/<dc:rights[\s\S]*?<rdf:li[^>]*>([^<]+)<\/rdf:li>/);
|
|
163
|
+
if (rightsMatch && rightsMatch[1].trim()) {
|
|
164
|
+
metadata.copyright = unescapeXML(rightsMatch[1].trim());
|
|
165
|
+
}
|
|
166
|
+
// EXIF - DateTimeOriginal
|
|
167
|
+
const dateMatch = xmpStr.match(/<exif:DateTimeOriginal>([^<]+)<\/exif:DateTimeOriginal>/);
|
|
168
|
+
if (dateMatch) {
|
|
169
|
+
try {
|
|
170
|
+
metadata.creationDate = new Date(dateMatch[1]);
|
|
171
|
+
}
|
|
172
|
+
catch (_e) {
|
|
173
|
+
// Ignore date parse errors
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// TIFF - Make and Model
|
|
177
|
+
const makeMatch = xmpStr.match(/<tiff:Make>([^<]+)<\/tiff:Make>/);
|
|
178
|
+
if (makeMatch) {
|
|
179
|
+
metadata.cameraMake = unescapeXML(makeMatch[1]);
|
|
180
|
+
}
|
|
181
|
+
const modelMatch = xmpStr.match(/<tiff:Model>([^<]+)<\/tiff:Model>/);
|
|
182
|
+
if (modelMatch) {
|
|
183
|
+
metadata.cameraModel = unescapeXML(modelMatch[1]);
|
|
184
|
+
}
|
|
185
|
+
const softwareMatch = xmpStr.match(/<tiff:Software>([^<]+)<\/tiff:Software>/);
|
|
186
|
+
if (softwareMatch) {
|
|
187
|
+
metadata.software = unescapeXML(softwareMatch[1]);
|
|
188
|
+
}
|
|
189
|
+
const orientationMatch = xmpStr.match(/<tiff:Orientation>([^<]+)<\/tiff:Orientation>/);
|
|
190
|
+
if (orientationMatch) {
|
|
191
|
+
metadata.orientation = parseInt(orientationMatch[1]);
|
|
192
|
+
}
|
|
193
|
+
// EXIF - Camera settings
|
|
194
|
+
const isoMatch = xmpStr.match(/<exif:ISOSpeedRatings>(?:<rdf:Seq[^>]*><rdf:li>)?([^<]+)/);
|
|
195
|
+
if (isoMatch) {
|
|
196
|
+
metadata.iso = parseInt(isoMatch[1]);
|
|
197
|
+
}
|
|
198
|
+
const exposureMatch = xmpStr.match(/<exif:ExposureTime>([^<]+)<\/exif:ExposureTime>/);
|
|
199
|
+
if (exposureMatch) {
|
|
200
|
+
// Handle rational format (e.g., "1/250")
|
|
201
|
+
if (exposureMatch[1].includes("/")) {
|
|
202
|
+
const [num, den] = exposureMatch[1].split("/").map(Number);
|
|
203
|
+
metadata.exposureTime = num / den;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
metadata.exposureTime = parseFloat(exposureMatch[1]);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const fNumberMatch = xmpStr.match(/<exif:FNumber>([^<]+)<\/exif:FNumber>/);
|
|
210
|
+
if (fNumberMatch) {
|
|
211
|
+
metadata.fNumber = parseFloat(fNumberMatch[1]);
|
|
212
|
+
}
|
|
213
|
+
const focalLengthMatch = xmpStr.match(/<exif:FocalLength>([^<]+)<\/exif:FocalLength>/);
|
|
214
|
+
if (focalLengthMatch) {
|
|
215
|
+
metadata.focalLength = parseFloat(focalLengthMatch[1]);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (_e) {
|
|
219
|
+
// Ignore XMP parsing errors
|
|
220
|
+
}
|
|
221
|
+
return metadata;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Create XMP packet from metadata
|
|
225
|
+
*/
|
|
226
|
+
function createXMP(metadata) {
|
|
227
|
+
const parts = [];
|
|
228
|
+
parts.push('<?xpacket begin="\ufeff" id="W5M0MpCehiHzreSzNTczkc9d"?>');
|
|
229
|
+
parts.push('<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="@cross/image">');
|
|
230
|
+
parts.push('<rdf:RDF xmlns:rdf="' + exports.XMP_NAMESPACES.RDF + '">');
|
|
231
|
+
parts.push('<rdf:Description rdf:about=""');
|
|
232
|
+
parts.push(' xmlns:dc="' + exports.XMP_NAMESPACES.DC + '"');
|
|
233
|
+
parts.push(' xmlns:xmp="' + exports.XMP_NAMESPACES.XMP + '"');
|
|
234
|
+
parts.push(' xmlns:exif="' + exports.XMP_NAMESPACES.EXIF + '"');
|
|
235
|
+
parts.push(' xmlns:tiff="' + exports.XMP_NAMESPACES.TIFF + '"');
|
|
236
|
+
parts.push(' xmlns:photoshop="' + exports.XMP_NAMESPACES.PHOTOSHOP + '"');
|
|
237
|
+
parts.push(' xmlns:xmpRights="' + exports.XMP_NAMESPACES.XMP_RIGHTS + '">');
|
|
238
|
+
// Dublin Core - title
|
|
239
|
+
if (metadata.title) {
|
|
240
|
+
parts.push(" <dc:title>");
|
|
241
|
+
parts.push(" <rdf:Alt>");
|
|
242
|
+
parts.push(' <rdf:li xml:lang="x-default">' + escapeXML(metadata.title) +
|
|
243
|
+
"</rdf:li>");
|
|
244
|
+
parts.push(" </rdf:Alt>");
|
|
245
|
+
parts.push(" </dc:title>");
|
|
246
|
+
}
|
|
247
|
+
// Dublin Core - description
|
|
248
|
+
if (metadata.description) {
|
|
249
|
+
parts.push(" <dc:description>");
|
|
250
|
+
parts.push(" <rdf:Alt>");
|
|
251
|
+
parts.push(' <rdf:li xml:lang="x-default">' + escapeXML(metadata.description) +
|
|
252
|
+
"</rdf:li>");
|
|
253
|
+
parts.push(" </rdf:Alt>");
|
|
254
|
+
parts.push(" </dc:description>");
|
|
255
|
+
}
|
|
256
|
+
// Dublin Core - creator
|
|
257
|
+
if (metadata.author) {
|
|
258
|
+
parts.push(" <dc:creator>");
|
|
259
|
+
parts.push(" <rdf:Seq>");
|
|
260
|
+
parts.push(" <rdf:li>" + escapeXML(metadata.author) + "</rdf:li>");
|
|
261
|
+
parts.push(" </rdf:Seq>");
|
|
262
|
+
parts.push(" </dc:creator>");
|
|
263
|
+
}
|
|
264
|
+
// Dublin Core - rights
|
|
265
|
+
if (metadata.copyright) {
|
|
266
|
+
parts.push(" <dc:rights>");
|
|
267
|
+
parts.push(" <rdf:Alt>");
|
|
268
|
+
parts.push(' <rdf:li xml:lang="x-default">' + escapeXML(metadata.copyright) +
|
|
269
|
+
"</rdf:li>");
|
|
270
|
+
parts.push(" </rdf:Alt>");
|
|
271
|
+
parts.push(" </dc:rights>");
|
|
272
|
+
}
|
|
273
|
+
// EXIF - DateTimeOriginal
|
|
274
|
+
if (metadata.creationDate) {
|
|
275
|
+
const isoDate = metadata.creationDate.toISOString();
|
|
276
|
+
parts.push(" <exif:DateTimeOriginal>" + isoDate + "</exif:DateTimeOriginal>");
|
|
277
|
+
}
|
|
278
|
+
// TIFF - Make and Model
|
|
279
|
+
if (metadata.cameraMake) {
|
|
280
|
+
parts.push(" <tiff:Make>" + escapeXML(metadata.cameraMake) + "</tiff:Make>");
|
|
281
|
+
}
|
|
282
|
+
if (metadata.cameraModel) {
|
|
283
|
+
parts.push(" <tiff:Model>" + escapeXML(metadata.cameraModel) + "</tiff:Model>");
|
|
284
|
+
}
|
|
285
|
+
if (metadata.software) {
|
|
286
|
+
parts.push(" <tiff:Software>" + escapeXML(metadata.software) + "</tiff:Software>");
|
|
287
|
+
}
|
|
288
|
+
if (metadata.orientation !== undefined) {
|
|
289
|
+
parts.push(" <tiff:Orientation>" + metadata.orientation + "</tiff:Orientation>");
|
|
290
|
+
}
|
|
291
|
+
// EXIF - Camera settings
|
|
292
|
+
if (metadata.iso !== undefined) {
|
|
293
|
+
parts.push(" <exif:ISOSpeedRatings>");
|
|
294
|
+
parts.push(" <rdf:Seq>");
|
|
295
|
+
parts.push(" <rdf:li>" + metadata.iso + "</rdf:li>");
|
|
296
|
+
parts.push(" </rdf:Seq>");
|
|
297
|
+
parts.push(" </exif:ISOSpeedRatings>");
|
|
298
|
+
}
|
|
299
|
+
if (metadata.exposureTime !== undefined) {
|
|
300
|
+
parts.push(" <exif:ExposureTime>" + metadata.exposureTime + "</exif:ExposureTime>");
|
|
301
|
+
}
|
|
302
|
+
if (metadata.fNumber !== undefined) {
|
|
303
|
+
parts.push(" <exif:FNumber>" + metadata.fNumber + "</exif:FNumber>");
|
|
304
|
+
}
|
|
305
|
+
if (metadata.focalLength !== undefined) {
|
|
306
|
+
parts.push(" <exif:FocalLength>" + metadata.focalLength + "</exif:FocalLength>");
|
|
307
|
+
}
|
|
308
|
+
parts.push("</rdf:Description>");
|
|
309
|
+
parts.push("</rdf:RDF>");
|
|
310
|
+
parts.push("</x:xmpmeta>");
|
|
311
|
+
parts.push('<?xpacket end="w"?>');
|
|
312
|
+
return parts.join("\n");
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Get list of supported XMP metadata fields
|
|
316
|
+
*/
|
|
317
|
+
function getSupportedXMPFields() {
|
|
318
|
+
return [
|
|
319
|
+
"title",
|
|
320
|
+
"description",
|
|
321
|
+
"author",
|
|
322
|
+
"copyright",
|
|
323
|
+
"creationDate",
|
|
324
|
+
"cameraMake",
|
|
325
|
+
"cameraModel",
|
|
326
|
+
"orientation",
|
|
327
|
+
"software",
|
|
328
|
+
"iso",
|
|
329
|
+
"exposureTime",
|
|
330
|
+
"fNumber",
|
|
331
|
+
"focalLength",
|
|
332
|
+
];
|
|
333
|
+
}
|
|
@@ -6,4 +6,8 @@ export declare function resizeBilinear(src: Uint8Array, srcWidth: number, srcHei
|
|
|
6
6
|
* Nearest neighbor resize
|
|
7
7
|
*/
|
|
8
8
|
export declare function resizeNearest(src: Uint8Array, srcWidth: number, srcHeight: number, dstWidth: number, dstHeight: number): Uint8Array;
|
|
9
|
+
/**
|
|
10
|
+
* Bicubic interpolation resize (Catmull-Rom)
|
|
11
|
+
*/
|
|
12
|
+
export declare function resizeBicubic(src: Uint8Array, srcWidth: number, srcHeight: number, dstWidth: number, dstHeight: number): Uint8Array;
|
|
9
13
|
//# sourceMappingURL=resize.d.ts.map
|