cross-image 0.1.4 → 0.2.0
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 +155 -121
- package/esm/mod.d.ts +32 -8
- package/esm/mod.js +32 -8
- package/esm/src/formats/dng.d.ts +27 -0
- package/esm/src/formats/dng.js +191 -0
- package/esm/src/formats/pam.d.ts +43 -0
- package/esm/src/formats/pam.js +177 -0
- package/esm/src/formats/pcx.d.ts +13 -0
- package/esm/src/formats/pcx.js +204 -0
- package/esm/src/formats/tiff.d.ts +7 -7
- package/esm/src/image.d.ts +133 -1
- package/esm/src/image.js +250 -11
- package/esm/src/utils/image_processing.d.ts +91 -0
- package/esm/src/utils/image_processing.js +231 -0
- package/esm/src/utils/webp_decoder.js +47 -12
- package/esm/src/utils/webp_encoder.js +97 -39
- package/package.json +4 -1
- package/script/mod.d.ts +32 -8
- package/script/mod.js +36 -10
- package/script/src/formats/dng.d.ts +27 -0
- package/script/src/formats/dng.js +195 -0
- package/script/src/formats/pam.d.ts +43 -0
- package/script/src/formats/pam.js +181 -0
- package/script/src/formats/pcx.d.ts +13 -0
- package/script/src/formats/pcx.js +208 -0
- package/script/src/formats/tiff.d.ts +7 -7
- package/script/src/image.d.ts +133 -1
- package/script/src/image.js +250 -11
- package/script/src/utils/image_processing.d.ts +91 -0
- package/script/src/utils/image_processing.js +242 -0
- package/script/src/utils/webp_decoder.js +47 -12
- package/script/src/utils/webp_encoder.js +97 -39
- package/esm/src/formats/raw.d.ts +0 -40
- package/esm/src/formats/raw.js +0 -118
- package/script/src/formats/raw.d.ts +0 -40
- package/script/src/formats/raw.js +0 -122
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { validateImageDimensions } from "../utils/security.js";
|
|
2
|
+
/**
|
|
3
|
+
* PAM format handler
|
|
4
|
+
* Implements the Netpbm PAM (Portable Arbitrary Map) format.
|
|
5
|
+
* This is a standard uncompressed format supported by GIMP and other tools.
|
|
6
|
+
*
|
|
7
|
+
* Format structure:
|
|
8
|
+
* - Header (text):
|
|
9
|
+
* P7
|
|
10
|
+
* WIDTH <width>
|
|
11
|
+
* HEIGHT <height>
|
|
12
|
+
* DEPTH 4
|
|
13
|
+
* MAXVAL 255
|
|
14
|
+
* TUPLTYPE RGB_ALPHA
|
|
15
|
+
* ENDHDR
|
|
16
|
+
* - Data (binary):
|
|
17
|
+
* RGBA pixel data (width * height * 4 bytes)
|
|
18
|
+
*/
|
|
19
|
+
export class PAMFormat {
|
|
20
|
+
constructor() {
|
|
21
|
+
/** Format name identifier */
|
|
22
|
+
Object.defineProperty(this, "name", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: "pam"
|
|
27
|
+
});
|
|
28
|
+
/** MIME type for PAM images */
|
|
29
|
+
Object.defineProperty(this, "mimeType", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
configurable: true,
|
|
32
|
+
writable: true,
|
|
33
|
+
value: "image/x-portable-arbitrary-map"
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if the given data is a PAM image
|
|
38
|
+
* @param data Raw image data to check
|
|
39
|
+
* @returns true if data has PAM signature
|
|
40
|
+
*/
|
|
41
|
+
canDecode(data) {
|
|
42
|
+
// Check if data has at least magic bytes
|
|
43
|
+
if (data.length < 3) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
// Check for P7 followed by whitespace (usually newline)
|
|
47
|
+
return data[0] === 0x50 && // P
|
|
48
|
+
data[1] === 0x37 && // 7
|
|
49
|
+
(data[2] === 0x0a || data[2] === 0x0d || data[2] === 0x20); // \n, \r, or space
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Decode PAM image data to RGBA
|
|
53
|
+
* @param data Raw PAM image data
|
|
54
|
+
* @returns Decoded image data with RGBA pixels
|
|
55
|
+
*/
|
|
56
|
+
decode(data) {
|
|
57
|
+
if (!this.canDecode(data)) {
|
|
58
|
+
throw new Error("Invalid PAM signature");
|
|
59
|
+
}
|
|
60
|
+
// Parse header
|
|
61
|
+
let offset = 0;
|
|
62
|
+
let width = 0;
|
|
63
|
+
let height = 0;
|
|
64
|
+
let depth = 0;
|
|
65
|
+
let maxval = 0;
|
|
66
|
+
let headerDone = false;
|
|
67
|
+
const decoder = new TextDecoder();
|
|
68
|
+
// Find end of header
|
|
69
|
+
// We need to read line by line.
|
|
70
|
+
// Since we have the full buffer, we can just scan for newlines.
|
|
71
|
+
let lineStart = 0;
|
|
72
|
+
while (!headerDone && offset < data.length) {
|
|
73
|
+
// Find next newline
|
|
74
|
+
let lineEnd = -1;
|
|
75
|
+
for (let i = offset; i < data.length; i++) {
|
|
76
|
+
if (data[i] === 0x0a) {
|
|
77
|
+
lineEnd = i;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (lineEnd === -1) {
|
|
82
|
+
throw new Error("Unexpected end of file in header");
|
|
83
|
+
}
|
|
84
|
+
const line = decoder.decode(data.subarray(lineStart, lineEnd)).trim();
|
|
85
|
+
offset = lineEnd + 1; // Skip newline
|
|
86
|
+
lineStart = offset;
|
|
87
|
+
// Skip comments
|
|
88
|
+
if (line.startsWith("#"))
|
|
89
|
+
continue;
|
|
90
|
+
if (line === "")
|
|
91
|
+
continue;
|
|
92
|
+
if (line === "P7")
|
|
93
|
+
continue;
|
|
94
|
+
if (line === "ENDHDR") {
|
|
95
|
+
headerDone = true;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
// Parse fields
|
|
99
|
+
const parts = line.split(/\s+/);
|
|
100
|
+
if (parts.length >= 2) {
|
|
101
|
+
const key = parts[0];
|
|
102
|
+
const value = parts[1];
|
|
103
|
+
switch (key) {
|
|
104
|
+
case "WIDTH":
|
|
105
|
+
width = parseInt(value, 10);
|
|
106
|
+
break;
|
|
107
|
+
case "HEIGHT":
|
|
108
|
+
height = parseInt(value, 10);
|
|
109
|
+
break;
|
|
110
|
+
case "DEPTH":
|
|
111
|
+
depth = parseInt(value, 10);
|
|
112
|
+
break;
|
|
113
|
+
case "MAXVAL":
|
|
114
|
+
maxval = parseInt(value, 10);
|
|
115
|
+
break;
|
|
116
|
+
case "TUPLTYPE":
|
|
117
|
+
// Optional check
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (!headerDone) {
|
|
123
|
+
throw new Error("Invalid PAM header: missing ENDHDR");
|
|
124
|
+
}
|
|
125
|
+
// Validate dimensions
|
|
126
|
+
if (width <= 0 || height <= 0) {
|
|
127
|
+
throw new Error(`Invalid PAM dimensions: ${width}x${height}`);
|
|
128
|
+
}
|
|
129
|
+
// Validate dimensions for security
|
|
130
|
+
validateImageDimensions(width, height);
|
|
131
|
+
// We only support DEPTH 4 (RGBA) and MAXVAL 255 for now
|
|
132
|
+
if (depth !== 4) {
|
|
133
|
+
throw new Error(`Unsupported PAM depth: ${depth}. Only depth 4 (RGBA) is supported.`);
|
|
134
|
+
}
|
|
135
|
+
if (maxval !== 255) {
|
|
136
|
+
throw new Error(`Unsupported PAM maxval: ${maxval}. Only maxval 255 is supported.`);
|
|
137
|
+
}
|
|
138
|
+
const expectedDataLength = width * height * 4;
|
|
139
|
+
const actualDataLength = data.length - offset;
|
|
140
|
+
if (actualDataLength < expectedDataLength) {
|
|
141
|
+
throw new Error(`Invalid PAM data length: expected ${expectedDataLength}, got ${actualDataLength}`);
|
|
142
|
+
}
|
|
143
|
+
// Extract pixel data
|
|
144
|
+
const pixelData = new Uint8Array(expectedDataLength);
|
|
145
|
+
pixelData.set(data.subarray(offset, offset + expectedDataLength));
|
|
146
|
+
return Promise.resolve({ width, height, data: pixelData });
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Encode RGBA image data to PAM format
|
|
150
|
+
* @param imageData Image data to encode
|
|
151
|
+
* @returns Encoded PAM image bytes
|
|
152
|
+
*/
|
|
153
|
+
encode(imageData) {
|
|
154
|
+
const { width, height, data } = imageData;
|
|
155
|
+
// Validate input
|
|
156
|
+
if (data.length !== width * height * 4) {
|
|
157
|
+
throw new Error(`Data length mismatch: expected ${width * height * 4}, got ${data.length}`);
|
|
158
|
+
}
|
|
159
|
+
// Create header
|
|
160
|
+
const header = `P7\n` +
|
|
161
|
+
`WIDTH ${width}\n` +
|
|
162
|
+
`HEIGHT ${height}\n` +
|
|
163
|
+
`DEPTH 4\n` +
|
|
164
|
+
`MAXVAL 255\n` +
|
|
165
|
+
`TUPLTYPE RGB_ALPHA\n` +
|
|
166
|
+
`ENDHDR\n`;
|
|
167
|
+
const encoder = new TextEncoder();
|
|
168
|
+
const headerBytes = encoder.encode(header);
|
|
169
|
+
// Create output buffer
|
|
170
|
+
const output = new Uint8Array(headerBytes.length + data.length);
|
|
171
|
+
// Write header
|
|
172
|
+
output.set(headerBytes, 0);
|
|
173
|
+
// Write pixel data
|
|
174
|
+
output.set(data, headerBytes.length);
|
|
175
|
+
return Promise.resolve(output);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ImageData, ImageFormat } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* PCX format handler
|
|
4
|
+
* Implements PCX decoder and encoder
|
|
5
|
+
*/
|
|
6
|
+
export declare class PCXFormat implements ImageFormat {
|
|
7
|
+
readonly name = "pcx";
|
|
8
|
+
readonly mimeType = "image/x-pcx";
|
|
9
|
+
canDecode(data: Uint8Array): boolean;
|
|
10
|
+
decode(data: Uint8Array): Promise<ImageData>;
|
|
11
|
+
encode(image: ImageData): Promise<Uint8Array>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=pcx.d.ts.map
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PCX format handler
|
|
3
|
+
* Implements PCX decoder and encoder
|
|
4
|
+
*/
|
|
5
|
+
export class PCXFormat {
|
|
6
|
+
constructor() {
|
|
7
|
+
Object.defineProperty(this, "name", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true,
|
|
11
|
+
value: "pcx"
|
|
12
|
+
});
|
|
13
|
+
Object.defineProperty(this, "mimeType", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
configurable: true,
|
|
16
|
+
writable: true,
|
|
17
|
+
value: "image/x-pcx"
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
canDecode(data) {
|
|
21
|
+
// PCX header check
|
|
22
|
+
// Byte 0: Manufacturer (must be 0x0A)
|
|
23
|
+
// Byte 1: Version (0, 2, 3, 4, 5)
|
|
24
|
+
// Byte 2: Encoding (1 = RLE)
|
|
25
|
+
return data.length >= 128 &&
|
|
26
|
+
data[0] === 0x0A &&
|
|
27
|
+
(data[1] === 0 || data[1] === 2 || data[1] === 3 || data[1] === 4 ||
|
|
28
|
+
data[1] === 5) &&
|
|
29
|
+
data[2] === 1;
|
|
30
|
+
}
|
|
31
|
+
decode(data) {
|
|
32
|
+
if (!this.canDecode(data)) {
|
|
33
|
+
return Promise.reject(new Error("Invalid PCX data"));
|
|
34
|
+
}
|
|
35
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
36
|
+
// Parse header
|
|
37
|
+
// const manufacturer = view.getUint8(0);
|
|
38
|
+
// const version = view.getUint8(1);
|
|
39
|
+
// const encoding = view.getUint8(2);
|
|
40
|
+
const bitsPerPixel = view.getUint8(3);
|
|
41
|
+
const xMin = view.getUint16(4, true);
|
|
42
|
+
const yMin = view.getUint16(6, true);
|
|
43
|
+
const xMax = view.getUint16(8, true);
|
|
44
|
+
const yMax = view.getUint16(10, true);
|
|
45
|
+
// const hDpi = view.getUint16(12, true);
|
|
46
|
+
// const vDpi = view.getUint16(14, true);
|
|
47
|
+
// const colormap = data.slice(16, 64);
|
|
48
|
+
// const reserved = view.getUint8(64);
|
|
49
|
+
const nPlanes = view.getUint8(65);
|
|
50
|
+
const bytesPerLine = view.getUint16(66, true);
|
|
51
|
+
// const paletteInfo = view.getUint16(68, true);
|
|
52
|
+
// const hScreenSize = view.getUint16(70, true);
|
|
53
|
+
// const vScreenSize = view.getUint16(72, true);
|
|
54
|
+
const width = xMax - xMin + 1;
|
|
55
|
+
const height = yMax - yMin + 1;
|
|
56
|
+
if (width <= 0 || height <= 0) {
|
|
57
|
+
return Promise.reject(new Error("Invalid PCX dimensions"));
|
|
58
|
+
}
|
|
59
|
+
// Decode RLE data
|
|
60
|
+
let offset = 128;
|
|
61
|
+
const scanlineLength = nPlanes * bytesPerLine;
|
|
62
|
+
const rawData = new Uint8Array(height * scanlineLength);
|
|
63
|
+
let ptr = 0;
|
|
64
|
+
// Decode all scanlines
|
|
65
|
+
for (let y = 0; y < height; y++) {
|
|
66
|
+
let x = 0;
|
|
67
|
+
while (x < scanlineLength) {
|
|
68
|
+
if (offset >= data.length)
|
|
69
|
+
break;
|
|
70
|
+
let byte = data[offset++];
|
|
71
|
+
let count = 1;
|
|
72
|
+
if ((byte & 0xC0) === 0xC0) {
|
|
73
|
+
count = byte & 0x3F;
|
|
74
|
+
if (offset >= data.length)
|
|
75
|
+
break;
|
|
76
|
+
byte = data[offset++];
|
|
77
|
+
}
|
|
78
|
+
for (let i = 0; i < count; i++) {
|
|
79
|
+
if (ptr < rawData.length) {
|
|
80
|
+
rawData[ptr++] = byte;
|
|
81
|
+
}
|
|
82
|
+
x++;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const rgba = new Uint8Array(width * height * 4);
|
|
87
|
+
if (nPlanes === 3 && bitsPerPixel === 8) {
|
|
88
|
+
// 24-bit RGB
|
|
89
|
+
for (let y = 0; y < height; y++) {
|
|
90
|
+
for (let x = 0; x < width; x++) {
|
|
91
|
+
const r = rawData[y * scanlineLength + x];
|
|
92
|
+
const g = rawData[y * scanlineLength + bytesPerLine + x];
|
|
93
|
+
const b = rawData[y * scanlineLength + 2 * bytesPerLine + x];
|
|
94
|
+
const idx = (y * width + x) * 4;
|
|
95
|
+
rgba[idx] = r;
|
|
96
|
+
rgba[idx + 1] = g;
|
|
97
|
+
rgba[idx + 2] = b;
|
|
98
|
+
rgba[idx + 3] = 255;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (nPlanes === 1 && bitsPerPixel === 8) {
|
|
103
|
+
// 8-bit palette
|
|
104
|
+
// Check for palette at end of file
|
|
105
|
+
let palette;
|
|
106
|
+
if (data[data.length - 769] === 0x0C) {
|
|
107
|
+
palette = data.slice(data.length - 768);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Fallback or error?
|
|
111
|
+
// Some old PCX might use header palette but that's only 16 colors.
|
|
112
|
+
// For 8bpp we expect 256 color palette at end.
|
|
113
|
+
return Promise.reject(new Error("Missing PCX palette"));
|
|
114
|
+
}
|
|
115
|
+
for (let y = 0; y < height; y++) {
|
|
116
|
+
for (let x = 0; x < width; x++) {
|
|
117
|
+
const colorIndex = rawData[y * scanlineLength + x];
|
|
118
|
+
const idx = (y * width + x) * 4;
|
|
119
|
+
rgba[idx] = palette[colorIndex * 3];
|
|
120
|
+
rgba[idx + 1] = palette[colorIndex * 3 + 1];
|
|
121
|
+
rgba[idx + 2] = palette[colorIndex * 3 + 2];
|
|
122
|
+
rgba[idx + 3] = 255;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
// Unsupported PCX format (e.g. 1-bit, 4-bit)
|
|
128
|
+
// For now only supporting 24-bit and 8-bit
|
|
129
|
+
return Promise.reject(new Error("Unsupported PCX format"));
|
|
130
|
+
}
|
|
131
|
+
return Promise.resolve({
|
|
132
|
+
width,
|
|
133
|
+
height,
|
|
134
|
+
data: rgba,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
encode(image) {
|
|
138
|
+
const width = image.width;
|
|
139
|
+
const height = image.height;
|
|
140
|
+
const data = image.data;
|
|
141
|
+
// We will encode as 24-bit RGB (3 planes)
|
|
142
|
+
const header = new Uint8Array(128);
|
|
143
|
+
const view = new DataView(header.buffer);
|
|
144
|
+
view.setUint8(0, 0x0A); // Manufacturer
|
|
145
|
+
view.setUint8(1, 5); // Version 3.0+
|
|
146
|
+
view.setUint8(2, 1); // Encoding RLE
|
|
147
|
+
view.setUint8(3, 8); // Bits per pixel (8 per plane)
|
|
148
|
+
view.setUint16(4, 0, true); // XMin
|
|
149
|
+
view.setUint16(6, 0, true); // YMin
|
|
150
|
+
view.setUint16(8, width - 1, true); // XMax
|
|
151
|
+
view.setUint16(10, height - 1, true); // YMax
|
|
152
|
+
view.setUint16(12, 72, true); // HDpi
|
|
153
|
+
view.setUint16(14, 72, true); // VDpi
|
|
154
|
+
view.setUint8(65, 3); // NPlanes (3 for RGB)
|
|
155
|
+
view.setUint16(66, width + (width % 2), true); // BytesPerLine (must be even)
|
|
156
|
+
view.setUint16(68, 1, true); // PaletteInfo (Color/BW)
|
|
157
|
+
const bytesPerLine = width + (width % 2);
|
|
158
|
+
const scanlineLength = bytesPerLine * 3;
|
|
159
|
+
const rleData = [];
|
|
160
|
+
// Helper to write RLE
|
|
161
|
+
const writeRLE = (byte, count) => {
|
|
162
|
+
if ((byte & 0xC0) === 0xC0 || count > 1) {
|
|
163
|
+
rleData.push(0xC0 | count);
|
|
164
|
+
rleData.push(byte);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
rleData.push(byte);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
for (let y = 0; y < height; y++) {
|
|
171
|
+
// Prepare scanline planes
|
|
172
|
+
const lineR = new Uint8Array(bytesPerLine);
|
|
173
|
+
const lineG = new Uint8Array(bytesPerLine);
|
|
174
|
+
const lineB = new Uint8Array(bytesPerLine);
|
|
175
|
+
for (let x = 0; x < width; x++) {
|
|
176
|
+
const idx = (y * width + x) * 4;
|
|
177
|
+
lineR[x] = data[idx];
|
|
178
|
+
lineG[x] = data[idx + 1];
|
|
179
|
+
lineB[x] = data[idx + 2];
|
|
180
|
+
}
|
|
181
|
+
// Compress each plane
|
|
182
|
+
for (const plane of [lineR, lineG, lineB]) {
|
|
183
|
+
let currentByte = plane[0];
|
|
184
|
+
let runLength = 1;
|
|
185
|
+
for (let x = 1; x < bytesPerLine; x++) {
|
|
186
|
+
const byte = plane[x];
|
|
187
|
+
if (byte === currentByte && runLength < 63) {
|
|
188
|
+
runLength++;
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
writeRLE(currentByte, runLength);
|
|
192
|
+
currentByte = byte;
|
|
193
|
+
runLength = 1;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
writeRLE(currentByte, runLength);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const result = new Uint8Array(header.length + rleData.length);
|
|
200
|
+
result.set(header);
|
|
201
|
+
result.set(rleData, header.length);
|
|
202
|
+
return Promise.resolve(result);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -15,9 +15,9 @@ export interface TIFFEncodeOptions {
|
|
|
15
15
|
*/
|
|
16
16
|
export declare class TIFFFormat implements ImageFormat {
|
|
17
17
|
/** Format name identifier */
|
|
18
|
-
readonly name
|
|
18
|
+
readonly name: string;
|
|
19
19
|
/** MIME type for TIFF images */
|
|
20
|
-
readonly mimeType
|
|
20
|
+
readonly mimeType: string;
|
|
21
21
|
/**
|
|
22
22
|
* Check if this format supports multiple frames (pages)
|
|
23
23
|
* @returns true for TIFF format
|
|
@@ -52,11 +52,11 @@ export declare class TIFFFormat implements ImageFormat {
|
|
|
52
52
|
* Extract metadata from an IFD
|
|
53
53
|
*/
|
|
54
54
|
private extractMetadataFromIFD;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
protected readUint16(data: Uint8Array, offset: number, isLittleEndian: boolean): number;
|
|
56
|
+
protected readUint32(data: Uint8Array, offset: number, isLittleEndian: boolean): number;
|
|
57
|
+
protected writeUint16LE(result: number[], value: number): void;
|
|
58
|
+
protected writeUint32LE(result: number[], value: number): void;
|
|
59
|
+
protected writeIFDEntry(result: number[], tag: number, type: number, count: number, valueOrOffset: number): void;
|
|
60
60
|
private getIFDValue;
|
|
61
61
|
private decodeUsingRuntime;
|
|
62
62
|
private readString;
|
package/esm/src/image.d.ts
CHANGED
|
@@ -72,24 +72,49 @@ export declare class Image {
|
|
|
72
72
|
* Get all registered formats
|
|
73
73
|
*/
|
|
74
74
|
static getFormats(): readonly ImageFormat[];
|
|
75
|
+
/**
|
|
76
|
+
* Decode an image from bytes
|
|
77
|
+
* @param data Raw image data
|
|
78
|
+
* @param format Optional format hint (e.g., "png", "jpeg", "webp")
|
|
79
|
+
* @returns Image instance
|
|
80
|
+
*/
|
|
81
|
+
static decode(data: Uint8Array, format?: string): Promise<Image>;
|
|
75
82
|
/**
|
|
76
83
|
* Read an image from bytes
|
|
84
|
+
* @deprecated Use `decode()` instead. This method will be removed in a future version.
|
|
77
85
|
* @param data Raw image data
|
|
78
86
|
* @param format Optional format hint (e.g., "png", "jpeg", "webp")
|
|
79
87
|
* @returns Image instance
|
|
80
88
|
*/
|
|
81
89
|
static read(data: Uint8Array, format?: string): Promise<Image>;
|
|
90
|
+
/**
|
|
91
|
+
* Decode all frames from a multi-frame image (GIF animation, multi-page TIFF)
|
|
92
|
+
* @param data Raw image data
|
|
93
|
+
* @param format Optional format hint (e.g., "gif", "tiff")
|
|
94
|
+
* @returns MultiFrameImageData with all frames
|
|
95
|
+
*/
|
|
96
|
+
static decodeFrames(data: Uint8Array, format?: string): Promise<MultiFrameImageData>;
|
|
82
97
|
/**
|
|
83
98
|
* Read all frames from a multi-frame image (GIF animation, multi-page TIFF)
|
|
99
|
+
* @deprecated Use `decodeFrames()` instead. This method will be removed in a future version.
|
|
84
100
|
* @param data Raw image data
|
|
85
101
|
* @param format Optional format hint (e.g., "gif", "tiff")
|
|
86
102
|
* @returns MultiFrameImageData with all frames
|
|
87
103
|
*/
|
|
88
104
|
static readFrames(data: Uint8Array, format?: string): Promise<MultiFrameImageData>;
|
|
105
|
+
/**
|
|
106
|
+
* Encode multi-frame image data to bytes in the specified format
|
|
107
|
+
* @param format Format name (e.g., "gif", "tiff")
|
|
108
|
+
* @param imageData Multi-frame image data to encode
|
|
109
|
+
* @param options Optional format-specific encoding options
|
|
110
|
+
* @returns Encoded image bytes
|
|
111
|
+
*/
|
|
112
|
+
static encodeFrames(format: string, imageData: MultiFrameImageData, options?: unknown): Promise<Uint8Array>;
|
|
89
113
|
/**
|
|
90
114
|
* Save multi-frame image data to bytes in the specified format
|
|
115
|
+
* @deprecated Use `encodeFrames()` instead. This method will be removed in a future version.
|
|
91
116
|
* @param format Format name (e.g., "gif", "tiff")
|
|
92
|
-
* @param imageData Multi-frame image data to
|
|
117
|
+
* @param imageData Multi-frame image data to encode
|
|
93
118
|
* @param options Optional format-specific encoding options
|
|
94
119
|
* @returns Encoded image bytes
|
|
95
120
|
*/
|
|
@@ -102,14 +127,33 @@ export declare class Image {
|
|
|
102
127
|
* @returns Image instance
|
|
103
128
|
*/
|
|
104
129
|
static fromRGBA(width: number, height: number, data: Uint8Array): Image;
|
|
130
|
+
/**
|
|
131
|
+
* Create a blank image with the specified dimensions and color
|
|
132
|
+
* @param width Image width
|
|
133
|
+
* @param height Image height
|
|
134
|
+
* @param r Red component (0-255, default: 0)
|
|
135
|
+
* @param g Green component (0-255, default: 0)
|
|
136
|
+
* @param b Blue component (0-255, default: 0)
|
|
137
|
+
* @param a Alpha component (0-255, default: 255)
|
|
138
|
+
* @returns Image instance
|
|
139
|
+
*/
|
|
140
|
+
static create(width: number, height: number, r?: number, g?: number, b?: number, a?: number): Image;
|
|
105
141
|
/**
|
|
106
142
|
* Resize the image
|
|
107
143
|
* @param options Resize options
|
|
108
144
|
* @returns This image instance for chaining
|
|
109
145
|
*/
|
|
110
146
|
resize(options: ResizeOptions): this;
|
|
147
|
+
/**
|
|
148
|
+
* Encode the image to bytes in the specified format
|
|
149
|
+
* @param format Format name (e.g., "png", "jpeg", "webp", "ascii")
|
|
150
|
+
* @param options Optional format-specific encoding options
|
|
151
|
+
* @returns Encoded image bytes
|
|
152
|
+
*/
|
|
153
|
+
encode(format: string, options?: unknown): Promise<Uint8Array>;
|
|
111
154
|
/**
|
|
112
155
|
* Save the image to bytes in the specified format
|
|
156
|
+
* @deprecated Use `encode()` instead. This method will be removed in a future version.
|
|
113
157
|
* @param format Format name (e.g., "png", "jpeg", "webp", "ascii")
|
|
114
158
|
* @param options Optional format-specific encoding options
|
|
115
159
|
* @returns Encoded image bytes
|
|
@@ -120,5 +164,93 @@ export declare class Image {
|
|
|
120
164
|
* @returns New image instance with copied data and metadata
|
|
121
165
|
*/
|
|
122
166
|
clone(): Image;
|
|
167
|
+
/**
|
|
168
|
+
* Composite another image on top of this image at the specified position
|
|
169
|
+
* @param overlay Image to place on top
|
|
170
|
+
* @param x X position (can be negative)
|
|
171
|
+
* @param y Y position (can be negative)
|
|
172
|
+
* @param opacity Opacity of overlay (0-1, default: 1)
|
|
173
|
+
* @returns This image instance for chaining
|
|
174
|
+
*/
|
|
175
|
+
composite(overlay: Image, x: number, y: number, opacity?: number): this;
|
|
176
|
+
/**
|
|
177
|
+
* Adjust brightness of the image
|
|
178
|
+
* @param amount Brightness adjustment (-1 to 1, where 0 is no change)
|
|
179
|
+
* @returns This image instance for chaining
|
|
180
|
+
*/
|
|
181
|
+
brightness(amount: number): this;
|
|
182
|
+
/**
|
|
183
|
+
* Adjust contrast of the image
|
|
184
|
+
* @param amount Contrast adjustment (-1 to 1, where 0 is no change)
|
|
185
|
+
* @returns This image instance for chaining
|
|
186
|
+
*/
|
|
187
|
+
contrast(amount: number): this;
|
|
188
|
+
/**
|
|
189
|
+
* Adjust exposure of the image
|
|
190
|
+
* @param amount Exposure adjustment in stops (-3 to 3, where 0 is no change)
|
|
191
|
+
* @returns This image instance for chaining
|
|
192
|
+
*/
|
|
193
|
+
exposure(amount: number): this;
|
|
194
|
+
/**
|
|
195
|
+
* Adjust saturation of the image
|
|
196
|
+
* @param amount Saturation adjustment (-1 to 1, where 0 is no change)
|
|
197
|
+
* @returns This image instance for chaining
|
|
198
|
+
*/
|
|
199
|
+
saturation(amount: number): this;
|
|
200
|
+
/**
|
|
201
|
+
* Invert colors of the image
|
|
202
|
+
* @returns This image instance for chaining
|
|
203
|
+
*/
|
|
204
|
+
invert(): this;
|
|
205
|
+
/**
|
|
206
|
+
* Convert the image to grayscale
|
|
207
|
+
* @returns This image instance for chaining
|
|
208
|
+
*/
|
|
209
|
+
grayscale(): this;
|
|
210
|
+
/**
|
|
211
|
+
* Fill a rectangular region with a color
|
|
212
|
+
* @param x Starting X position
|
|
213
|
+
* @param y Starting Y position
|
|
214
|
+
* @param width Width of the fill region
|
|
215
|
+
* @param height Height of the fill region
|
|
216
|
+
* @param r Red component (0-255)
|
|
217
|
+
* @param g Green component (0-255)
|
|
218
|
+
* @param b Blue component (0-255)
|
|
219
|
+
* @param a Alpha component (0-255, default: 255)
|
|
220
|
+
* @returns This image instance for chaining
|
|
221
|
+
*/
|
|
222
|
+
fillRect(x: number, y: number, width: number, height: number, r: number, g: number, b: number, a?: number): this;
|
|
223
|
+
/**
|
|
224
|
+
* Crop the image to a rectangular region
|
|
225
|
+
* @param x Starting X position
|
|
226
|
+
* @param y Starting Y position
|
|
227
|
+
* @param width Width of the crop region
|
|
228
|
+
* @param height Height of the crop region
|
|
229
|
+
* @returns This image instance for chaining
|
|
230
|
+
*/
|
|
231
|
+
crop(x: number, y: number, width: number, height: number): this;
|
|
232
|
+
/**
|
|
233
|
+
* Get the pixel color at the specified position
|
|
234
|
+
* @param x X position
|
|
235
|
+
* @param y Y position
|
|
236
|
+
* @returns Object with r, g, b, a components (0-255) or undefined if out of bounds
|
|
237
|
+
*/
|
|
238
|
+
getPixel(x: number, y: number): {
|
|
239
|
+
r: number;
|
|
240
|
+
g: number;
|
|
241
|
+
b: number;
|
|
242
|
+
a: number;
|
|
243
|
+
} | undefined;
|
|
244
|
+
/**
|
|
245
|
+
* Set the pixel color at the specified position
|
|
246
|
+
* @param x X position
|
|
247
|
+
* @param y Y position
|
|
248
|
+
* @param r Red component (0-255)
|
|
249
|
+
* @param g Green component (0-255)
|
|
250
|
+
* @param b Blue component (0-255)
|
|
251
|
+
* @param a Alpha component (0-255, default: 255)
|
|
252
|
+
* @returns This image instance for chaining
|
|
253
|
+
*/
|
|
254
|
+
setPixel(x: number, y: number, r: number, g: number, b: number, a?: number): this;
|
|
123
255
|
}
|
|
124
256
|
//# sourceMappingURL=image.d.ts.map
|