cross-image 0.2.4 → 0.4.1
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/LICENSE +21 -21
- package/README.md +615 -333
- package/esm/mod.d.ts +6 -4
- package/esm/mod.js +4 -2
- package/esm/src/formats/apng.d.ts +7 -5
- package/esm/src/formats/apng.js +15 -10
- package/esm/src/formats/ascii.d.ts +3 -3
- package/esm/src/formats/ascii.js +1 -1
- package/esm/src/formats/avif.d.ts +3 -3
- package/esm/src/formats/avif.js +17 -7
- package/esm/src/formats/bmp.d.ts +3 -3
- package/esm/src/formats/bmp.js +2 -2
- package/esm/src/formats/dng.d.ts +1 -1
- package/esm/src/formats/dng.js +1 -1
- package/esm/src/formats/gif.d.ts +5 -5
- package/esm/src/formats/gif.js +17 -13
- package/esm/src/formats/heic.d.ts +3 -3
- package/esm/src/formats/heic.js +17 -7
- package/esm/src/formats/ico.d.ts +3 -3
- package/esm/src/formats/ico.js +4 -4
- package/esm/src/formats/jpeg.d.ts +3 -3
- package/esm/src/formats/jpeg.js +23 -11
- package/esm/src/formats/pam.d.ts +3 -3
- package/esm/src/formats/pam.js +2 -2
- package/esm/src/formats/pcx.d.ts +3 -3
- package/esm/src/formats/pcx.js +2 -2
- package/esm/src/formats/png.d.ts +4 -3
- package/esm/src/formats/png.js +9 -3
- package/esm/src/formats/png_base.d.ts +42 -1
- package/esm/src/formats/png_base.js +200 -10
- package/esm/src/formats/ppm.d.ts +3 -3
- package/esm/src/formats/ppm.js +2 -2
- package/esm/src/formats/tiff.d.ts +7 -18
- package/esm/src/formats/tiff.js +162 -27
- package/esm/src/formats/webp.d.ts +3 -3
- package/esm/src/formats/webp.js +11 -8
- package/esm/src/image.d.ts +26 -3
- package/esm/src/image.js +66 -22
- package/esm/src/types.d.ts +122 -4
- package/esm/src/utils/base64.d.ts +32 -0
- package/esm/src/utils/base64.js +173 -0
- package/esm/src/utils/gif_decoder.d.ts +4 -1
- package/esm/src/utils/gif_decoder.js +91 -65
- package/esm/src/utils/gif_encoder.d.ts +3 -1
- package/esm/src/utils/gif_encoder.js +4 -2
- package/esm/src/utils/image_processing.d.ts +31 -0
- package/esm/src/utils/image_processing.js +232 -70
- package/esm/src/utils/jpeg_decoder.d.ts +17 -4
- package/esm/src/utils/jpeg_decoder.js +448 -83
- package/esm/src/utils/jpeg_encoder.d.ts +15 -1
- package/esm/src/utils/jpeg_encoder.js +263 -24
- package/esm/src/utils/resize.js +51 -20
- package/esm/src/utils/tiff_deflate.d.ts +18 -0
- package/esm/src/utils/tiff_deflate.js +27 -0
- package/esm/src/utils/tiff_packbits.d.ts +24 -0
- package/esm/src/utils/tiff_packbits.js +90 -0
- package/esm/src/utils/webp_decoder.d.ts +3 -1
- package/esm/src/utils/webp_decoder.js +144 -63
- package/esm/src/utils/webp_encoder.js +5 -11
- package/package.json +1 -1
- package/script/mod.d.ts +6 -4
- package/script/mod.js +13 -3
- package/script/src/formats/apng.d.ts +7 -5
- package/script/src/formats/apng.js +15 -10
- package/script/src/formats/ascii.d.ts +3 -3
- package/script/src/formats/ascii.js +1 -1
- package/script/src/formats/avif.d.ts +3 -3
- package/script/src/formats/avif.js +17 -7
- package/script/src/formats/bmp.d.ts +3 -3
- package/script/src/formats/bmp.js +2 -2
- package/script/src/formats/dng.d.ts +1 -1
- package/script/src/formats/dng.js +1 -1
- package/script/src/formats/gif.d.ts +5 -5
- package/script/src/formats/gif.js +17 -13
- package/script/src/formats/heic.d.ts +3 -3
- package/script/src/formats/heic.js +17 -7
- package/script/src/formats/ico.d.ts +3 -3
- package/script/src/formats/ico.js +4 -4
- package/script/src/formats/jpeg.d.ts +3 -3
- package/script/src/formats/jpeg.js +23 -11
- package/script/src/formats/pam.d.ts +3 -3
- package/script/src/formats/pam.js +2 -2
- package/script/src/formats/pcx.d.ts +3 -3
- package/script/src/formats/pcx.js +2 -2
- package/script/src/formats/png.d.ts +4 -3
- package/script/src/formats/png.js +9 -3
- package/script/src/formats/png_base.d.ts +42 -1
- package/script/src/formats/png_base.js +200 -10
- package/script/src/formats/ppm.d.ts +3 -3
- package/script/src/formats/ppm.js +2 -2
- package/script/src/formats/tiff.d.ts +7 -18
- package/script/src/formats/tiff.js +162 -27
- package/script/src/formats/webp.d.ts +3 -3
- package/script/src/formats/webp.js +11 -8
- package/script/src/image.d.ts +26 -3
- package/script/src/image.js +64 -20
- package/script/src/types.d.ts +122 -4
- package/script/src/utils/base64.d.ts +32 -0
- package/script/src/utils/base64.js +179 -0
- package/script/src/utils/gif_decoder.d.ts +4 -1
- package/script/src/utils/gif_decoder.js +91 -65
- package/script/src/utils/gif_encoder.d.ts +3 -1
- package/script/src/utils/gif_encoder.js +4 -2
- package/script/src/utils/image_processing.d.ts +31 -0
- package/script/src/utils/image_processing.js +236 -70
- package/script/src/utils/jpeg_decoder.d.ts +17 -4
- package/script/src/utils/jpeg_decoder.js +448 -83
- package/script/src/utils/jpeg_encoder.d.ts +15 -1
- package/script/src/utils/jpeg_encoder.js +263 -24
- package/script/src/utils/resize.js +51 -20
- package/script/src/utils/tiff_deflate.d.ts +18 -0
- package/script/src/utils/tiff_deflate.js +31 -0
- package/script/src/utils/tiff_packbits.d.ts +24 -0
- package/script/src/utils/tiff_packbits.js +94 -0
- package/script/src/utils/webp_decoder.d.ts +3 -1
- package/script/src/utils/webp_decoder.js +144 -63
- package/script/src/utils/webp_encoder.js +5 -11
|
@@ -43,7 +43,48 @@ export declare abstract class PNGBase {
|
|
|
43
43
|
/**
|
|
44
44
|
* Filter PNG data for encoding (using filter type 0 - None)
|
|
45
45
|
*/
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Apply PNG filter to image data based on compression level
|
|
48
|
+
* @param data Raw RGBA pixel data
|
|
49
|
+
* @param width Image width
|
|
50
|
+
* @param height Image height
|
|
51
|
+
* @param compressionLevel Compression level (0-9, default 6)
|
|
52
|
+
* @returns Filtered data with filter type byte per scanline
|
|
53
|
+
*/
|
|
54
|
+
protected filterData(data: Uint8Array, width: number, height: number, compressionLevel?: number): Uint8Array;
|
|
55
|
+
/**
|
|
56
|
+
* Apply filter type 0 (None) - no filtering
|
|
57
|
+
*/
|
|
58
|
+
private applyNoFilter;
|
|
59
|
+
/**
|
|
60
|
+
* Apply filter type 1 (Sub) - subtract left pixel
|
|
61
|
+
*/
|
|
62
|
+
private applySubFilter;
|
|
63
|
+
/**
|
|
64
|
+
* Apply filter type 2 (Up) - subtract above pixel
|
|
65
|
+
*/
|
|
66
|
+
private applyUpFilter;
|
|
67
|
+
/**
|
|
68
|
+
* Apply filter type 3 (Average) - subtract average of left and above
|
|
69
|
+
*/
|
|
70
|
+
private applyAverageFilter;
|
|
71
|
+
/**
|
|
72
|
+
* Apply filter type 4 (Paeth) - Paeth predictor
|
|
73
|
+
*/
|
|
74
|
+
private applyPaethFilter;
|
|
75
|
+
/**
|
|
76
|
+
* Calculate sum of absolute differences for a filtered scanline
|
|
77
|
+
* Lower values indicate better compression potential
|
|
78
|
+
*/
|
|
79
|
+
private calculateFilterScore;
|
|
80
|
+
/**
|
|
81
|
+
* Apply adaptive filtering - choose best filter per scanline
|
|
82
|
+
*/
|
|
83
|
+
private applyAdaptiveFilter;
|
|
84
|
+
/**
|
|
85
|
+
* Filter a single scanline with specified filter type
|
|
86
|
+
*/
|
|
87
|
+
private filterScanline;
|
|
47
88
|
/**
|
|
48
89
|
* Get bytes per pixel for a given color type and bit depth
|
|
49
90
|
*/
|
|
@@ -108,9 +108,7 @@ class PNGBase {
|
|
|
108
108
|
for (let x = 0; x < scanline.length; x++) {
|
|
109
109
|
const left = x >= bytesPerPixel ? scanline[x - bytesPerPixel] : 0;
|
|
110
110
|
const above = prevLine ? prevLine[x] : 0;
|
|
111
|
-
const upperLeft = (x >= bytesPerPixel && prevLine)
|
|
112
|
-
? prevLine[x - bytesPerPixel]
|
|
113
|
-
: 0;
|
|
111
|
+
const upperLeft = (x >= bytesPerPixel && prevLine) ? prevLine[x - bytesPerPixel] : 0;
|
|
114
112
|
switch (filterType) {
|
|
115
113
|
case 0: // None
|
|
116
114
|
break;
|
|
@@ -124,8 +122,7 @@ class PNGBase {
|
|
|
124
122
|
scanline[x] = (scanline[x] + Math.floor((left + above) / 2)) & 0xff;
|
|
125
123
|
break;
|
|
126
124
|
case 4: // Paeth
|
|
127
|
-
scanline[x] =
|
|
128
|
-
(scanline[x] + this.paethPredictor(left, above, upperLeft)) & 0xff;
|
|
125
|
+
scanline[x] = (scanline[x] + this.paethPredictor(left, above, upperLeft)) & 0xff;
|
|
129
126
|
break;
|
|
130
127
|
}
|
|
131
128
|
}
|
|
@@ -147,18 +144,211 @@ class PNGBase {
|
|
|
147
144
|
/**
|
|
148
145
|
* Filter PNG data for encoding (using filter type 0 - None)
|
|
149
146
|
*/
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Apply PNG filter to image data based on compression level
|
|
149
|
+
* @param data Raw RGBA pixel data
|
|
150
|
+
* @param width Image width
|
|
151
|
+
* @param height Image height
|
|
152
|
+
* @param compressionLevel Compression level (0-9, default 6)
|
|
153
|
+
* @returns Filtered data with filter type byte per scanline
|
|
154
|
+
*/
|
|
155
|
+
filterData(data, width, height, compressionLevel = 6) {
|
|
156
|
+
// Choose filtering strategy based on compression level
|
|
157
|
+
if (compressionLevel <= 2) {
|
|
158
|
+
// Fast: No filtering
|
|
159
|
+
return this.applyNoFilter(data, width, height);
|
|
160
|
+
}
|
|
161
|
+
else if (compressionLevel <= 6) {
|
|
162
|
+
// Balanced: Sub filter
|
|
163
|
+
return this.applySubFilter(data, width, height);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// Best: Adaptive filtering (choose best filter per scanline)
|
|
167
|
+
return this.applyAdaptiveFilter(data, width, height);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Apply filter type 0 (None) - no filtering
|
|
172
|
+
*/
|
|
173
|
+
applyNoFilter(data, width, height) {
|
|
174
|
+
const bytesPerScanline = width * 4;
|
|
175
|
+
const filtered = new Uint8Array(height * (1 + bytesPerScanline));
|
|
153
176
|
let pos = 0;
|
|
154
177
|
for (let y = 0; y < height; y++) {
|
|
155
178
|
filtered[pos++] = 0; // Filter type: None
|
|
156
|
-
|
|
157
|
-
|
|
179
|
+
const scanlineStart = y * bytesPerScanline;
|
|
180
|
+
for (let x = 0; x < bytesPerScanline; x++) {
|
|
181
|
+
filtered[pos++] = data[scanlineStart + x];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return filtered;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Apply filter type 1 (Sub) - subtract left pixel
|
|
188
|
+
*/
|
|
189
|
+
applySubFilter(data, width, height) {
|
|
190
|
+
const bytesPerScanline = width * 4;
|
|
191
|
+
const filtered = new Uint8Array(height * (1 + bytesPerScanline));
|
|
192
|
+
let pos = 0;
|
|
193
|
+
for (let y = 0; y < height; y++) {
|
|
194
|
+
filtered[pos++] = 1; // Filter type: Sub
|
|
195
|
+
const scanlineStart = y * bytesPerScanline;
|
|
196
|
+
for (let x = 0; x < bytesPerScanline; x++) {
|
|
197
|
+
const current = data[scanlineStart + x];
|
|
198
|
+
const left = x >= 4 ? data[scanlineStart + x - 4] : 0;
|
|
199
|
+
filtered[pos++] = (current - left) & 0xff;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return filtered;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Apply filter type 2 (Up) - subtract above pixel
|
|
206
|
+
*/
|
|
207
|
+
applyUpFilter(data, width, height) {
|
|
208
|
+
const bytesPerScanline = width * 4;
|
|
209
|
+
const filtered = new Uint8Array(height * (1 + bytesPerScanline));
|
|
210
|
+
let pos = 0;
|
|
211
|
+
for (let y = 0; y < height; y++) {
|
|
212
|
+
filtered[pos++] = 2; // Filter type: Up
|
|
213
|
+
const scanlineStart = y * bytesPerScanline;
|
|
214
|
+
const prevScanlineStart = (y - 1) * bytesPerScanline;
|
|
215
|
+
for (let x = 0; x < bytesPerScanline; x++) {
|
|
216
|
+
const current = data[scanlineStart + x];
|
|
217
|
+
const up = y > 0 ? data[prevScanlineStart + x] : 0;
|
|
218
|
+
filtered[pos++] = (current - up) & 0xff;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
return filtered;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Apply filter type 3 (Average) - subtract average of left and above
|
|
225
|
+
*/
|
|
226
|
+
applyAverageFilter(data, width, height) {
|
|
227
|
+
const bytesPerScanline = width * 4;
|
|
228
|
+
const filtered = new Uint8Array(height * (1 + bytesPerScanline));
|
|
229
|
+
let pos = 0;
|
|
230
|
+
for (let y = 0; y < height; y++) {
|
|
231
|
+
filtered[pos++] = 3; // Filter type: Average
|
|
232
|
+
const scanlineStart = y * bytesPerScanline;
|
|
233
|
+
const prevScanlineStart = (y - 1) * bytesPerScanline;
|
|
234
|
+
for (let x = 0; x < bytesPerScanline; x++) {
|
|
235
|
+
const current = data[scanlineStart + x];
|
|
236
|
+
const left = x >= 4 ? data[scanlineStart + x - 4] : 0;
|
|
237
|
+
const up = y > 0 ? data[prevScanlineStart + x] : 0;
|
|
238
|
+
const avg = Math.floor((left + up) / 2);
|
|
239
|
+
filtered[pos++] = (current - avg) & 0xff;
|
|
158
240
|
}
|
|
159
241
|
}
|
|
160
242
|
return filtered;
|
|
161
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Apply filter type 4 (Paeth) - Paeth predictor
|
|
246
|
+
*/
|
|
247
|
+
applyPaethFilter(data, width, height) {
|
|
248
|
+
const bytesPerScanline = width * 4;
|
|
249
|
+
const filtered = new Uint8Array(height * (1 + bytesPerScanline));
|
|
250
|
+
let pos = 0;
|
|
251
|
+
for (let y = 0; y < height; y++) {
|
|
252
|
+
filtered[pos++] = 4; // Filter type: Paeth
|
|
253
|
+
const scanlineStart = y * bytesPerScanline;
|
|
254
|
+
const prevScanlineStart = (y - 1) * bytesPerScanline;
|
|
255
|
+
for (let x = 0; x < bytesPerScanline; x++) {
|
|
256
|
+
const current = data[scanlineStart + x];
|
|
257
|
+
const left = x >= 4 ? data[scanlineStart + x - 4] : 0;
|
|
258
|
+
const up = y > 0 ? data[prevScanlineStart + x] : 0;
|
|
259
|
+
const upLeft = (y > 0 && x >= 4) ? data[prevScanlineStart + x - 4] : 0;
|
|
260
|
+
const paeth = this.paethPredictor(left, up, upLeft);
|
|
261
|
+
filtered[pos++] = (current - paeth) & 0xff;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return filtered;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Calculate sum of absolute differences for a filtered scanline
|
|
268
|
+
* Lower values indicate better compression potential
|
|
269
|
+
*/
|
|
270
|
+
calculateFilterScore(filtered) {
|
|
271
|
+
let sum = 0;
|
|
272
|
+
for (let i = 1; i < filtered.length; i++) {
|
|
273
|
+
const byte = filtered[i];
|
|
274
|
+
// Penalize larger absolute values
|
|
275
|
+
sum += byte < 128 ? byte : (256 - byte);
|
|
276
|
+
}
|
|
277
|
+
return sum;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Apply adaptive filtering - choose best filter per scanline
|
|
281
|
+
*/
|
|
282
|
+
applyAdaptiveFilter(data, width, height) {
|
|
283
|
+
const bytesPerScanline = width * 4;
|
|
284
|
+
const filtered = new Uint8Array(height * (1 + bytesPerScanline));
|
|
285
|
+
let outPos = 0;
|
|
286
|
+
// Try each filter type and choose the best for each scanline
|
|
287
|
+
const filters = [
|
|
288
|
+
(y) => this.filterScanline(data, y, width, 0), // None
|
|
289
|
+
(y) => this.filterScanline(data, y, width, 1), // Sub
|
|
290
|
+
(y) => this.filterScanline(data, y, width, 2), // Up
|
|
291
|
+
(y) => this.filterScanline(data, y, width, 3), // Average
|
|
292
|
+
(y) => this.filterScanline(data, y, width, 4), // Paeth
|
|
293
|
+
];
|
|
294
|
+
for (let y = 0; y < height; y++) {
|
|
295
|
+
let bestFilter = null;
|
|
296
|
+
let bestScore = Infinity;
|
|
297
|
+
// Try each filter type
|
|
298
|
+
for (const filterFn of filters) {
|
|
299
|
+
const result = filterFn(y);
|
|
300
|
+
const score = this.calculateFilterScore(result);
|
|
301
|
+
if (score < bestScore) {
|
|
302
|
+
bestScore = score;
|
|
303
|
+
bestFilter = result;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Copy best filter result
|
|
307
|
+
if (bestFilter) {
|
|
308
|
+
filtered.set(bestFilter, outPos);
|
|
309
|
+
outPos += bestFilter.length;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return filtered;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Filter a single scanline with specified filter type
|
|
316
|
+
*/
|
|
317
|
+
filterScanline(data, y, width, filterType) {
|
|
318
|
+
const bytesPerScanline = width * 4;
|
|
319
|
+
const result = new Uint8Array(1 + bytesPerScanline);
|
|
320
|
+
result[0] = filterType;
|
|
321
|
+
const scanlineStart = y * bytesPerScanline;
|
|
322
|
+
const prevScanlineStart = (y - 1) * bytesPerScanline;
|
|
323
|
+
for (let x = 0; x < bytesPerScanline; x++) {
|
|
324
|
+
const current = data[scanlineStart + x];
|
|
325
|
+
const left = x >= 4 ? data[scanlineStart + x - 4] : 0;
|
|
326
|
+
const up = y > 0 ? data[prevScanlineStart + x] : 0;
|
|
327
|
+
const upLeft = (y > 0 && x >= 4) ? data[prevScanlineStart + x - 4] : 0;
|
|
328
|
+
let filtered;
|
|
329
|
+
switch (filterType) {
|
|
330
|
+
case 0: // None
|
|
331
|
+
filtered = current;
|
|
332
|
+
break;
|
|
333
|
+
case 1: // Sub
|
|
334
|
+
filtered = (current - left) & 0xff;
|
|
335
|
+
break;
|
|
336
|
+
case 2: // Up
|
|
337
|
+
filtered = (current - up) & 0xff;
|
|
338
|
+
break;
|
|
339
|
+
case 3: // Average
|
|
340
|
+
filtered = (current - Math.floor((left + up) / 2)) & 0xff;
|
|
341
|
+
break;
|
|
342
|
+
case 4: // Paeth
|
|
343
|
+
filtered = (current - this.paethPredictor(left, up, upLeft)) & 0xff;
|
|
344
|
+
break;
|
|
345
|
+
default:
|
|
346
|
+
filtered = current;
|
|
347
|
+
}
|
|
348
|
+
result[x + 1] = filtered;
|
|
349
|
+
}
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
162
352
|
/**
|
|
163
353
|
* Get bytes per pixel for a given color type and bit depth
|
|
164
354
|
*/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImageData, ImageFormat, ImageMetadata } from "../types.js";
|
|
1
|
+
import type { ImageData, ImageDecoderOptions, ImageFormat, ImageMetadata } from "../types.js";
|
|
2
2
|
/**
|
|
3
3
|
* PPM format handler
|
|
4
4
|
* Implements the Netpbm PPM (Portable PixMap) format.
|
|
@@ -34,14 +34,14 @@ export declare class PPMFormat implements ImageFormat {
|
|
|
34
34
|
* @param data Raw PPM image data
|
|
35
35
|
* @returns Decoded image data with RGBA pixels
|
|
36
36
|
*/
|
|
37
|
-
decode(data: Uint8Array): Promise<ImageData>;
|
|
37
|
+
decode(data: Uint8Array, _options?: ImageDecoderOptions): Promise<ImageData>;
|
|
38
38
|
/**
|
|
39
39
|
* Encode RGBA image data to PPM format (P6 binary)
|
|
40
40
|
* Note: Alpha channel is ignored as PPM doesn't support transparency
|
|
41
41
|
* @param imageData Image data to encode
|
|
42
42
|
* @returns Encoded PPM image bytes
|
|
43
43
|
*/
|
|
44
|
-
encode(imageData: ImageData): Promise<Uint8Array>;
|
|
44
|
+
encode(imageData: ImageData, _options?: unknown): Promise<Uint8Array>;
|
|
45
45
|
/**
|
|
46
46
|
* Check if a byte is whitespace (space, tab, CR, LF)
|
|
47
47
|
*/
|
|
@@ -59,7 +59,7 @@ class PPMFormat {
|
|
|
59
59
|
* @param data Raw PPM image data
|
|
60
60
|
* @returns Decoded image data with RGBA pixels
|
|
61
61
|
*/
|
|
62
|
-
decode(data) {
|
|
62
|
+
decode(data, _options) {
|
|
63
63
|
if (!this.canDecode(data)) {
|
|
64
64
|
throw new Error("Invalid PPM signature");
|
|
65
65
|
}
|
|
@@ -211,7 +211,7 @@ class PPMFormat {
|
|
|
211
211
|
* @param imageData Image data to encode
|
|
212
212
|
* @returns Encoded PPM image bytes
|
|
213
213
|
*/
|
|
214
|
-
encode(imageData) {
|
|
214
|
+
encode(imageData, _options) {
|
|
215
215
|
const { width, height, data } = imageData;
|
|
216
216
|
// Validate input
|
|
217
217
|
if (data.length !== width * height * 4) {
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
import type { ImageData, ImageFormat, ImageMetadata, MultiFrameImageData } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Options for TIFF encoding
|
|
4
|
-
*/
|
|
5
|
-
export interface TIFFEncodeOptions {
|
|
6
|
-
/** Compression method: "none" for uncompressed (default), "lzw" for LZW compression */
|
|
7
|
-
compression?: "none" | "lzw";
|
|
8
|
-
/** Encode as grayscale instead of RGB/RGBA */
|
|
9
|
-
grayscale?: boolean;
|
|
10
|
-
/** Encode as RGB without alpha channel (ignored if grayscale is true) */
|
|
11
|
-
rgb?: boolean;
|
|
12
|
-
}
|
|
1
|
+
import type { ImageData, ImageDecoderOptions, ImageFormat, ImageMetadata, MultiFrameImageData } from "../types.js";
|
|
13
2
|
/**
|
|
14
3
|
* TIFF format handler
|
|
15
|
-
* Implements pure-JS TIFF decoder for uncompressed and
|
|
16
|
-
* and encoder for uncompressed and
|
|
17
|
-
* for
|
|
4
|
+
* Implements pure-JS TIFF decoder for uncompressed, LZW, PackBits, and Deflate-compressed RGB/RGBA images
|
|
5
|
+
* and encoder for uncompressed, LZW, PackBits, and Deflate-compressed RGBA TIFFs. Falls back to ImageDecoder
|
|
6
|
+
* for JPEG-compressed TIFFs.
|
|
18
7
|
* Supports multi-page TIFF files.
|
|
19
8
|
*/
|
|
20
9
|
export declare class TIFFFormat implements ImageFormat {
|
|
@@ -38,12 +27,12 @@ export declare class TIFFFormat implements ImageFormat {
|
|
|
38
27
|
* @param data Raw TIFF image data
|
|
39
28
|
* @returns Decoded image data with RGBA pixels of first page
|
|
40
29
|
*/
|
|
41
|
-
decode(data: Uint8Array): Promise<ImageData>;
|
|
30
|
+
decode(data: Uint8Array, _options?: ImageDecoderOptions): Promise<ImageData>;
|
|
42
31
|
encode(imageData: ImageData, options?: unknown): Promise<Uint8Array>;
|
|
43
32
|
/**
|
|
44
33
|
* Decode all pages from a multi-page TIFF
|
|
45
34
|
*/
|
|
46
|
-
decodeFrames(data: Uint8Array): Promise<MultiFrameImageData>;
|
|
35
|
+
decodeFrames(data: Uint8Array, _options?: ImageDecoderOptions): Promise<MultiFrameImageData>;
|
|
47
36
|
/**
|
|
48
37
|
* Encode multi-page TIFF
|
|
49
38
|
*/
|
|
@@ -65,7 +54,7 @@ export declare class TIFFFormat implements ImageFormat {
|
|
|
65
54
|
private decodeUsingRuntime;
|
|
66
55
|
private readString;
|
|
67
56
|
/**
|
|
68
|
-
* Pure JavaScript TIFF decoder for uncompressed and
|
|
57
|
+
* Pure JavaScript TIFF decoder for uncompressed, LZW, PackBits, and Deflate-compressed RGB/RGBA images
|
|
69
58
|
* Returns null if the TIFF uses unsupported features
|
|
70
59
|
*/
|
|
71
60
|
private decodePureJS;
|