@poe-platform/safe-bash 0.1.844 → 0.1.846
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/dist/image-ast/ast.d.ts +12 -2
- package/dist/image-ast/browser/ast.d.ts +12 -2
- package/dist/image-ast/browser/codecs/exif-metadata.d.ts +2 -0
- package/dist/image-ast/browser/codecs/exif.d.ts +2 -0
- package/dist/image-ast/browser/codecs/gif-metadata-storage.d.ts +1 -0
- package/dist/image-ast/browser/codecs/gif-metadata.d.ts +1 -0
- package/dist/image-ast/browser/codecs/gif-output-parts.d.ts +1 -1
- package/dist/image-ast/browser/codecs/jpeg.d.ts +1 -1
- package/dist/image-ast/browser/codecs/netpbm-storage.d.ts +2 -2
- package/dist/image-ast/browser/codecs/netpbm.d.ts +4 -4
- package/dist/image-ast/browser/codecs/png-storage.d.ts +9 -1
- package/dist/image-ast/browser/codecs/png.d.ts +1 -0
- package/dist/image-ast/browser/codecs/tiff-layout.d.ts +3 -2
- package/dist/image-ast/codecs/exif-metadata.d.ts +2 -0
- package/dist/image-ast/codecs/exif.d.ts +2 -0
- package/dist/image-ast/codecs/gif-metadata-storage.d.ts +1 -0
- package/dist/image-ast/codecs/gif-metadata.d.ts +1 -0
- package/dist/image-ast/codecs/gif-output-parts.d.ts +1 -1
- package/dist/image-ast/codecs/jpeg.d.ts +1 -1
- package/dist/image-ast/codecs/netpbm-storage.d.ts +2 -2
- package/dist/image-ast/codecs/netpbm.d.ts +4 -4
- package/dist/image-ast/codecs/png-storage.d.ts +9 -1
- package/dist/image-ast/codecs/png.d.ts +1 -0
- package/dist/image-ast/codecs/tiff-layout.d.ts +3 -2
- package/dist/image-ast/index.js +554 -163
- package/dist/mp4-ast/types.d.ts +2 -0
- package/dist/safe-bash/command-chunks/{chunk-LORSYIAF.js → chunk-CSJHADNR.js} +31 -7
- package/dist/safe-bash/command-chunks/{chunk-KSCVKF7I.js → chunk-F42YLXD4.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-2EEIB5O3.js → chunk-HUE2ATJY.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-3SWIXYXT.js → chunk-NBQWCUOP.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-U5TQVW64.js → chunk-ZTEK2JJD.js} +1 -1
- package/dist/safe-bash-command-ffmpeg/index.js +535 -88
- package/dist/safe-bash-command-ffprobe/index.js +2 -2
- package/dist/safe-bash-command-ffprobe/media.js +2 -2
- package/dist/safe-bash-command-imagemagick/compare-file.d.ts +3 -2
- package/dist/safe-bash-command-imagemagick/index.d.ts +1 -0
- package/dist/safe-bash-command-imagemagick/index.js +895 -276
- package/dist/safe-bash-command-imagemagick/raw-output.d.ts +10 -0
- package/dist/safe-bash-command-python/executor.js +3 -3
- package/dist/safe-bash-command-python/index.js +3 -3
- package/dist/safe-bash-command-python/jspi.js +2 -2
- package/dist/safe-bash-command-python/worker.js +1 -1
- package/package.json +2 -2
|
@@ -1,7 +1,90 @@
|
|
|
1
1
|
import "../safe-bash/command-chunks/chunk-65DS4IOB.js";
|
|
2
2
|
|
|
3
|
-
// packages/safe-bash-command-imagemagick/src/
|
|
3
|
+
// packages/safe-bash-command-imagemagick/src/raw-rgb.ts
|
|
4
|
+
function rawRgbInput(width, height, depth, endian, byteLength) {
|
|
5
|
+
if (depth !== 8 && depth !== 16) throw new Error(`unsupported RGB input depth '${depth}'`);
|
|
6
|
+
const length = width * height * 3 * (depth / 8);
|
|
7
|
+
if (!Number.isSafeInteger(length) || length > byteLength) throw new Error("unexpected end-of-file in RGB input");
|
|
8
|
+
const header = new TextEncoder().encode(`P6
|
|
9
|
+
${width} ${height}
|
|
10
|
+
${depth === 8 ? 255 : 65535}
|
|
11
|
+
`);
|
|
12
|
+
const swap = depth === 16 && endian !== "msb";
|
|
13
|
+
return {
|
|
14
|
+
size: header.length + length,
|
|
15
|
+
*read(position, size) {
|
|
16
|
+
const bytes = new Uint8Array(size);
|
|
17
|
+
const headerLength = Math.max(0, Math.min(size, header.length - position));
|
|
18
|
+
bytes.set(header.subarray(position, position + headerLength));
|
|
19
|
+
if (headerLength < size) {
|
|
20
|
+
const start = Math.max(0, position - header.length), end = start + size - headerLength;
|
|
21
|
+
const alignedStart = swap ? start - start % 2 : start;
|
|
22
|
+
const alignedEnd = swap ? end + end % 2 : end;
|
|
23
|
+
for (let offset = alignedStart; offset < alignedEnd; offset += 8192) {
|
|
24
|
+
const length2 = Math.min(8192, alignedEnd - offset);
|
|
25
|
+
const input = yield { position: offset, length: length2 };
|
|
26
|
+
if (input.length !== length2) throw new Error("unexpected end-of-file in RGB input");
|
|
27
|
+
for (let i = Math.max(start, offset); i < Math.min(end, offset + length2); i++) {
|
|
28
|
+
bytes[headerLength + i - start] = input[(swap ? i ^ 1 : i) - offset];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return bytes;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// packages/safe-bash-command-imagemagick/src/raw-output.ts
|
|
38
|
+
import { encodeImage as encodeRaster, encodeStoredImage as encodeStoredRaster } from "../image-ast/portable.js";
|
|
4
39
|
import { yieldTurn } from "../safe-bash-contracts/yield.js";
|
|
40
|
+
function isRawCoder(format) {
|
|
41
|
+
return format === "rgb" || format === "rgba" || format === "bgr" || format === "bgra" || format === "gray";
|
|
42
|
+
}
|
|
43
|
+
function encodeImage(image, options) {
|
|
44
|
+
const format = options.format;
|
|
45
|
+
if (!isRawCoder(format)) return encodeRaster(image, { ...options, format });
|
|
46
|
+
const channels = format === "gray" ? 1 : format.endsWith("a") ? 4 : 3;
|
|
47
|
+
const depth = (image.bitsPerSample ?? 8) > 8 ? 16 : 8;
|
|
48
|
+
const data = new Uint8Array(image.width * image.height * channels * depth / 8);
|
|
49
|
+
const view = new DataView(data.buffer), samples = image.data16 ?? image.data;
|
|
50
|
+
const scale = image.data16 ? 65535 : 255, maximum = depth === 16 ? 65535 : 255;
|
|
51
|
+
let offset = 0;
|
|
52
|
+
for (let pixel = 0; pixel < image.width * image.height; pixel++) {
|
|
53
|
+
for (let channel = 0; channel < channels; channel++) {
|
|
54
|
+
const index = format.startsWith("bgr") && channel < 3 ? 2 - channel : channel;
|
|
55
|
+
const value = format === "gray" ? 0.212656 * samples[pixel * 4] + 0.715158 * samples[pixel * 4 + 1] + 0.072186 * samples[pixel * 4 + 2] : channel === 3 && !image.hasAlpha ? scale : samples[pixel * 4 + index];
|
|
56
|
+
const quantum = Math.round(value * maximum / scale);
|
|
57
|
+
if (depth === 16) view.setUint16(offset, quantum, options.endian === void 0 || options.endian === "lsb");
|
|
58
|
+
else data[offset] = quantum;
|
|
59
|
+
offset += depth / 8;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return { data, format: "raw", channels };
|
|
63
|
+
}
|
|
64
|
+
async function* encodeStoredImage(image, storage, signal, options) {
|
|
65
|
+
if (!isRawCoder(options.format)) return yield* encodeStoredRaster(image, storage, signal, { ...options, format: options.format });
|
|
66
|
+
let size = 0, channels = 0;
|
|
67
|
+
for (let pixel = 0; pixel < image.width * image.height; pixel += 4096) {
|
|
68
|
+
await yieldTurn(signal);
|
|
69
|
+
const count = Math.min(4096, image.width * image.height - pixel);
|
|
70
|
+
const data = new Uint8Array(await storage.read(image.position + pixel * 4, count * 4, { signal }));
|
|
71
|
+
if (data.length !== count * 4) throw new Error("Truncated raw pixel storage");
|
|
72
|
+
let data16;
|
|
73
|
+
if (image.storedData16) {
|
|
74
|
+
const bytes = await storage.read(image.storedData16.position + pixel * 8, count * 8, { signal });
|
|
75
|
+
if (bytes.length !== count * 8) throw new Error("Truncated raw sample storage");
|
|
76
|
+
data16 = new Uint16Array(new Uint8Array(bytes).buffer);
|
|
77
|
+
}
|
|
78
|
+
const encoded = encodeImage({ ...image, width: count, height: 1, data, ...data16 ? { data16 } : {} }, options);
|
|
79
|
+
size += encoded.data.length;
|
|
80
|
+
channels = encoded.channels;
|
|
81
|
+
yield encoded.data;
|
|
82
|
+
}
|
|
83
|
+
return { format: "raw", width: image.width, height: image.height, channels, premultiplied: false, size };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// packages/safe-bash-command-imagemagick/src/deskew.ts
|
|
87
|
+
import { yieldTurn as yieldTurn2 } from "../safe-bash-contracts/yield.js";
|
|
5
88
|
function* deskewAngle(width, height, spec) {
|
|
6
89
|
const threshold = Number(spec.endsWith("%") ? spec.slice(0, -1) : spec) * (spec.endsWith("%") ? 255 / 100 : 255 / 65535);
|
|
7
90
|
if (!spec || !Number.isFinite(threshold)) throw new Error("Invalid deskew threshold");
|
|
@@ -80,7 +163,7 @@ async function storedDeskewAngle(image, storage, spec, signal) {
|
|
|
80
163
|
let next = steps.next();
|
|
81
164
|
while (!next.done) {
|
|
82
165
|
if (!next.value) {
|
|
83
|
-
await
|
|
166
|
+
await yieldTurn2(signal);
|
|
84
167
|
next = steps.next();
|
|
85
168
|
} else {
|
|
86
169
|
const { position, length } = next.value;
|
|
@@ -105,7 +188,7 @@ function deskewPlan(image, radians) {
|
|
|
105
188
|
}
|
|
106
189
|
|
|
107
190
|
// packages/safe-bash-command-imagemagick/src/raster-backing.ts
|
|
108
|
-
import { yieldTurn as
|
|
191
|
+
import { yieldTurn as yieldTurn3 } from "../safe-bash-contracts/yield.js";
|
|
109
192
|
var RasterBackingCache = class {
|
|
110
193
|
constructor(storage, signal) {
|
|
111
194
|
this.storage = storage;
|
|
@@ -118,14 +201,14 @@ var RasterBackingCache = class {
|
|
|
118
201
|
async allocate(length) {
|
|
119
202
|
const region = { position: this.storage.allocate(length), length }, zero = new Uint8Array(Math.min(4096, length));
|
|
120
203
|
for (let offset = 0; offset < length; offset += zero.length) {
|
|
121
|
-
if (offset % 65536 === 0) await
|
|
204
|
+
if (offset % 65536 === 0) await yieldTurn3(this.signal);
|
|
122
205
|
await this.storage.write(region.position + offset, zero.subarray(0, Math.min(zero.length, length - offset)), { signal: this.signal });
|
|
123
206
|
}
|
|
124
207
|
return region;
|
|
125
208
|
}
|
|
126
209
|
async page(region, offset) {
|
|
127
210
|
this.signal.throwIfAborted();
|
|
128
|
-
if (++this.work % 16384 === 0) await
|
|
211
|
+
if (++this.work % 16384 === 0) await yieldTurn3(this.signal);
|
|
129
212
|
const start = Math.floor(offset / 4096) * 4096, key = region.position + ":" + start;
|
|
130
213
|
let page = this.pages.get(key);
|
|
131
214
|
if (page) {
|
|
@@ -181,7 +264,7 @@ var RasterBackingCache = class {
|
|
|
181
264
|
};
|
|
182
265
|
|
|
183
266
|
// packages/safe-bash-command-imagemagick/src/floodfill.ts
|
|
184
|
-
import { yieldTurn as
|
|
267
|
+
import { yieldTurn as yieldTurn4 } from "../safe-bash-contracts/yield.js";
|
|
185
268
|
function matchesAlphaFloodfill(r, g, b, a, refR, refG, refB, refA, fuzz) {
|
|
186
269
|
return (a - refA) ** 2 + ((r - refR) ** 2 + (g - refG) ** 2 + (b - refB) ** 2) * (a / 255) * (refA / 255) / 3 <= 2 * fuzz ** 2;
|
|
187
270
|
}
|
|
@@ -206,7 +289,7 @@ async function floodfillStoredImage(image, storage, seedX, seedY, target, replac
|
|
|
206
289
|
await cache.flush();
|
|
207
290
|
const position = storage.allocate(count * 4);
|
|
208
291
|
for (let start2 = 0; start2 < count; start2 += 1024) {
|
|
209
|
-
await
|
|
292
|
+
await yieldTurn4(signal);
|
|
210
293
|
const length = Math.min(1024, count - start2), pixels = new Uint8Array(await storage.read(image.position + start2 * 4, length * 4, { signal }));
|
|
211
294
|
const flags = await storage.read(visited.position + start2, length, { signal });
|
|
212
295
|
if (pixels.length !== length * 4 || flags.length !== length) throw new Error("Truncated floodfill pixels");
|
|
@@ -342,6 +425,45 @@ function* extendEdgePixelSteps(source, width, height) {
|
|
|
342
425
|
}
|
|
343
426
|
}
|
|
344
427
|
|
|
428
|
+
// packages/safe-bash-command-imagemagick/src/bilevel-kernel.ts
|
|
429
|
+
function* bilevelPixelSteps(count, highDepth) {
|
|
430
|
+
const histogram = new Float64Array(65536), sampleBytes = highDepth ? 2 : 1;
|
|
431
|
+
let low = 0, high = 65535;
|
|
432
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
433
|
+
for (let first = 0; first < count; first += 4096) {
|
|
434
|
+
yield;
|
|
435
|
+
const size = Math.min(4096, count - first);
|
|
436
|
+
const bytes = yield { kind: "read", position: first * 4 * sampleBytes, length: size * 4 * sampleBytes };
|
|
437
|
+
if (!bytes || bytes.length !== size * 4 * sampleBytes) throw new Error("Truncated bilevel pixels");
|
|
438
|
+
const samples = highDepth ? new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2) : bytes;
|
|
439
|
+
const data = pass ? new Uint8Array(size * 4) : void 0;
|
|
440
|
+
for (let pixel = 0; pixel < size; pixel++) {
|
|
441
|
+
const offset = pixel * 4;
|
|
442
|
+
const gray = Math.round((highDepth ? 1 : 257) * (0.212656 * samples[offset] + 0.715158 * samples[offset + 1] + 0.072186 * samples[offset + 2]));
|
|
443
|
+
if (!data) histogram[gray]++;
|
|
444
|
+
else {
|
|
445
|
+
const value = gray > (high > low ? (low + high) / 2 : 65535 / 2) ? 255 : 0;
|
|
446
|
+
data.fill(value, offset, offset + 3);
|
|
447
|
+
data[offset + 3] = 255;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (data) yield { kind: "write", position: first * 4, data };
|
|
451
|
+
}
|
|
452
|
+
if (pass === 0) {
|
|
453
|
+
let sum = 0;
|
|
454
|
+
for (; low < 65535; low++) {
|
|
455
|
+
sum += histogram[low];
|
|
456
|
+
if (sum > 0.02 * count) break;
|
|
457
|
+
}
|
|
458
|
+
sum = 0;
|
|
459
|
+
for (; high > 0; high--) {
|
|
460
|
+
sum += histogram[high];
|
|
461
|
+
if (sum > 0.01 * count) break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
345
467
|
// packages/safe-bash-command-imagemagick/src/compare-phash.ts
|
|
346
468
|
function* perceptualHashSteps(info, image) {
|
|
347
469
|
const weights = Array.from({ length: 9 }, (_, i) => {
|
|
@@ -1510,7 +1632,7 @@ function* pointResizePixelSteps(image, width, height, sample = false) {
|
|
|
1510
1632
|
|
|
1511
1633
|
// packages/safe-bash-command-imagemagick/src/trim.ts
|
|
1512
1634
|
import { extractImageSteps, transformStoredImage } from "../image-ast/portable.js";
|
|
1513
|
-
import { yieldTurn as
|
|
1635
|
+
import { yieldTurn as yieldTurn5 } from "../safe-bash-contracts/yield.js";
|
|
1514
1636
|
function* trimBounds(width, height, fuzz) {
|
|
1515
1637
|
const corners = [];
|
|
1516
1638
|
for (const pixel of [0, width - 1, (height - 1) * width, width * height - 1]) {
|
|
@@ -1574,7 +1696,7 @@ async function trimStoredMagick(image, storage, fuzz, signal) {
|
|
|
1574
1696
|
let next = steps.next();
|
|
1575
1697
|
while (!next.done) {
|
|
1576
1698
|
if (!next.value) {
|
|
1577
|
-
await
|
|
1699
|
+
await yieldTurn5(signal);
|
|
1578
1700
|
next = steps.next();
|
|
1579
1701
|
} else {
|
|
1580
1702
|
const { position: position2, length } = next.value;
|
|
@@ -1881,7 +2003,7 @@ function* quantizePixelSteps(length, requested, grayscale = false) {
|
|
|
1881
2003
|
}
|
|
1882
2004
|
|
|
1883
2005
|
// packages/safe-bash-command-imagemagick/src/connected-components.ts
|
|
1884
|
-
import { yieldTurn as
|
|
2006
|
+
import { yieldTurn as yieldTurn6 } from "../safe-bash-contracts/yield.js";
|
|
1885
2007
|
function* labelSteps(width, height, connectivity) {
|
|
1886
2008
|
const components = [];
|
|
1887
2009
|
for (let seed = 0; seed < width * height; seed++) {
|
|
@@ -1978,7 +2100,7 @@ async function connectedComponentsStored(image, storage, connectivity, verbose,
|
|
|
1978
2100
|
while (!next.done) {
|
|
1979
2101
|
const request = next.value;
|
|
1980
2102
|
if (!request) {
|
|
1981
|
-
await
|
|
2103
|
+
await yieldTurn6(signal);
|
|
1982
2104
|
next = steps.next(0);
|
|
1983
2105
|
continue;
|
|
1984
2106
|
}
|
|
@@ -1993,7 +2115,7 @@ async function connectedComponentsStored(image, storage, connectivity, verbose,
|
|
|
1993
2115
|
const report = reportSteps(next.value);
|
|
1994
2116
|
let part = report.next();
|
|
1995
2117
|
while (!part.done) {
|
|
1996
|
-
await
|
|
2118
|
+
await yieldTurn6(signal);
|
|
1997
2119
|
part = report.next();
|
|
1998
2120
|
}
|
|
1999
2121
|
text = part.value;
|
|
@@ -2001,7 +2123,7 @@ async function connectedComponentsStored(image, storage, connectivity, verbose,
|
|
|
2001
2123
|
await cache.flush();
|
|
2002
2124
|
const position = storage.allocate(size);
|
|
2003
2125
|
for (let offset = 0; offset < size; offset += 4096) {
|
|
2004
|
-
await
|
|
2126
|
+
await yieldTurn6(signal);
|
|
2005
2127
|
const bytes = new Uint8Array(await storage.read(regions.labels.position + offset, Math.min(4096, size - offset), { signal })), view = new DataView(bytes.buffer);
|
|
2006
2128
|
for (let i = 0; i < bytes.length; i += 4) {
|
|
2007
2129
|
const value = Math.round((view.getUint32(i, true) - 1) / 257);
|
|
@@ -2158,7 +2280,7 @@ async function withImageInputs(input, stdinBytes, signal, run) {
|
|
|
2158
2280
|
|
|
2159
2281
|
// packages/safe-bash-command-imagemagick/src/text-output.ts
|
|
2160
2282
|
import { IntegerTable } from "@poe-platform/safe-fs/storage";
|
|
2161
|
-
import { yieldTurn as
|
|
2283
|
+
import { yieldTurn as yieldTurn7 } from "../safe-bash-contracts/yield.js";
|
|
2162
2284
|
var hex = (value) => value.toString(16).toUpperCase().padStart(2, "0");
|
|
2163
2285
|
function pixelEnumerationLine(x, y, r, g, b, a) {
|
|
2164
2286
|
return `${x},${y}: (${r},${g},${b},${a}) #${hex(r)}${hex(g)}${hex(b)}${a < 255 ? hex(a) : ""} srgba(${r},${g},${b},${(a / 255).toFixed(3)})`;
|
|
@@ -2173,7 +2295,7 @@ async function* storedPixelEnumeration(image, storage, signal) {
|
|
|
2173
2295
|
`;
|
|
2174
2296
|
const size = image.width * image.height * 4;
|
|
2175
2297
|
for (let start = 0; start < size; start += 16384) {
|
|
2176
|
-
await
|
|
2298
|
+
await yieldTurn7(signal);
|
|
2177
2299
|
const bytes = await storage.read(image.position + start, Math.min(16384, size - start));
|
|
2178
2300
|
const original = (image.magickColorspace === "HSL" || image.magickColorspace === "HSB" || image.magickColorspace === "HWB" || image.magickColorspace === "XYZ" || image.magickColorspace === "YCbCr" || image.magickColorspace === "YUV") && image.storedData16 ? await storage.read(image.storedData16.position + start * 2, bytes.length * 2) : void 0;
|
|
2179
2301
|
const data16 = original ? new Uint16Array(original.buffer.slice(original.byteOffset, original.byteOffset + original.byteLength)) : void 0;
|
|
@@ -2195,7 +2317,7 @@ async function* storedHistogram(image, storage, signal) {
|
|
|
2195
2317
|
const sampleOffsets = (image.magickColorspace === "HWB" || image.magickColorspace === "XYZ" || image.magickColorspace === "YCbCr" || image.magickColorspace === "YUV") && image.storedHueSamples !== void 0 ? new IntegerTable(storage, 128) : void 0;
|
|
2196
2318
|
let unique = 0;
|
|
2197
2319
|
for (let start = 0; start < size; start += 16384) {
|
|
2198
|
-
await
|
|
2320
|
+
await yieldTurn7(signal);
|
|
2199
2321
|
const bytes = await storage.read(image.position + start, Math.min(16384, size - start));
|
|
2200
2322
|
const original = (image.magickColorspace === "HSL" || image.magickColorspace === "HSB" || image.magickColorspace === "HWB" || image.magickColorspace === "XYZ" || image.magickColorspace === "YCbCr" || image.magickColorspace === "YUV") && image.storedData16 ? await storage.read(image.storedData16.position + start * 2, bytes.length * 2) : void 0;
|
|
2201
2323
|
const data16 = original ? new Uint16Array(original.buffer.slice(original.byteOffset, original.byteOffset + original.byteLength)) : void 0;
|
|
@@ -2209,7 +2331,7 @@ async function* storedHistogram(image, storage, signal) {
|
|
|
2209
2331
|
}
|
|
2210
2332
|
}
|
|
2211
2333
|
for (let index = 0; index < unique; index++) {
|
|
2212
|
-
if (index % 128 === 0) await
|
|
2334
|
+
if (index % 128 === 0) await yieldTurn7(signal);
|
|
2213
2335
|
const key = await order.get(BigInt(index));
|
|
2214
2336
|
const samples = sampleOffsets ? await storage.read(image.storedHueSamples + Number(await sampleOffsets.get(BigInt(index))) * 8, 32) : void 0;
|
|
2215
2337
|
const hueSamples = samples ? Array.from(new Float64Array(samples.buffer.slice(samples.byteOffset, samples.byteOffset + samples.byteLength))) : void 0;
|
|
@@ -2254,7 +2376,7 @@ async function* encodeText(parts, signal) {
|
|
|
2254
2376
|
|
|
2255
2377
|
// packages/safe-bash-command-imagemagick/src/stored-stack.ts
|
|
2256
2378
|
import { IntegerTable as IntegerTable2 } from "@poe-platform/safe-fs/storage";
|
|
2257
|
-
import { yieldTurn as
|
|
2379
|
+
import { yieldTurn as yieldTurn8 } from "../safe-bash-contracts/yield.js";
|
|
2258
2380
|
var magickInput = /* @__PURE__ */ Symbol("magickInput");
|
|
2259
2381
|
var StoredImageStack = class {
|
|
2260
2382
|
constructor(storage, signal, parent) {
|
|
@@ -2263,6 +2385,7 @@ var StoredImageStack = class {
|
|
|
2263
2385
|
this.frames = parent?.frames ?? /* @__PURE__ */ new Map();
|
|
2264
2386
|
this.records = parent?.records ?? /* @__PURE__ */ new WeakMap();
|
|
2265
2387
|
this.delayRegions = parent?.delayRegions ?? /* @__PURE__ */ new WeakMap();
|
|
2388
|
+
this.iccRegions = parent?.iccRegions ?? /* @__PURE__ */ new WeakMap();
|
|
2266
2389
|
this.indices = new IntegerTable2(storage, 128);
|
|
2267
2390
|
}
|
|
2268
2391
|
storage;
|
|
@@ -2271,6 +2394,7 @@ var StoredImageStack = class {
|
|
|
2271
2394
|
frames;
|
|
2272
2395
|
records;
|
|
2273
2396
|
delayRegions;
|
|
2397
|
+
iccRegions;
|
|
2274
2398
|
length = 0;
|
|
2275
2399
|
cache(position, image) {
|
|
2276
2400
|
this.frames.delete(position);
|
|
@@ -2281,12 +2405,12 @@ var StoredImageStack = class {
|
|
|
2281
2405
|
async retain(image) {
|
|
2282
2406
|
const known = this.records.get(image);
|
|
2283
2407
|
if (known !== void 0) return known;
|
|
2284
|
-
const { delay, storedDelay, ...metadata } = image, source = storedDelay ?? delay;
|
|
2408
|
+
const { delay, storedDelay, icc, ...metadata } = image, source = storedDelay ?? delay;
|
|
2285
2409
|
let delays = source ? this.delayRegions.get(source) : void 0;
|
|
2286
2410
|
if (source && !delays) {
|
|
2287
2411
|
delays = { position: this.storage.allocate(source.length * 9), length: source.length };
|
|
2288
2412
|
for (let start = 0; start < source.length; start += 512) {
|
|
2289
|
-
await
|
|
2413
|
+
await yieldTurn8(this.signal);
|
|
2290
2414
|
const count = Math.min(512, source.length - start), bytes = new Uint8Array(count * 9), view = new DataView(bytes.buffer);
|
|
2291
2415
|
for (let i = 0; i < count; i++) {
|
|
2292
2416
|
const value = storedDelay ? await storedDelay.at(start + i, { signal: this.signal }) : delay[start + i];
|
|
@@ -2299,11 +2423,20 @@ var StoredImageStack = class {
|
|
|
2299
2423
|
}
|
|
2300
2424
|
this.delayRegions.set(source, delays);
|
|
2301
2425
|
}
|
|
2302
|
-
|
|
2426
|
+
let profile = icc ? this.iccRegions.get(icc) : void 0;
|
|
2427
|
+
if (icc && !profile) {
|
|
2428
|
+
profile = { position: this.storage.allocate(icc.length), length: icc.length };
|
|
2429
|
+
for (let offset = 0; offset < icc.length; offset += 4096) {
|
|
2430
|
+
await yieldTurn8(this.signal);
|
|
2431
|
+
await this.storage.write(profile.position + offset, icc.subarray(offset, offset + 4096));
|
|
2432
|
+
}
|
|
2433
|
+
this.iccRegions.set(icc, profile);
|
|
2434
|
+
}
|
|
2435
|
+
const record = { image: metadata, ...profile ? { icc: profile } : {}, ...image[magickInput] ? { source: image[magickInput] } : {}, ...delays ? { delays } : {} };
|
|
2303
2436
|
const text = JSON.stringify(record), encoder = new TextEncoder(), position = this.storage.allocate(8);
|
|
2304
2437
|
let size = 0;
|
|
2305
2438
|
for (let offset = 0; offset < text.length; ) {
|
|
2306
|
-
await
|
|
2439
|
+
await yieldTurn8(this.signal);
|
|
2307
2440
|
const bytes = new Uint8Array(4096), { read, written } = encoder.encodeInto(text.slice(offset, offset + 4097), bytes);
|
|
2308
2441
|
await this.storage.write(this.storage.allocate(written), bytes.subarray(0, written));
|
|
2309
2442
|
offset += read;
|
|
@@ -2326,11 +2459,20 @@ var StoredImageStack = class {
|
|
|
2326
2459
|
const decoder = new TextDecoder();
|
|
2327
2460
|
let text = "";
|
|
2328
2461
|
for (let offset = 0; offset < size; offset += 4096) {
|
|
2329
|
-
await
|
|
2462
|
+
await yieldTurn8(this.signal);
|
|
2330
2463
|
text += decoder.decode(await this.storage.read(position + 8 + offset, Math.min(4096, size - offset)), { stream: true });
|
|
2331
2464
|
}
|
|
2332
2465
|
const record = JSON.parse(text + decoder.decode());
|
|
2333
2466
|
const image = { ...record.image, ...record.source ? { [magickInput]: record.source } : {} };
|
|
2467
|
+
if (record.icc) {
|
|
2468
|
+
const icc = new Uint8Array(record.icc.length);
|
|
2469
|
+
for (let offset = 0; offset < icc.length; offset += 4096) {
|
|
2470
|
+
await yieldTurn8(this.signal);
|
|
2471
|
+
icc.set(await this.storage.read(record.icc.position + offset, Math.min(4096, icc.length - offset)), offset);
|
|
2472
|
+
}
|
|
2473
|
+
Object.assign(image, { icc });
|
|
2474
|
+
this.iccRegions.set(icc, record.icc);
|
|
2475
|
+
}
|
|
2334
2476
|
if (record.delays) {
|
|
2335
2477
|
const region = record.delays, storage = this.storage, signal = this.signal;
|
|
2336
2478
|
const reader = { length: region.length, async at(index, options) {
|
|
@@ -2375,12 +2517,12 @@ var StoredImageStack = class {
|
|
|
2375
2517
|
const removed = new IntegerTable2(this.storage, 128);
|
|
2376
2518
|
let work = 0;
|
|
2377
2519
|
for (const index of indices) if (index >= 0 && index < this.length) {
|
|
2378
|
-
if (++work % 128 === 0) await
|
|
2520
|
+
if (++work % 128 === 0) await yieldTurn8(this.signal);
|
|
2379
2521
|
await removed.set(BigInt(index), 1n);
|
|
2380
2522
|
}
|
|
2381
2523
|
let next = 0;
|
|
2382
2524
|
for (let index = 0; index < this.length; index++) {
|
|
2383
|
-
if (index % 128 === 0) await
|
|
2525
|
+
if (index % 128 === 0) await yieldTurn8(this.signal);
|
|
2384
2526
|
if (await removed.get(BigInt(index))) continue;
|
|
2385
2527
|
if (next !== index) await this.indices.set(BigInt(next), await this.indices.get(BigInt(index)));
|
|
2386
2528
|
next++;
|
|
@@ -2390,11 +2532,11 @@ var StoredImageStack = class {
|
|
|
2390
2532
|
};
|
|
2391
2533
|
|
|
2392
2534
|
// packages/safe-bash-command-imagemagick/src/remap.ts
|
|
2393
|
-
import { yieldTurn as
|
|
2535
|
+
import { yieldTurn as yieldTurn9 } from "../safe-bash-contracts/yield.js";
|
|
2394
2536
|
async function remapStoredImage(image, paletteImage, storage, dither, signal) {
|
|
2395
2537
|
const palette = [], seen = /* @__PURE__ */ new Set();
|
|
2396
2538
|
for (let offset = 0; offset < paletteImage.width * paletteImage.height * 4 && palette.length < 256; offset += 4096) {
|
|
2397
|
-
await
|
|
2539
|
+
await yieldTurn9(signal);
|
|
2398
2540
|
const length = Math.min(4096, paletteImage.width * paletteImage.height * 4 - offset), bytes = await storage.read(paletteImage.position + offset, length, { signal });
|
|
2399
2541
|
if (bytes.length !== length) throw new Error("Truncated remap palette");
|
|
2400
2542
|
for (let i = 0; i < length && palette.length < 256; i += 4) {
|
|
@@ -2409,7 +2551,7 @@ async function remapStoredImage(image, paletteImage, storage, dither, signal) {
|
|
|
2409
2551
|
const count = image.width * image.height, cache = new RasterBackingCache(storage, signal);
|
|
2410
2552
|
const errors = dither ? { position: storage.allocate(count * 16), length: count * 16 } : void 0;
|
|
2411
2553
|
if (errors) for (let start = 0; start < count; start += 1024) {
|
|
2412
|
-
await
|
|
2554
|
+
await yieldTurn9(signal);
|
|
2413
2555
|
const length = Math.min(1024, count - start), pixels = await storage.read(image.position + start * 4, length * 4, { signal });
|
|
2414
2556
|
if (pixels.length !== length * 4) throw new Error("Truncated remap pixels");
|
|
2415
2557
|
const bytes = new Uint8Array(length * 16), view = new DataView(bytes.buffer);
|
|
@@ -2418,7 +2560,7 @@ async function remapStoredImage(image, paletteImage, storage, dither, signal) {
|
|
|
2418
2560
|
}
|
|
2419
2561
|
const position = storage.allocate(count * 4);
|
|
2420
2562
|
for (let start = 0; start < count; start += 1024) {
|
|
2421
|
-
await
|
|
2563
|
+
await yieldTurn9(signal);
|
|
2422
2564
|
const length = Math.min(1024, count - start), pixels = new Uint8Array(await storage.read(image.position + start * 4, length * 4, { signal }));
|
|
2423
2565
|
if (pixels.length !== length * 4) throw new Error("Truncated remap pixels");
|
|
2424
2566
|
for (let i = 0; i < length; i++) {
|
|
@@ -3182,9 +3324,8 @@ function* embossPixelSteps(image, geometry) {
|
|
|
3182
3324
|
}
|
|
3183
3325
|
|
|
3184
3326
|
// packages/safe-bash-command-imagemagick/src/encoded-snapshots.ts
|
|
3185
|
-
import { encodeStoredImage } from "../image-ast/portable.js";
|
|
3186
3327
|
import { IntegerTable as IntegerTable3 } from "@poe-platform/safe-fs/storage";
|
|
3187
|
-
import { yieldTurn as
|
|
3328
|
+
import { yieldTurn as yieldTurn10 } from "../safe-bash-contracts/yield.js";
|
|
3188
3329
|
var EncodedSnapshots = class {
|
|
3189
3330
|
constructor(storage, signal) {
|
|
3190
3331
|
this.storage = storage;
|
|
@@ -3214,7 +3355,7 @@ var EncodedSnapshots = class {
|
|
|
3214
3355
|
};
|
|
3215
3356
|
try {
|
|
3216
3357
|
while (true) {
|
|
3217
|
-
await
|
|
3358
|
+
await yieldTurn10(this.signal);
|
|
3218
3359
|
const next = await encoder.next();
|
|
3219
3360
|
if (next.done) {
|
|
3220
3361
|
if (!next.value) throw new Error("Image encoding did not finish");
|
|
@@ -3226,7 +3367,7 @@ var EncodedSnapshots = class {
|
|
|
3226
3367
|
new DataView(header.buffer).setFloat64(0, bytes.length, true);
|
|
3227
3368
|
await this.storage.write(position, header);
|
|
3228
3369
|
for (let start = 0; start < bytes.length; start += 4096) {
|
|
3229
|
-
await
|
|
3370
|
+
await yieldTurn10(this.signal);
|
|
3230
3371
|
await this.storage.write(position + 8 + start, bytes.subarray(start, start + 4096));
|
|
3231
3372
|
}
|
|
3232
3373
|
await this.buckets.set(hash, BigInt(position));
|
|
@@ -3265,7 +3406,7 @@ var EncodedSnapshots = class {
|
|
|
3265
3406
|
const decoder = new TextDecoder();
|
|
3266
3407
|
let text = "";
|
|
3267
3408
|
for (let start = 0; start < size; start += 4096) {
|
|
3268
|
-
await
|
|
3409
|
+
await yieldTurn10(this.signal);
|
|
3269
3410
|
text += decoder.decode(await this.storage.read(position + 8 + start, Math.min(4096, size - start)), { stream: true });
|
|
3270
3411
|
}
|
|
3271
3412
|
const record = JSON.parse(text + decoder.decode());
|
|
@@ -3275,7 +3416,7 @@ var EncodedSnapshots = class {
|
|
|
3275
3416
|
async find(path, hash) {
|
|
3276
3417
|
let position = Number(await this.buckets.get(hash) ?? -1n);
|
|
3277
3418
|
while (position >= 0) {
|
|
3278
|
-
await
|
|
3419
|
+
await yieldTurn10(this.signal);
|
|
3279
3420
|
const record = await this.record(position);
|
|
3280
3421
|
if (record.path === path) return record;
|
|
3281
3422
|
position = record.next ?? -1;
|
|
@@ -3333,13 +3474,13 @@ async function decodeFileImage(source, storage, filesystem, cwd, signal, options
|
|
|
3333
3474
|
}
|
|
3334
3475
|
|
|
3335
3476
|
// packages/safe-bash-command-imagemagick/src/compare-file.ts
|
|
3336
|
-
import { readImageMetadataFromSource, tryPdfMetadata, readImageMetadata, decodeImage,
|
|
3477
|
+
import { readImageMetadataFromSource, tryPdfMetadata, readImageMetadata, decodeImage, tryImageFile, UnsupportedStoredResource as UnsupportedStoredResource2, UnsupportedImageFormat as UnsupportedImageFormat2 } from "../image-ast/portable.js";
|
|
3337
3478
|
import { PagedStorage as PagedStorage2, PagedStorageCache } from "@poe-platform/safe-fs/storage";
|
|
3338
3479
|
import { FsError as FsError2 } from "@poe-platform/safe-fs/contracts";
|
|
3339
3480
|
import { resolvePath as resolvePath2 } from "../safe-bash-contracts/path.js";
|
|
3340
3481
|
import { writeBytes } from "../safe-bash-contracts/io.js";
|
|
3341
3482
|
import { writeFileOutput } from "../safe-bash-contracts/filesystem-output-budget.js";
|
|
3342
|
-
import { yieldTurn as
|
|
3483
|
+
import { yieldTurn as yieldTurn11 } from "../safe-bash-contracts/yield.js";
|
|
3343
3484
|
var CompareInputFailure = class extends Error {
|
|
3344
3485
|
constructor(reason) {
|
|
3345
3486
|
super("Comparison input failed");
|
|
@@ -3364,7 +3505,7 @@ async function withCompareFiles(input, stdinBytes, signal, run) {
|
|
|
3364
3505
|
const { data, data16: ignored, ...metadata } = image, position = storage.allocate(data.length);
|
|
3365
3506
|
for (let offset = 0; offset < data.length; offset += 16384) {
|
|
3366
3507
|
if (offset % 1048576 === 0)
|
|
3367
|
-
await
|
|
3508
|
+
await yieldTurn11(signal);
|
|
3368
3509
|
await storage.write(position + offset, data.subarray(offset, offset + 16384));
|
|
3369
3510
|
}
|
|
3370
3511
|
return { ...metadata, position };
|
|
@@ -3393,46 +3534,53 @@ async function withCompareFiles(input, stdinBytes, signal, run) {
|
|
|
3393
3534
|
try {
|
|
3394
3535
|
const result = await withImageInputs(input, stdinBytes, signal, async (read) => {
|
|
3395
3536
|
const publishImage = async (image, path, encoding, snapshot, retire = true) => {
|
|
3396
|
-
if (path !== "-" || snapshot) {
|
|
3397
|
-
const output = resolvePath2(cwd, path), info = await tryImageFile({ image, storage, ...snapshot ? { encoded: snapshot } : {}, async close() {
|
|
3398
|
-
if (retire) {
|
|
3399
|
-
await storage.close();
|
|
3400
|
-
await read.close();
|
|
3401
|
-
}
|
|
3402
|
-
} }, output, { filesystem: budgetedFs, workingDirectory: cwd, signal }, encoding);
|
|
3403
|
-
if (info)
|
|
3404
|
-
return;
|
|
3405
|
-
}
|
|
3406
|
-
const encoded = snapshot ? (async function* () {
|
|
3407
|
-
for (let position = 0; position < snapshot.source.size; position += 16384) {
|
|
3408
|
-
await yieldTurn10(signal);
|
|
3409
|
-
yield new Uint8Array(await snapshot.source.read(position, Math.min(16384, snapshot.source.size - position), io));
|
|
3410
|
-
}
|
|
3411
|
-
})() : encodeStoredImage2(image, storage, signal, encoding), chunks = [];
|
|
3412
|
-
let size = 0;
|
|
3413
3537
|
try {
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3538
|
+
if (path !== "-" || snapshot) {
|
|
3539
|
+
const output = resolvePath2(cwd, path), info = await tryImageFile({ image, storage, ...snapshot ? { encoded: snapshot } : {}, async close() {
|
|
3540
|
+
if (retire) {
|
|
3541
|
+
await storage.close();
|
|
3542
|
+
await read.close();
|
|
3543
|
+
}
|
|
3544
|
+
} }, output, { filesystem: budgetedFs, workingDirectory: cwd, signal }, { ...encoding, format: isRawCoder(encoding.format) ? "raw" : encoding.format });
|
|
3545
|
+
if (info)
|
|
3546
|
+
return;
|
|
3547
|
+
}
|
|
3548
|
+
const encoded = snapshot ? (async function* () {
|
|
3549
|
+
for (let position = 0; position < snapshot.source.size; position += 16384) {
|
|
3550
|
+
await yieldTurn11(signal);
|
|
3551
|
+
yield new Uint8Array(await snapshot.source.read(position, Math.min(16384, snapshot.source.size - position), io));
|
|
3420
3552
|
}
|
|
3553
|
+
})() : encodeStoredImage(image, storage, signal, encoding), chunks = [];
|
|
3554
|
+
let size = 0;
|
|
3555
|
+
try {
|
|
3556
|
+
for await (const chunk of encoded) {
|
|
3557
|
+
if (path === "-" && !snapshot && stdout)
|
|
3558
|
+
await writeBytes(stdout, chunk, signal);
|
|
3559
|
+
else {
|
|
3560
|
+
chunks.push(chunk);
|
|
3561
|
+
size += chunk.length;
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
} finally {
|
|
3565
|
+
await encoded.return(void 0);
|
|
3421
3566
|
}
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3567
|
+
if (path === "-" && !snapshot && stdout)
|
|
3568
|
+
return;
|
|
3569
|
+
const bytes = new Uint8Array(size);
|
|
3570
|
+
let offset = 0;
|
|
3571
|
+
for (const chunk of chunks) {
|
|
3572
|
+
bytes.set(chunk, offset);
|
|
3573
|
+
offset += chunk.length;
|
|
3574
|
+
}
|
|
3575
|
+
if (path === "-" && !snapshot)
|
|
3576
|
+
return bytes;
|
|
3577
|
+
await writeFileOutput(context, bytes, (admitted) => fs.writeFile(resolvePath2(cwd, path), admitted, io));
|
|
3578
|
+
} catch (error) {
|
|
3579
|
+
signal.throwIfAborted();
|
|
3580
|
+
if (error instanceof FsError2 && ["ENOENT", "ENOTDIR"].includes(error.code))
|
|
3581
|
+
throw new FsError2(error.code, { syscall: "write", path, cause: error });
|
|
3582
|
+
throw error;
|
|
3432
3583
|
}
|
|
3433
|
-
if (path === "-" && !snapshot)
|
|
3434
|
-
return bytes;
|
|
3435
|
-
await writeFileOutput(context, bytes, (admitted) => fs.writeFile(resolvePath2(cwd, path), admitted, io));
|
|
3436
3584
|
};
|
|
3437
3585
|
const publishPending = async () => {
|
|
3438
3586
|
let index = 0;
|
|
@@ -3474,7 +3622,7 @@ async function withCompareFiles(input, stdinBytes, signal, run) {
|
|
|
3474
3622
|
try {
|
|
3475
3623
|
let next = iterator.next();
|
|
3476
3624
|
while (!next.done) {
|
|
3477
|
-
await
|
|
3625
|
+
await yieldTurn11(signal);
|
|
3478
3626
|
let configured = next.value, image;
|
|
3479
3627
|
try {
|
|
3480
3628
|
image = bytes ? await retain(decodeImage(bytes, configured)) : await decodeFileImage(checked, storage, fs, cwd, signal, configured);
|
|
@@ -3520,7 +3668,10 @@ async function withCompareFiles(input, stdinBytes, signal, run) {
|
|
|
3520
3668
|
throw error;
|
|
3521
3669
|
}
|
|
3522
3670
|
},
|
|
3523
|
-
|
|
3671
|
+
async stage(image, path, encoding) {
|
|
3672
|
+
if (path === "-") return publishImage(image, path, encoding, void 0, false);
|
|
3673
|
+
await snapshots.stage(image, path, encoding);
|
|
3674
|
+
},
|
|
3524
3675
|
publishPending,
|
|
3525
3676
|
async publishText(image, path, chunks) {
|
|
3526
3677
|
const encoded = (async function* () {
|
|
@@ -3535,7 +3686,7 @@ async function withCompareFiles(input, stdinBytes, signal, run) {
|
|
|
3535
3686
|
await publishPending();
|
|
3536
3687
|
},
|
|
3537
3688
|
async publish(image, path, encoding) {
|
|
3538
|
-
if (!snapshots.size) return publishImage(image, path, encoding);
|
|
3689
|
+
if (!snapshots.size && (!isRawCoder(encoding.format) || path === "-")) return publishImage(image, path, encoding);
|
|
3539
3690
|
let bytes;
|
|
3540
3691
|
if (path === "-") bytes = await publishImage(image, path, encoding);
|
|
3541
3692
|
else await snapshots.stage(image, path, encoding);
|
|
@@ -3642,7 +3793,7 @@ async function withIdentifyFiles(input, stdinBytes, signal, run) {
|
|
|
3642
3793
|
// packages/safe-bash-command-imagemagick/src/index.ts
|
|
3643
3794
|
import { FsError as FsError4 } from "../safe-bash-contracts/errors.js";
|
|
3644
3795
|
import { resolvePath as resolvePath3 } from "../safe-bash-contracts/path.js";
|
|
3645
|
-
import { yieldTurn as
|
|
3796
|
+
import { yieldTurn as yieldTurn12, drainCooperativeSteps as drainSteps } from "../safe-bash-contracts/yield.js";
|
|
3646
3797
|
import { InputByteBudget } from "../safe-bash-contracts/io.js";
|
|
3647
3798
|
import { writeFileOutput as writeFileOutput2 } from "../safe-bash-contracts/filesystem-output-budget.js";
|
|
3648
3799
|
import {
|
|
@@ -3651,7 +3802,7 @@ import {
|
|
|
3651
3802
|
} from "../safe-bash-contracts/command.js";
|
|
3652
3803
|
import { readBytes as readBytes2, writeBytes as writeBytes2 } from "../safe-bash-contracts/io.js";
|
|
3653
3804
|
import { createOutputOperation } from "../safe-bash-contracts/output.js";
|
|
3654
|
-
import { readImageMetadataFromSource as readImageMetadataFromSource3, decodeImageToStorage as decodeImageToStorage2, transformStoredImage as transformStoredImage2, UnsupportedStoredResource as UnsupportedStoredResource4, decodeImage as decodeImage3, decodePngToCanvas, FONT_5X7,
|
|
3805
|
+
import { readImageMetadataFromSource as readImageMetadataFromSource3, decodeImageToStorage as decodeImageToStorage2, transformStoredImage as transformStoredImage2, UnsupportedStoredResource as UnsupportedStoredResource4, decodeImage as decodeImage3, decodePngToCanvas, FONT_5X7, readImageMetadata as readImageMetadata3, parseColor as baseParseColor, applyExifOrientationSteps, compositeImageSteps, computeImageStatsSteps as computeImageStatsSteps2, ensureAlphaImageSteps, extendImageSteps, extractChannelImageSteps, extractImageSteps as extractImageSteps2, flipImageSteps, flopImageSteps, grayscaleImageSteps, resizeImageSteps, rotateImageSteps, thresholdImageSteps } from "../image-ast/portable.js";
|
|
3655
3806
|
var X11_NAMED_COLORS = {
|
|
3656
3807
|
aliceblue: [240, 248, 255, 255],
|
|
3657
3808
|
antiquewhite: [250, 235, 215, 255],
|
|
@@ -3947,6 +4098,13 @@ function parseMagickGeometry(raw) {
|
|
|
3947
4098
|
break;
|
|
3948
4099
|
}
|
|
3949
4100
|
}
|
|
4101
|
+
if (s.includes(":")) {
|
|
4102
|
+
const parts = s.split(":");
|
|
4103
|
+
const ratio = Number(parts[0]) / Number(parts[1]);
|
|
4104
|
+
if (parts.length === 2 && Number(parts[0]) > 0 && Number(parts[1]) > 0 && Number.isFinite(ratio)) {
|
|
4105
|
+
return { aspectRatio: ratio, x, y, hasOffset, forceExact, shrinkOnly, enlargeOnly, fillArea, isPercent: false };
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
3950
4108
|
if (isArea) {
|
|
3951
4109
|
if (s.includes("x") || s.includes("X")) {
|
|
3952
4110
|
const [wStr, hStr] = s.split(/[xX]/);
|
|
@@ -4050,6 +4208,7 @@ function createDefaultState() {
|
|
|
4050
4208
|
tile: void 0,
|
|
4051
4209
|
strip: false,
|
|
4052
4210
|
adjoin: true,
|
|
4211
|
+
scene: 0,
|
|
4053
4212
|
dither: true,
|
|
4054
4213
|
formatStr: void 0,
|
|
4055
4214
|
channels: { r: true, g: true, b: true, a: false },
|
|
@@ -4500,6 +4659,7 @@ function* formatMagickPropertyStringSteps(fmt, meta, getImage, context = {}, res
|
|
|
4500
4659
|
Q: String(context.quality ?? meta.quality ?? 92)
|
|
4501
4660
|
};
|
|
4502
4661
|
const properties = {
|
|
4662
|
+
...meta.properties,
|
|
4503
4663
|
orientation: ["Undefined", "TopLeft", "TopRight", "BottomRight", "BottomLeft", "LeftTop", "RightTop", "RightBottom", "LeftBottom"][meta.orientation ?? 0] ?? "Undefined",
|
|
4504
4664
|
...meta.jpegSamplingFactor === void 0 ? {} : { "jpeg:sampling-factor": meta.jpegSamplingFactor },
|
|
4505
4665
|
"exif:orientation": meta.orientation === void 0 ? "" : String(meta.orientation),
|
|
@@ -4803,14 +4963,16 @@ function* createCheckerboardImageSteps(width, height) {
|
|
|
4803
4963
|
function* applyMagickSpliceSteps(img, geomStr, bg, gravity = "northwest", signal) {
|
|
4804
4964
|
let cooperativeWork = 0;
|
|
4805
4965
|
const g = parseMagickGeometry(geomStr);
|
|
4806
|
-
const sw = Math.max(0, Math.round(g.width ?? 0));
|
|
4807
|
-
const sh = Math.max(0, Math.round(g.height ?? 0));
|
|
4966
|
+
const sw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? img.width / 100 : 1)));
|
|
4967
|
+
const sh = Math.max(0, Math.round((g.height ?? 0) * (g.isPercent ? img.height / 100 : 1)));
|
|
4808
4968
|
const box = gravityAdjustBox(img.width, img.height, sw, sh, g.x, g.y, gravity);
|
|
4809
4969
|
const anchor = resolveGravityOffset(sw, sh, gravity);
|
|
4810
|
-
const sx = Math.max(0, Math.min(img.width, box.x + anchor.left));
|
|
4811
|
-
const sy = Math.max(0, Math.min(img.height, box.y + anchor.top));
|
|
4812
4970
|
const outW = img.width + sw;
|
|
4813
4971
|
const outH = img.height + sh;
|
|
4972
|
+
const xOffset = box.x + anchor.left;
|
|
4973
|
+
const sx = xOffset < 0 || xOffset > img.width ? outW : xOffset;
|
|
4974
|
+
if (box.y + anchor.top > outH) throw new Error("pixels are not authentic");
|
|
4975
|
+
const sy = Math.max(0, Math.min(img.height, box.y + anchor.top));
|
|
4814
4976
|
const out = new Uint8Array(new ArrayBuffer(outW * outH * 4 + outH), 0, outW * outH * 4);
|
|
4815
4977
|
for (let y = 0; y < outH; y++) {
|
|
4816
4978
|
if (++cooperativeWork % 65536 === 0)
|
|
@@ -4825,7 +4987,7 @@ function* applyMagickSpliceSteps(img, geomStr, bg, gravity = "northwest", signal
|
|
|
4825
4987
|
out[dstIdx + 2] = bg.b;
|
|
4826
4988
|
out[dstIdx + 3] = bg.a;
|
|
4827
4989
|
} else {
|
|
4828
|
-
const origX = x < sx ? x : x - sw;
|
|
4990
|
+
const origX = Math.min(img.width - 1, x < sx ? x : x - sw);
|
|
4829
4991
|
const origY = y < sy ? y : y - sh;
|
|
4830
4992
|
const srcIdx = (origY * img.width + origX) * 4;
|
|
4831
4993
|
out[dstIdx] = img.data[srcIdx];
|
|
@@ -4944,19 +5106,32 @@ function hasSceneOutputPattern(path) {
|
|
|
4944
5106
|
return false;
|
|
4945
5107
|
}
|
|
4946
5108
|
function formatSceneOutputPath(pattern, index) {
|
|
4947
|
-
|
|
4948
|
-
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
5109
|
+
let path = "", hasScene = false;
|
|
5110
|
+
for (let cursor = 0; cursor < pattern.length; cursor++) {
|
|
5111
|
+
if (pattern[cursor] === "%") {
|
|
5112
|
+
if (pattern[cursor + 1] === "%") {
|
|
5113
|
+
path += "%";
|
|
5114
|
+
cursor++;
|
|
5115
|
+
continue;
|
|
5116
|
+
}
|
|
5117
|
+
let end = cursor + 1;
|
|
5118
|
+
while (pattern[end] !== void 0 && pattern[end] >= "0" && pattern[end] <= "9") end++;
|
|
5119
|
+
if (pattern[end] === "d") {
|
|
5120
|
+
const width = Number(pattern.slice(cursor + 1, end));
|
|
5121
|
+
path += String(index).padStart(width, pattern[cursor + 1] === "0" ? "0" : " ");
|
|
5122
|
+
hasScene = true;
|
|
5123
|
+
cursor = end;
|
|
5124
|
+
continue;
|
|
5125
|
+
}
|
|
5126
|
+
}
|
|
5127
|
+
path += pattern[cursor];
|
|
4954
5128
|
}
|
|
4955
|
-
|
|
5129
|
+
if (hasScene) return path;
|
|
5130
|
+
const dot = path.lastIndexOf(".");
|
|
4956
5131
|
if (dot > 0) {
|
|
4957
|
-
return `${
|
|
5132
|
+
return `${path.slice(0, dot)}-${index}${path.slice(dot)}`;
|
|
4958
5133
|
}
|
|
4959
|
-
return `${
|
|
5134
|
+
return `${path}-${index}`;
|
|
4960
5135
|
}
|
|
4961
5136
|
function parseChannelMask(spec) {
|
|
4962
5137
|
const s = spec.toLowerCase().trim();
|
|
@@ -6898,13 +7073,12 @@ function magickCropArea(img, geomStr, gravity) {
|
|
|
6898
7073
|
}
|
|
6899
7074
|
function magickExtentLayout(img, geomStr, state) {
|
|
6900
7075
|
const g = parseMagickGeometry(geomStr);
|
|
6901
|
-
const targetW = Math.max(1, Math.round(g.width ?? img.width));
|
|
6902
|
-
const targetH = Math.max(1, Math.round(g.height ?? img.height));
|
|
6903
|
-
|
|
6904
|
-
const
|
|
6905
|
-
const
|
|
6906
|
-
const
|
|
6907
|
-
const top = Math.round(offset.top - (isSouth ? -g.y : g.y));
|
|
7076
|
+
const targetW = Math.max(1, Math.round(g.aspectRatio !== void 0 ? Math.min(img.width, img.height * g.aspectRatio) : g.isPercent ? img.width * (g.percentX ?? 100) / 100 : g.width ?? img.width));
|
|
7077
|
+
const targetH = Math.max(1, Math.round(g.aspectRatio !== void 0 ? Math.min(img.height, img.width / g.aspectRatio) : g.isPercent ? img.height * (g.percentY ?? 100) / 100 : g.height ?? img.height));
|
|
7078
|
+
if (g.enlargeOnly && img.width > targetW && img.height > targetH || g.shrinkOnly && img.width < targetW && img.height < targetH) return void 0;
|
|
7079
|
+
const offset = gravityAdjustBox(img.width, img.height, targetW, targetH, g.x, g.y, state.gravity);
|
|
7080
|
+
const left = -offset.x;
|
|
7081
|
+
const top = -offset.y;
|
|
6908
7082
|
const dstX0 = Math.max(0, left);
|
|
6909
7083
|
const dstY0 = Math.max(0, top);
|
|
6910
7084
|
const dstX1 = Math.min(targetW, left + img.width);
|
|
@@ -6914,6 +7088,7 @@ function magickExtentLayout(img, geomStr, state) {
|
|
|
6914
7088
|
function* applyMagickExtentSteps(img, geomStr, state, signal) {
|
|
6915
7089
|
yield;
|
|
6916
7090
|
const layout = magickExtentLayout(img, geomStr, state);
|
|
7091
|
+
if (!layout) return img;
|
|
6917
7092
|
const virtualCanvas = magickResizeCanvas(img, layout.width, layout.height);
|
|
6918
7093
|
const source = img[magickInput];
|
|
6919
7094
|
const canvas = {
|
|
@@ -6930,7 +7105,7 @@ async function decodeStoredMagickSvg(svg, density, backend, signal) {
|
|
|
6930
7105
|
const encoder = new TextEncoder(), base = backend.storage.allocate(0);
|
|
6931
7106
|
let size = 0;
|
|
6932
7107
|
for (let offset = 0; offset < svg.length; ) {
|
|
6933
|
-
await
|
|
7108
|
+
await yieldTurn12(signal);
|
|
6934
7109
|
const bytes = new Uint8Array(4096), { read, written } = encoder.encodeInto(svg.slice(offset, offset + 4097), bytes);
|
|
6935
7110
|
await backend.storage.write(backend.storage.allocate(written), bytes.subarray(0, written));
|
|
6936
7111
|
offset += read;
|
|
@@ -7297,12 +7472,32 @@ function* appendStackImagesSteps(stack, vertical, state) {
|
|
|
7297
7472
|
}
|
|
7298
7473
|
return { ...canvas, hasAlpha };
|
|
7299
7474
|
}
|
|
7475
|
+
function expandFilenameProperties(spec, state) {
|
|
7476
|
+
let output = "";
|
|
7477
|
+
for (let i = 0; i < spec.length; ) {
|
|
7478
|
+
if (spec.startsWith("%%", i)) {
|
|
7479
|
+
output += "%%";
|
|
7480
|
+
i += 2;
|
|
7481
|
+
continue;
|
|
7482
|
+
}
|
|
7483
|
+
if (spec.startsWith("%[filename:", i)) {
|
|
7484
|
+
const end = spec.indexOf("]", i + 11);
|
|
7485
|
+
if (end >= 0) {
|
|
7486
|
+
const key = spec.slice(i + 2, end).toLowerCase();
|
|
7487
|
+
output += state.filenameProperties?.[key] ?? spec.slice(i, end + 1);
|
|
7488
|
+
i = end + 1;
|
|
7489
|
+
continue;
|
|
7490
|
+
}
|
|
7491
|
+
}
|
|
7492
|
+
output += spec[i++];
|
|
7493
|
+
}
|
|
7494
|
+
return output;
|
|
7495
|
+
}
|
|
7300
7496
|
function inferOutputFormat(spec, fallback = "png") {
|
|
7301
7497
|
const prefixMatch = /^([a-zA-Z0-9]+):(.*)$/.exec(spec);
|
|
7302
7498
|
if (prefixMatch) {
|
|
7303
7499
|
const prefix = prefixMatch[1].toLowerCase();
|
|
7304
7500
|
const rest = prefixMatch[2];
|
|
7305
|
-
if (prefix === "rgba") throw new Error("unsupported output coder 'rgba'");
|
|
7306
7501
|
const fmt = extToImageFormat(prefix);
|
|
7307
7502
|
if (fmt) {
|
|
7308
7503
|
return { format: fmt, path: rest };
|
|
@@ -7317,7 +7512,11 @@ function inferOutputFormat(spec, fallback = "png") {
|
|
|
7317
7512
|
return { format: fallback, path: spec };
|
|
7318
7513
|
}
|
|
7319
7514
|
function extToImageFormat(ext) {
|
|
7515
|
+
const rawCoder = ext.toLowerCase();
|
|
7516
|
+
if (isRawCoder(rawCoder)) return rawCoder;
|
|
7320
7517
|
switch (ext.toLowerCase()) {
|
|
7518
|
+
case "miff":
|
|
7519
|
+
return "miff";
|
|
7321
7520
|
case "png":
|
|
7322
7521
|
return "png";
|
|
7323
7522
|
case "jpg":
|
|
@@ -7332,6 +7531,8 @@ function extToImageFormat(ext) {
|
|
|
7332
7531
|
case "tif":
|
|
7333
7532
|
case "tiff":
|
|
7334
7533
|
return "tiff";
|
|
7534
|
+
case "pam":
|
|
7535
|
+
return "pam";
|
|
7335
7536
|
case "ppm":
|
|
7336
7537
|
return "ppm";
|
|
7337
7538
|
case "pgm":
|
|
@@ -7440,6 +7641,15 @@ function* parseInputOperandsSteps(token, files, state, stdinBytes, maxDecodeDime
|
|
|
7440
7641
|
const { baseToken, pageSpec, inlineGeom } = parseInputToken(token);
|
|
7441
7642
|
function* applyMod(imgs) {
|
|
7442
7643
|
return yield* mapSteps(imgs, function* (im) {
|
|
7644
|
+
if (state.orientation !== void 0) im = { ...im, orientation: state.orientation };
|
|
7645
|
+
if (state.units !== void 0) im = applyMagickUnits(im, state.units);
|
|
7646
|
+
for (const key of ["comment", "label"]) {
|
|
7647
|
+
const value = state[key];
|
|
7648
|
+
if (value !== void 0) {
|
|
7649
|
+
const expanded = yield* formatMagickPropertyStringSteps(value, im, () => im, { filePath: baseToken });
|
|
7650
|
+
im = { ...im, properties: { ...im.properties, [key]: expanded } };
|
|
7651
|
+
}
|
|
7652
|
+
}
|
|
7443
7653
|
if (state.delay !== void 0) im = { ...im, delay: Array(im.delay?.length ?? 1).fill(state.delay) };
|
|
7444
7654
|
return inlineGeom ? yield* applyInlineReadModifierSteps(im, inlineGeom, state.kernel) : im;
|
|
7445
7655
|
});
|
|
@@ -7486,14 +7696,28 @@ function* parseInputOperandsSteps(token, files, state, stdinBytes, maxDecodeDime
|
|
|
7486
7696
|
if (lower === "null:") {
|
|
7487
7697
|
return yield* applyMod([yield* createSolidRgbaImageSteps(1, 1, { r: 0, g: 0, b: 0, a: 0 })]);
|
|
7488
7698
|
}
|
|
7489
|
-
|
|
7699
|
+
const rgb = lower.startsWith("rgb:");
|
|
7700
|
+
let cleanToken = rgb ? baseToken.slice(4) : baseToken;
|
|
7490
7701
|
const prefixMatch = /^([a-zA-Z0-9]+):(.*)$/.exec(cleanToken);
|
|
7491
7702
|
if (prefixMatch && extToImageFormat(prefixMatch[1])) {
|
|
7492
7703
|
cleanToken = prefixMatch[2];
|
|
7493
7704
|
}
|
|
7494
|
-
|
|
7705
|
+
let rawBytes = cleanToken === "-" ? stdinBytes : files.get(cleanToken) ?? files.get(token);
|
|
7495
7706
|
if (!rawBytes)
|
|
7496
7707
|
return void 0;
|
|
7708
|
+
if (rgb) {
|
|
7709
|
+
if (!state.hasSize) throw new Error("must specify image size for RGB input");
|
|
7710
|
+
const raw = rawRgbInput(state.sizeWidth, state.sizeHeight, state.inputDepth ?? 16, state.inputEndian ?? "lsb", rawBytes.length);
|
|
7711
|
+
const bytes = new Uint8Array(raw.size);
|
|
7712
|
+
for (let position = 0; position < raw.size; position += 8192) {
|
|
7713
|
+
yield;
|
|
7714
|
+
const steps = raw.read(position, Math.min(8192, raw.size - position));
|
|
7715
|
+
let next = steps.next();
|
|
7716
|
+
while (!next.done) next = steps.next(rawBytes.subarray(next.value.position, next.value.position + next.value.length));
|
|
7717
|
+
bytes.set(next.value, position);
|
|
7718
|
+
}
|
|
7719
|
+
rawBytes = bytes;
|
|
7720
|
+
}
|
|
7497
7721
|
let totalPages = 1;
|
|
7498
7722
|
let inputMeta;
|
|
7499
7723
|
try {
|
|
@@ -7644,7 +7868,7 @@ async function drainIdentifySteps(steps, signal) {
|
|
|
7644
7868
|
while (!next.done) {
|
|
7645
7869
|
try {
|
|
7646
7870
|
if (next.value) await next.value.run();
|
|
7647
|
-
else await
|
|
7871
|
+
else await yieldTurn12(signal);
|
|
7648
7872
|
next = steps.next();
|
|
7649
7873
|
} catch (error) {
|
|
7650
7874
|
next = steps.throw(error);
|
|
@@ -8505,7 +8729,7 @@ async function transformStoredMagickPixels(image, backend, operation, signal, hi
|
|
|
8505
8729
|
let storedData16;
|
|
8506
8730
|
let storedHueSamples;
|
|
8507
8731
|
for (let offset = 0; offset < size; offset += 16384) {
|
|
8508
|
-
if (offset % 1048576 === 0) await
|
|
8732
|
+
if (offset % 1048576 === 0) await yieldTurn12(signal);
|
|
8509
8733
|
const data = await backend.storage.read(image.position + offset, Math.min(16384, size - offset));
|
|
8510
8734
|
const bytes16 = (highDepth || operation.highDepth) && image.storedData16 ? await backend.storage.read(image.storedData16.position + offset * 2, data.length * 2) : void 0;
|
|
8511
8735
|
const data16 = bytes16 ? new Uint16Array(bytes16.buffer, bytes16.byteOffset, bytes16.byteLength / 2) : void 0;
|
|
@@ -8527,9 +8751,118 @@ async function transformStoredMagickPixels(image, backend, operation, signal, hi
|
|
|
8527
8751
|
}
|
|
8528
8752
|
return result;
|
|
8529
8753
|
}
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
|
|
8754
|
+
function* prepareMiffPages(stack) {
|
|
8755
|
+
const miffPages = [];
|
|
8756
|
+
for (const frame of stack) {
|
|
8757
|
+
yield;
|
|
8758
|
+
miffPages.push(yield* prepareMagickOutput(frame, "miff"));
|
|
8759
|
+
}
|
|
8760
|
+
return { ...miffPages[0], miffPages };
|
|
8761
|
+
}
|
|
8762
|
+
function prepareStoredMiffPages(stack, image, backend, signal) {
|
|
8763
|
+
return { ...image, storedMiffPages: { length: stack.length, async at(index) {
|
|
8764
|
+
return prepareStoredMagickOutput(await stack.get(index), "miff", backend, signal);
|
|
8765
|
+
} } };
|
|
8766
|
+
}
|
|
8767
|
+
function* prepareTiffPages(stack) {
|
|
8768
|
+
const tiffPages = [];
|
|
8769
|
+
for (const frame of stack) {
|
|
8770
|
+
yield;
|
|
8771
|
+
tiffPages.push(yield* prepareMagickOutput(frame, "tiff"));
|
|
8772
|
+
}
|
|
8773
|
+
return { ...tiffPages[0], tiffPages };
|
|
8774
|
+
}
|
|
8775
|
+
function prepareStoredTiffPages(stack, image, backend, signal) {
|
|
8776
|
+
return { ...image, storedTiffPages: { length: stack.length, async at(index) {
|
|
8777
|
+
return prepareStoredMagickOutput(await stack.get(index), "tiff", backend, signal);
|
|
8778
|
+
} } };
|
|
8779
|
+
}
|
|
8780
|
+
function* prepareGifFrames(stack) {
|
|
8781
|
+
let cooperativeWork = 0;
|
|
8782
|
+
let fw = 0, fh = 0;
|
|
8783
|
+
for (const frame of stack) {
|
|
8784
|
+
fw = Math.max(fw, frame.width);
|
|
8785
|
+
fh = Math.max(fh, frame.height);
|
|
8786
|
+
}
|
|
8787
|
+
const combined = new Uint8Array(fw * fh * stack.length * 4);
|
|
8788
|
+
const delays = [];
|
|
8789
|
+
const disposals = [];
|
|
8790
|
+
for (let idx = 0; idx < stack.length; idx++) {
|
|
8791
|
+
if (++cooperativeWork % 64 === 0) yield;
|
|
8792
|
+
const outputFrame = yield* prepareMagickOutput(stack[idx], "gif");
|
|
8793
|
+
disposals.push(typeof outputFrame.disposal === "number" ? outputFrame.disposal : 1);
|
|
8794
|
+
delays.push(outputFrame.delay?.[stack[idx][magickInput]?.sceneIdx ?? 0] ?? 100);
|
|
8795
|
+
for (let y = 0; y < outputFrame.height; y++) {
|
|
8796
|
+
if (++cooperativeWork % 64 === 0) yield;
|
|
8797
|
+
combined.set(outputFrame.data.subarray(y * outputFrame.width * 4, (y + 1) * outputFrame.width * 4), (idx * fw * fh + y * fw) * 4);
|
|
8798
|
+
}
|
|
8799
|
+
}
|
|
8800
|
+
return {
|
|
8801
|
+
...yield* prepareMagickOutput(stack[0], "gif"),
|
|
8802
|
+
width: fw,
|
|
8803
|
+
height: fh * stack.length,
|
|
8804
|
+
pages: stack.length,
|
|
8805
|
+
pageHeight: fh,
|
|
8806
|
+
delay: delays,
|
|
8807
|
+
disposal: disposals,
|
|
8808
|
+
gifFrames: stack.map((frame) => ({ width: frame.width, height: frame.height, x: frame.virtualCanvas?.x ?? 0, y: frame.virtualCanvas?.y ?? 0 })),
|
|
8809
|
+
data: combined
|
|
8810
|
+
};
|
|
8811
|
+
}
|
|
8812
|
+
async function prepareStoredGifFrames(stack, backend, signal) {
|
|
8813
|
+
const first = await prepareStoredMagickOutput(await stack.get(0), "gif", backend, signal);
|
|
8814
|
+
let width = first.width, height = first.height;
|
|
8815
|
+
for (let index = 1; index < stack.length; index++) {
|
|
8816
|
+
const frame = await stack.get(index);
|
|
8817
|
+
width = Math.max(width, frame.width);
|
|
8818
|
+
height = Math.max(height, frame.height);
|
|
8819
|
+
}
|
|
8820
|
+
const size = width * height * 4, position = backend.storage.allocate(size * stack.length);
|
|
8821
|
+
for (let index = 0; index < stack.length; index++) {
|
|
8822
|
+
const frame = await prepareStoredMagickOutput(await stack.get(index), "gif", backend, signal);
|
|
8823
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x += 4096) {
|
|
8824
|
+
await yieldTurn12(signal);
|
|
8825
|
+
const count = Math.min(4096, width - x), bytes = new Uint8Array(count * 4);
|
|
8826
|
+
if (y < frame.height && x < frame.width) bytes.set(await backend.storage.read(frame.position + (y * frame.width + x) * 4, Math.min(count, frame.width - x) * 4));
|
|
8827
|
+
await backend.storage.write(position + index * size + (y * width + x) * 4, bytes);
|
|
8828
|
+
}
|
|
8829
|
+
}
|
|
8830
|
+
const { storedData16: ignored, ...metadata } = first;
|
|
8831
|
+
return {
|
|
8832
|
+
...metadata,
|
|
8833
|
+
position,
|
|
8834
|
+
width,
|
|
8835
|
+
height: height * stack.length,
|
|
8836
|
+
pages: stack.length,
|
|
8837
|
+
pageHeight: height,
|
|
8838
|
+
storedGifFrame: { async at(index) {
|
|
8839
|
+
const frame = await stack.get(index);
|
|
8840
|
+
return { width: frame.width, height: frame.height, x: frame.virtualCanvas?.x ?? 0, y: frame.virtualCanvas?.y ?? 0 };
|
|
8841
|
+
} },
|
|
8842
|
+
storedDisposal: { length: stack.length, async at(index) {
|
|
8843
|
+
const frame = await stack.get(index);
|
|
8844
|
+
return typeof frame.disposal === "number" ? frame.disposal : 1;
|
|
8845
|
+
} },
|
|
8846
|
+
storedDelay: { length: stack.length, async at(index) {
|
|
8847
|
+
const frame = await stack.get(index);
|
|
8848
|
+
const scene = frame[magickInput]?.sceneIdx ?? 0;
|
|
8849
|
+
return await frame.storedDelay?.at(scene, { signal }) ?? frame.delay?.[scene] ?? 100;
|
|
8850
|
+
} }
|
|
8851
|
+
};
|
|
8852
|
+
}
|
|
8853
|
+
function* prepareMagickOutput(image, format) {
|
|
8854
|
+
image = yield* prepareHueOutput(image, format);
|
|
8855
|
+
if (format !== "pbm") return image;
|
|
8856
|
+
const source = image.data16 ? { ...image, data: new Uint8Array(image.data16.buffer, image.data16.byteOffset, image.data16.byteLength) } : image;
|
|
8857
|
+
return yield* applyMagickRasterSteps({ ...image, space: "b-w", channels: 1, hasAlpha: false }, bilevelPixelSteps(image.width * image.height, !!image.data16), void 0, { ...image, hasAlpha: false }, [source]);
|
|
8858
|
+
}
|
|
8859
|
+
async function prepareStoredMagickOutput(image, format, backend, signal) {
|
|
8860
|
+
if (image.magickColorspace === "HSL" || image.magickColorspace === "HSB" || image.magickColorspace === "HWB" || image.magickColorspace === "XYZ" || image.magickColorspace === "YCbCr" || image.magickColorspace === "YUV") {
|
|
8861
|
+
image = await transformStoredMagickPixels(image, backend, { end: 0, highDepth: true, apply: (frame) => prepareHueOutput(frame, format) }, signal);
|
|
8862
|
+
}
|
|
8863
|
+
if (format !== "pbm") return image;
|
|
8864
|
+
const source = image.storedData16 ? { ...image, position: image.storedData16.position } : image;
|
|
8865
|
+
return transformStoredMagickRaster({ ...image, space: "b-w", channels: 1, hasAlpha: false }, backend, bilevelPixelSteps(image.width * image.height, !!image.storedData16), signal, { ...image, hasAlpha: false }, [source]);
|
|
8533
8866
|
}
|
|
8534
8867
|
function parseMagickDisposal(value) {
|
|
8535
8868
|
const names = ["undefined", "none", "background", "previous"];
|
|
@@ -8538,6 +8871,49 @@ function parseMagickDisposal(value) {
|
|
|
8538
8871
|
if (["0", "1", "2", "3"].includes(value)) return Number(value);
|
|
8539
8872
|
return 0;
|
|
8540
8873
|
}
|
|
8874
|
+
function parseMagickOrientation(value) {
|
|
8875
|
+
const orientation = ["undefined", "topleft", "topright", "bottomright", "bottomleft", "lefttop", "righttop", "rightbottom", "leftbottom"].indexOf(value.toLowerCase());
|
|
8876
|
+
if (orientation < 0) throw new Error(`unrecognized image orientation '-orient' '${value}'`);
|
|
8877
|
+
return orientation;
|
|
8878
|
+
}
|
|
8879
|
+
function parseMagickUnits(value) {
|
|
8880
|
+
switch (value.toLowerCase()) {
|
|
8881
|
+
case "pixelsperinch":
|
|
8882
|
+
return "inch";
|
|
8883
|
+
case "pixelspercentimeter":
|
|
8884
|
+
return "cm";
|
|
8885
|
+
case "undefined":
|
|
8886
|
+
return "unknown";
|
|
8887
|
+
default:
|
|
8888
|
+
throw new Error(`unrecognized units type '-units' '${value}'`);
|
|
8889
|
+
}
|
|
8890
|
+
}
|
|
8891
|
+
function applyMagickUnits(image, unit) {
|
|
8892
|
+
const scale = image.resolution?.unit === "meter" ? 100 : 1;
|
|
8893
|
+
const x = image.resolution ? image.resolution.x / scale : image.density;
|
|
8894
|
+
const y = image.resolution ? image.resolution.y / scale : image.density;
|
|
8895
|
+
return { ...image, density: x * (unit === "cm" ? 2.54 : 1), resolution: { x, y, unit } };
|
|
8896
|
+
}
|
|
8897
|
+
function magickResampleGeometry(image, value) {
|
|
8898
|
+
const geometry = parseMagickGeometry(value);
|
|
8899
|
+
const x = geometry.width ?? 72, y = geometry.height ?? x;
|
|
8900
|
+
if (!(x > 0) || !(y > 0)) throw new Error(`invalid argument '-resample' '${value}'`);
|
|
8901
|
+
const scale = image.resolution?.unit === "meter" ? 100 : 1;
|
|
8902
|
+
const sourceX = (image.resolution ? image.resolution.x / scale : image.density) || 72;
|
|
8903
|
+
const sourceY = (image.resolution ? image.resolution.y / scale : image.density) || 72;
|
|
8904
|
+
return `${Math.max(1, Math.round(image.width * x / sourceX))}x${Math.max(1, Math.round(image.height * y / sourceY))}!`;
|
|
8905
|
+
}
|
|
8906
|
+
function applyMagickDensity(image, value) {
|
|
8907
|
+
const geometry = parseMagickGeometry(value);
|
|
8908
|
+
const x = geometry.width ?? 72, y = geometry.height ?? x;
|
|
8909
|
+
const unit = image.resolution?.unit ?? "unknown";
|
|
8910
|
+
const scale = unit === "meter" ? 100 : 1;
|
|
8911
|
+
return {
|
|
8912
|
+
...image,
|
|
8913
|
+
density: x * (unit === "cm" || unit === "meter" ? 2.54 : 1),
|
|
8914
|
+
resolution: { x: x * scale, y: y * scale, unit }
|
|
8915
|
+
};
|
|
8916
|
+
}
|
|
8541
8917
|
function applyMagickReadSetting(tokens, state, start) {
|
|
8542
8918
|
let i = start;
|
|
8543
8919
|
const t = tokens[i];
|
|
@@ -8554,6 +8930,23 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8554
8930
|
} else if (t === "+channel") {
|
|
8555
8931
|
state.channels = { r: true, g: true, b: true, a: false };
|
|
8556
8932
|
state.channelExplicit = false;
|
|
8933
|
+
} else if (t === "-depth") {
|
|
8934
|
+
state.inputDepth = Number(tokens[++i]);
|
|
8935
|
+
if (!Number.isInteger(state.inputDepth) || state.inputDepth < 1) throw new Error("invalid input depth");
|
|
8936
|
+
} else if (t === "-compress") {
|
|
8937
|
+
const compression = (tokens[++i] ?? "").toLowerCase();
|
|
8938
|
+
if (compression !== "none" && compression !== "zip") throw new Error(`unsupported compression '${compression}'`);
|
|
8939
|
+
state.netpbmAscii = compression === "none";
|
|
8940
|
+
} else if (t === "+compress") {
|
|
8941
|
+
delete state.netpbmAscii;
|
|
8942
|
+
} else if (t === "+depth") {
|
|
8943
|
+
delete state.inputDepth;
|
|
8944
|
+
} else if (t === "-endian") {
|
|
8945
|
+
const endian = (tokens[++i] ?? "").toLowerCase();
|
|
8946
|
+
if (!["msb", "lsb", "undefined"].includes(endian)) throw new Error(`unrecognized endian type '${endian}'`);
|
|
8947
|
+
state.inputEndian = endian;
|
|
8948
|
+
} else if (t === "+endian") {
|
|
8949
|
+
delete state.inputEndian;
|
|
8557
8950
|
} else if (t === "-size") {
|
|
8558
8951
|
const g = parseMagickGeometry(tokens[++i] ?? "1x1");
|
|
8559
8952
|
state.sizeWidth = Math.max(1, Math.round(g.width ?? 1));
|
|
@@ -8586,6 +8979,8 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8586
8979
|
state.gravity = parseGravity(tokens[++i] ?? "center");
|
|
8587
8980
|
} else if (t === "+gravity") {
|
|
8588
8981
|
state.gravity = "northwest";
|
|
8982
|
+
} else if (t === "-comment" || t === "-label") {
|
|
8983
|
+
state[t === "-comment" ? "comment" : "label"] = tokens[++i] ?? "";
|
|
8589
8984
|
} else if (t === "-sampling-factor") {
|
|
8590
8985
|
state.samplingFactor = tokens[++i] ?? "";
|
|
8591
8986
|
} else if (t === "+sampling-factor") {
|
|
@@ -8607,6 +9002,9 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8607
9002
|
state.compose = parseCompose(cRaw);
|
|
8608
9003
|
} else if (t === "-define") {
|
|
8609
9004
|
const defStr = tokens[++i] ?? "";
|
|
9005
|
+
if (defStr.toLowerCase().startsWith("png:exclude-chunk=")) {
|
|
9006
|
+
state.omitPngResolution = defStr.slice("png:exclude-chunk=".length).split(",").some((chunk) => ["phys", "all"].includes(chunk.trim().toLowerCase()));
|
|
9007
|
+
}
|
|
8610
9008
|
if (defStr.toLowerCase().startsWith("connected-components:")) {
|
|
8611
9009
|
const [key, value, extra] = defStr.toLowerCase().split("=");
|
|
8612
9010
|
if (extra !== void 0 || key !== "connected-components:verbose" || value !== "true" && value !== "false") throw new Error(`Unsupported connected-components define: ${defStr}`);
|
|
@@ -8620,12 +9018,13 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8620
9018
|
const k = (tokens[++i] ?? "").toLowerCase();
|
|
8621
9019
|
const v = tokens[++i] ?? "";
|
|
8622
9020
|
if (k.startsWith("option:connected-components:") || k.startsWith("connected-components:")) throw new Error(`Unsupported connected-components setting: ${k}`);
|
|
9021
|
+
if (k.startsWith("filename:")) state.filenameProperties = { ...state.filenameProperties, [k]: v };
|
|
8623
9022
|
if (k === "option:compose:args")
|
|
8624
9023
|
state.composeArgs = v;
|
|
8625
9024
|
} else return void 0;
|
|
8626
9025
|
return i;
|
|
8627
9026
|
}
|
|
8628
|
-
function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBytes, signal, analysis = { text: "", warnings: "" }) {
|
|
9027
|
+
function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBytes, signal, analysis = { text: "", warnings: "", bytes: [] }, registers = /* @__PURE__ */ new Map()) {
|
|
8629
9028
|
let cooperativeWork = 63;
|
|
8630
9029
|
let stack = [];
|
|
8631
9030
|
let operandsOnly = false;
|
|
@@ -8638,9 +9037,20 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8638
9037
|
i++;
|
|
8639
9038
|
continue;
|
|
8640
9039
|
}
|
|
9040
|
+
if (t.slice(0, 4).toLowerCase() === "mpr:") {
|
|
9041
|
+
const saved = registers.get(t.slice(4));
|
|
9042
|
+
if (!saved) throw new Error(`unable to open image '${t}'`);
|
|
9043
|
+
for (const image of saved) {
|
|
9044
|
+
yield;
|
|
9045
|
+
stack.push({ ...image, data: new Uint8Array(image.data) });
|
|
9046
|
+
}
|
|
9047
|
+
i++;
|
|
9048
|
+
continue;
|
|
9049
|
+
}
|
|
8641
9050
|
if (operandsOnly) {
|
|
8642
9051
|
const loaded = yield* parseInputOperandsSteps(t, files, state, stdinBytes);
|
|
8643
|
-
if (loaded)
|
|
9052
|
+
if (!loaded) throw new Error(`unable to open image '${t}'`);
|
|
9053
|
+
stack.push(...loaded);
|
|
8644
9054
|
i++;
|
|
8645
9055
|
continue;
|
|
8646
9056
|
}
|
|
@@ -8659,11 +9069,39 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8659
9069
|
const endIdx = depth === 0 ? j - 1 : j;
|
|
8660
9070
|
const subTokens = tokens.slice(i + 1, endIdx);
|
|
8661
9071
|
const subState = { ...state };
|
|
8662
|
-
const subResult = yield* evaluatePipelineTokensSteps(subTokens, files, subState, stack, stdinBytes, signal, analysis);
|
|
9072
|
+
const subResult = yield* evaluatePipelineTokensSteps(subTokens, files, subState, stack, stdinBytes, signal, analysis, registers);
|
|
8663
9073
|
stack.push(...subResult);
|
|
8664
9074
|
i = j;
|
|
8665
9075
|
continue;
|
|
8666
9076
|
}
|
|
9077
|
+
if (t === "-orient") {
|
|
9078
|
+
const orientation = state.orientation = parseMagickOrientation(tokens[++i] ?? "");
|
|
9079
|
+
stack = yield* mapSteps(stack, function* (image) {
|
|
9080
|
+
yield;
|
|
9081
|
+
return { ...image, orientation };
|
|
9082
|
+
});
|
|
9083
|
+
i++;
|
|
9084
|
+
continue;
|
|
9085
|
+
}
|
|
9086
|
+
if (t === "-units") {
|
|
9087
|
+
const units = state.units = parseMagickUnits(tokens[++i] ?? "");
|
|
9088
|
+
stack = yield* mapSteps(stack, function* (image) {
|
|
9089
|
+
yield;
|
|
9090
|
+
return applyMagickUnits(image, units);
|
|
9091
|
+
});
|
|
9092
|
+
i++;
|
|
9093
|
+
continue;
|
|
9094
|
+
}
|
|
9095
|
+
if (t === "-density") {
|
|
9096
|
+
const value = tokens[++i] ?? "72";
|
|
9097
|
+
state.density = Math.max(1, Math.round(parseMagickGeometry(value).width ?? 72));
|
|
9098
|
+
stack = yield* mapSteps(stack, function* (image) {
|
|
9099
|
+
yield;
|
|
9100
|
+
return applyMagickDensity(image, value);
|
|
9101
|
+
});
|
|
9102
|
+
i++;
|
|
9103
|
+
continue;
|
|
9104
|
+
}
|
|
8667
9105
|
if (t === "-set" && tokens[i + 1]?.toLowerCase() === "delay") {
|
|
8668
9106
|
const delay = Number(tokens[i + 2] ?? 0) * 10;
|
|
8669
9107
|
stack = yield* mapSteps(stack, function* (image) {
|
|
@@ -8682,6 +9120,26 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8682
9120
|
i += 3;
|
|
8683
9121
|
continue;
|
|
8684
9122
|
}
|
|
9123
|
+
if (t === "-set" && !tokens[i + 1]?.toLowerCase().startsWith("option:") && !tokens[i + 1]?.toLowerCase().startsWith("filename:") && !tokens[i + 1]?.toLowerCase().startsWith("connected-components:")) {
|
|
9124
|
+
const key = tokens[++i] ?? "", value = tokens[++i] ?? "";
|
|
9125
|
+
stack = yield* mapSteps(stack, function* (image) {
|
|
9126
|
+
const expanded = yield* formatMagickPropertyStringSteps(value, image, () => image, image[magickInput]);
|
|
9127
|
+
return key.toLowerCase() === "density" ? applyMagickDensity(image, expanded) : { ...image, properties: { ...image.properties, [key]: expanded } };
|
|
9128
|
+
});
|
|
9129
|
+
i++;
|
|
9130
|
+
continue;
|
|
9131
|
+
}
|
|
9132
|
+
if (t === "+set") {
|
|
9133
|
+
const key = tokens[++i] ?? "";
|
|
9134
|
+
stack = yield* mapSteps(stack, function* (image) {
|
|
9135
|
+
yield;
|
|
9136
|
+
const properties = { ...image.properties };
|
|
9137
|
+
delete properties[key];
|
|
9138
|
+
return { ...image, properties };
|
|
9139
|
+
});
|
|
9140
|
+
i++;
|
|
9141
|
+
continue;
|
|
9142
|
+
}
|
|
8685
9143
|
const setting = applyMagickReadSetting(tokens, state, i);
|
|
8686
9144
|
const pixelOperation = setting === void 0 ? parseMagickPixelOperation(tokens, state, i, signal) : void 0;
|
|
8687
9145
|
const warpOperation = setting === void 0 ? parseMagickWarpOperation(tokens, state, i) : void 0;
|
|
@@ -8723,35 +9181,59 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8723
9181
|
return { ...output, ..."space" in plan && plan.space ? { space: plan.space, channels: plan.space === "srgb" ? 4 : output.channels } : {}, ...plan.virtualCanvas ? { virtualCanvas: plan.virtualCanvas } : {} };
|
|
8724
9182
|
});
|
|
8725
9183
|
} else if (t === "-write" || t === "+write") {
|
|
8726
|
-
|
|
8727
|
-
if (stack.length
|
|
9184
|
+
if (i + 1 >= tokens.length) throw new Error(`missing argument '${t}'`);
|
|
9185
|
+
if (stack.length === 0) throw new Error(`no images for write '${t}'`);
|
|
9186
|
+
const writePath = expandFilenameProperties(tokens[++i] ?? "", state);
|
|
9187
|
+
if (writePath.slice(0, 4).toLowerCase() === "mpr:") {
|
|
9188
|
+
const saved = [];
|
|
9189
|
+
for (const image of stack) {
|
|
9190
|
+
yield;
|
|
9191
|
+
saved.push({ ...image, data: new Uint8Array(image.data) });
|
|
9192
|
+
}
|
|
9193
|
+
registers.set(writePath.slice(4), saved);
|
|
9194
|
+
} else if (stack.length > 0 && writePath && writePath.toLowerCase() !== "null:") {
|
|
8728
9195
|
const top = stack[stack.length - 1];
|
|
8729
9196
|
const { format, path } = inferOutputFormat(writePath, top.format);
|
|
8730
|
-
if (stack.length > 1 && (
|
|
9197
|
+
if (hasSceneOutputPattern(path) || stack.length > 1 && (!state.adjoin || path !== "-" && ["png", "jpeg", "bmp"].includes(format))) {
|
|
8731
9198
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
8732
9199
|
if (++cooperativeWork % 65536 === 0)
|
|
8733
9200
|
yield;
|
|
8734
|
-
const framePath = formatSceneOutputPath(path, idx);
|
|
8735
|
-
const { data: frameBytes } = encodeImage(yield*
|
|
9201
|
+
const framePath = formatSceneOutputPath(path, state.scene + idx);
|
|
9202
|
+
const { data: frameBytes } = encodeImage(yield* prepareMagickOutput(stack[idx], format), { format, netpbmAscii: state.netpbmAscii ?? false, ...state.inputDepth === void 0 ? {} : { netpbmDepth: Math.min(16, state.inputDepth) }, endian: state.inputEndian, omitPngResolution: state.strip || state.omitPngResolution === true, ...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor }, chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4", quality: state.quality });
|
|
8736
9203
|
files.set(framePath, frameBytes);
|
|
8737
9204
|
}
|
|
8738
9205
|
} else {
|
|
8739
|
-
const
|
|
8740
|
-
|
|
9206
|
+
const image = stack.length > 1 && format === "miff" ? yield* prepareMiffPages(stack) : stack.length > 1 && format === "tiff" ? yield* prepareTiffPages(stack) : stack.length > 1 && format === "gif" ? yield* prepareGifFrames(stack) : yield* prepareMagickOutput(top, format);
|
|
9207
|
+
const { data: encoded } = encodeImage(image, { format, ...stack.length > 1 && format === "gif" ? { pageHeight: image.pageHeight } : {}, ...state.loop === void 0 ? {} : { loop: state.loop }, ...state.optimizeLayers ? { optimizeFrames: true } : {}, netpbmAscii: state.netpbmAscii ?? false, ...state.inputDepth === void 0 ? {} : { netpbmDepth: Math.min(16, state.inputDepth) }, endian: state.inputEndian, omitPngResolution: state.strip || state.omitPngResolution === true, ...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor }, chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4", quality: state.quality });
|
|
9208
|
+
if (path === "-") analysis.bytes.push(encoded);
|
|
9209
|
+
else files.set(path, encoded);
|
|
8741
9210
|
}
|
|
8742
9211
|
}
|
|
8743
9212
|
} else if (t === "-geometry") {
|
|
8744
9213
|
state.geometry = tokens[++i] ?? "+0+0";
|
|
8745
9214
|
} else if (t === "-tile") {
|
|
8746
9215
|
state.tile = tokens[++i];
|
|
9216
|
+
} else if (t === "-profile" || t === "+profile") {
|
|
9217
|
+
const name = tokens[++i];
|
|
9218
|
+
if (!name) throw new Error(`missing argument '${t}'`);
|
|
9219
|
+
const profile = t === "-profile" ? files.get(name) : void 0;
|
|
9220
|
+
if (t === "-profile" && !profile) throw new Error(`unable to open profile '${name}'`);
|
|
9221
|
+
stack = stack.map((image) => applyMagickProfile(image, name, profile));
|
|
8747
9222
|
} else if (t === "-strip") {
|
|
8748
9223
|
state.strip = true;
|
|
9224
|
+
for (let index = 0; index < stack.length; index++) {
|
|
9225
|
+
const { icc: ignored, properties: ignoredProperties, ...image } = stack[index];
|
|
9226
|
+
stack[index] = image;
|
|
9227
|
+
}
|
|
8749
9228
|
} else if (t === "-format") {
|
|
8750
9229
|
state.formatStr = tokens[++i] ?? "";
|
|
8751
9230
|
} else if (t === "+adjoin") {
|
|
8752
9231
|
state.adjoin = false;
|
|
8753
9232
|
} else if (t === "-adjoin") {
|
|
8754
9233
|
state.adjoin = true;
|
|
9234
|
+
} else if (t === "-scene") {
|
|
9235
|
+
state.scene = Number(tokens[++i]);
|
|
9236
|
+
if (!Number.isSafeInteger(state.scene) || state.scene < 0) throw new Error("invalid scene number");
|
|
8755
9237
|
} else if (t === "-delay") {
|
|
8756
9238
|
state.delay = Number(tokens[++i] ?? 0) * 10;
|
|
8757
9239
|
} else if (t === "-loop") {
|
|
@@ -8920,6 +9402,12 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8920
9402
|
const { virtualCanvas: ignoredCanvas, ...reset } = image;
|
|
8921
9403
|
return reset;
|
|
8922
9404
|
});
|
|
9405
|
+
} else if (t === "-resample") {
|
|
9406
|
+
const value = tokens[++i] ?? "72";
|
|
9407
|
+
stack = yield* mapSteps(stack, function* (image) {
|
|
9408
|
+
const resized = yield* applyMagickResizeSteps(image, magickResampleGeometry(image, value), state.kernel);
|
|
9409
|
+
return applyMagickDensity(resized, value);
|
|
9410
|
+
});
|
|
8923
9411
|
} else if (t === "-resize" || t === "-scale" || t === "-sample" || t === "-thumbnail") {
|
|
8924
9412
|
const geom = tokens[++i] ?? "100%";
|
|
8925
9413
|
const k = t === "-sample" ? "nearest" : state.kernel;
|
|
@@ -8950,18 +9438,22 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8950
9438
|
return { ...canvas, virtualCanvas: magickBorderCanvas(im, bw, bh) };
|
|
8951
9439
|
});
|
|
8952
9440
|
} else if (t === "-shave") {
|
|
8953
|
-
const
|
|
9441
|
+
const geometry = tokens[++i] ?? "0x0";
|
|
9442
|
+
const g = parseMagickGeometry(geometry);
|
|
8954
9443
|
const sw = Math.max(0, Math.round(g.width ?? 0));
|
|
8955
9444
|
const sh = Math.max(0, Math.round(g.height ?? sw));
|
|
8956
9445
|
stack = yield* mapSteps(stack, function* (im) {
|
|
8957
|
-
|
|
8958
|
-
|
|
9446
|
+
if (sw * 2 >= im.width || sh * 2 >= im.height) {
|
|
9447
|
+
analysis.warnings += `magick: geometry does not contain image '${geometry}'
|
|
9448
|
+
`;
|
|
9449
|
+
return im;
|
|
9450
|
+
}
|
|
8959
9451
|
return { ...yield* extractImageSteps2(im, {
|
|
8960
|
-
left:
|
|
8961
|
-
top:
|
|
8962
|
-
width:
|
|
8963
|
-
height:
|
|
8964
|
-
}), virtualCanvas: magickBorderCanvas(im, -
|
|
9452
|
+
left: sw,
|
|
9453
|
+
top: sh,
|
|
9454
|
+
width: im.width - sw * 2,
|
|
9455
|
+
height: im.height - sh * 2
|
|
9456
|
+
}), virtualCanvas: magickBorderCanvas(im, -sw, -sh) };
|
|
8965
9457
|
});
|
|
8966
9458
|
} else if (t === "-trim") {
|
|
8967
9459
|
stack = yield* mapSteps(stack, function* (im) {
|
|
@@ -9294,25 +9786,36 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
9294
9786
|
if (mergeOntoCanvas) {
|
|
9295
9787
|
state.background = prevBg;
|
|
9296
9788
|
}
|
|
9297
|
-
if (loaded) {
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
}
|
|
9789
|
+
if (!loaded) throw new Error(`unable to open image '${t}'`);
|
|
9790
|
+
if (mergeOntoCanvas && loaded[0]) {
|
|
9791
|
+
yield* blitOverRgbaInPlaceSteps(stack[0], loaded[0], 0, 0);
|
|
9792
|
+
detachRgbaBuffer(loaded[0].data);
|
|
9793
|
+
} else {
|
|
9794
|
+
stack.push(...loaded);
|
|
9304
9795
|
}
|
|
9305
9796
|
}
|
|
9306
9797
|
i++;
|
|
9307
9798
|
}
|
|
9308
9799
|
return stack;
|
|
9309
9800
|
}
|
|
9801
|
+
function combineConvertOutput(result, analysis) {
|
|
9802
|
+
const stdout = analysis.text + result.stdout, stderr = analysis.warnings + result.stderr;
|
|
9803
|
+
if (!analysis.bytes.length) return { ...result, stdout, stderr };
|
|
9804
|
+
const chunks = [...analysis.bytes, ...result.stdoutBytes ? [result.stdoutBytes] : stdout ? [new TextEncoder().encode(stdout)] : []];
|
|
9805
|
+
const stdoutBytes = new Uint8Array(chunks.reduce((size, chunk) => size + chunk.length, 0));
|
|
9806
|
+
let offset = 0;
|
|
9807
|
+
for (const chunk of chunks) {
|
|
9808
|
+
stdoutBytes.set(chunk, offset);
|
|
9809
|
+
offset += chunk.length;
|
|
9810
|
+
}
|
|
9811
|
+
return { ...result, stdout: "", stderr, stdoutBytes };
|
|
9812
|
+
}
|
|
9310
9813
|
function* runConvertCliSteps(argv, files, stdinBytes, signal) {
|
|
9311
|
-
const analysis = { text: "", warnings: "" };
|
|
9814
|
+
const analysis = { text: "", warnings: "", bytes: [] };
|
|
9312
9815
|
const result = yield* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis);
|
|
9313
|
-
return
|
|
9816
|
+
return combineConvertOutput(result, analysis);
|
|
9314
9817
|
}
|
|
9315
|
-
function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = { text: "", warnings: "" }) {
|
|
9818
|
+
function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = { text: "", warnings: "", bytes: [] }) {
|
|
9316
9819
|
const listRes = tryHandleMagickListOption(argv);
|
|
9317
9820
|
if (listRes) return listRes;
|
|
9318
9821
|
let cooperativeWork = 63;
|
|
@@ -9331,7 +9834,7 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9331
9834
|
stderr: ""
|
|
9332
9835
|
};
|
|
9333
9836
|
}
|
|
9334
|
-
|
|
9837
|
+
let outSpec = argv[argv.length - 1];
|
|
9335
9838
|
const pipelineTokens = argv.slice(0, -1);
|
|
9336
9839
|
const state = createDefaultState();
|
|
9337
9840
|
try {
|
|
@@ -9344,9 +9847,10 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9344
9847
|
`
|
|
9345
9848
|
};
|
|
9346
9849
|
}
|
|
9850
|
+
outSpec = expandFilenameProperties(outSpec, state);
|
|
9347
9851
|
const finalImg = stack[stack.length - 1];
|
|
9348
9852
|
const outLower = outSpec.toLowerCase();
|
|
9349
|
-
if (outLower === "null:") return { exitCode: 0, stdout: "", stderr: "" };
|
|
9853
|
+
if (outLower === "null:" || outLower.startsWith("mpr:")) return { exitCode: 0, stdout: "", stderr: "" };
|
|
9350
9854
|
if (outLower === "info:" || outLower === "info:-") {
|
|
9351
9855
|
const formatted = [];
|
|
9352
9856
|
for (const [idx, im] of stack.entries()) {
|
|
@@ -9379,50 +9883,21 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9379
9883
|
return { exitCode: 0, stdout: hist, stderr: "" };
|
|
9380
9884
|
}
|
|
9381
9885
|
const { format, path: outPath } = inferOutputFormat(outSpec, "png");
|
|
9382
|
-
if (stack.length > 1 && (
|
|
9886
|
+
if (hasSceneOutputPattern(outPath) || stack.length > 1 && (!state.adjoin || outPath !== "-" && ["png", "jpeg", "bmp"].includes(format))) {
|
|
9383
9887
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
9384
9888
|
if (++cooperativeWork % 64 === 0)
|
|
9385
9889
|
yield;
|
|
9386
|
-
const framePath = formatSceneOutputPath(outPath, idx);
|
|
9387
|
-
const { data: frameBytes } = encodeImage(yield*
|
|
9890
|
+
const framePath = formatSceneOutputPath(outPath, state.scene + idx);
|
|
9891
|
+
const { data: frameBytes } = encodeImage(yield* prepareMagickOutput(stack[idx], format), { format, netpbmAscii: state.netpbmAscii ?? false, ...state.inputDepth === void 0 ? {} : { netpbmDepth: Math.min(16, state.inputDepth) }, endian: state.inputEndian, omitPngResolution: state.strip || state.omitPngResolution === true, ...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor }, chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4", quality: state.quality });
|
|
9388
9892
|
files.set(framePath, frameBytes);
|
|
9389
9893
|
}
|
|
9390
9894
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
9391
9895
|
}
|
|
9392
|
-
let toEncode = yield*
|
|
9896
|
+
let toEncode = stack.length > 1 && format === "miff" ? yield* prepareMiffPages(stack) : stack.length > 1 && format === "tiff" ? yield* prepareTiffPages(stack) : yield* prepareMagickOutput(finalImg, format);
|
|
9393
9897
|
let encodePageHeight;
|
|
9394
9898
|
if (stack.length > 1 && format === "gif") {
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
fw = Math.max(fw, frame.width);
|
|
9398
|
-
fh = Math.max(fh, frame.height);
|
|
9399
|
-
}
|
|
9400
|
-
const combined = new Uint8Array(fw * fh * stack.length * 4);
|
|
9401
|
-
const delays = [];
|
|
9402
|
-
const disposals = [];
|
|
9403
|
-
for (let idx = 0; idx < stack.length; idx++) {
|
|
9404
|
-
if (++cooperativeWork % 64 === 0)
|
|
9405
|
-
yield;
|
|
9406
|
-
const outputFrame = yield* prepareHueOutput(stack[idx], format);
|
|
9407
|
-
disposals.push(typeof outputFrame.disposal === "number" ? outputFrame.disposal : 1);
|
|
9408
|
-
delays.push(outputFrame.delay?.[stack[idx][magickInput]?.sceneIdx ?? 0] ?? 100);
|
|
9409
|
-
for (let y = 0; y < outputFrame.height; y++) {
|
|
9410
|
-
if (++cooperativeWork % 64 === 0) yield;
|
|
9411
|
-
combined.set(outputFrame.data.subarray(y * outputFrame.width * 4, (y + 1) * outputFrame.width * 4), (idx * fw * fh + y * fw) * 4);
|
|
9412
|
-
}
|
|
9413
|
-
}
|
|
9414
|
-
toEncode = {
|
|
9415
|
-
...yield* prepareHueOutput(stack[0], format),
|
|
9416
|
-
width: fw,
|
|
9417
|
-
height: fh * stack.length,
|
|
9418
|
-
pages: stack.length,
|
|
9419
|
-
pageHeight: fh,
|
|
9420
|
-
delay: delays,
|
|
9421
|
-
disposal: disposals,
|
|
9422
|
-
gifFrames: stack.map((frame) => ({ width: frame.width, height: frame.height, x: frame.virtualCanvas?.x ?? 0, y: frame.virtualCanvas?.y ?? 0 })),
|
|
9423
|
-
data: combined
|
|
9424
|
-
};
|
|
9425
|
-
encodePageHeight = fh;
|
|
9899
|
+
toEncode = yield* prepareGifFrames(stack);
|
|
9900
|
+
encodePageHeight = toEncode.pageHeight;
|
|
9426
9901
|
}
|
|
9427
9902
|
if (typeof globalThis.gc === "function") {
|
|
9428
9903
|
try {
|
|
@@ -9434,6 +9909,10 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9434
9909
|
}
|
|
9435
9910
|
const { data: encoded } = encodeImage(toEncode, {
|
|
9436
9911
|
format,
|
|
9912
|
+
netpbmAscii: state.netpbmAscii ?? false,
|
|
9913
|
+
...state.inputDepth === void 0 ? {} : { netpbmDepth: Math.min(16, state.inputDepth) },
|
|
9914
|
+
endian: state.inputEndian,
|
|
9915
|
+
omitPngResolution: state.strip || state.omitPngResolution === true,
|
|
9437
9916
|
...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor },
|
|
9438
9917
|
chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4",
|
|
9439
9918
|
quality: state.quality,
|
|
@@ -9470,7 +9949,7 @@ async function transformStoredMagickRaster(image, backend, steps, signal, dimens
|
|
|
9470
9949
|
signal.throwIfAborted();
|
|
9471
9950
|
const request = next.value;
|
|
9472
9951
|
if (!request) {
|
|
9473
|
-
await
|
|
9952
|
+
await yieldTurn12(signal);
|
|
9474
9953
|
await checkpoint?.();
|
|
9475
9954
|
next = steps.next();
|
|
9476
9955
|
} else if (request.kind === "write") {
|
|
@@ -9502,7 +9981,7 @@ async function morphStoredMagickImage(image, backend, plan, signal) {
|
|
|
9502
9981
|
const position = backend.storage.allocate(size);
|
|
9503
9982
|
const a = images[step.a], b = images[step.b];
|
|
9504
9983
|
for (let offset = 0; offset < size; offset += 16384) {
|
|
9505
|
-
await
|
|
9984
|
+
await yieldTurn12(signal);
|
|
9506
9985
|
const length = Math.min(16384, size - offset);
|
|
9507
9986
|
const left = new Uint8Array(await backend.storage.read(a.position + offset, length));
|
|
9508
9987
|
const bytes = await drainSteps(subtractMagickPixelSteps(left, await backend.storage.read(b.position + offset, length), image.hasAlpha), signal);
|
|
@@ -9525,14 +10004,17 @@ async function transformStoredMagickCoordinates(image, backend, token, geometry,
|
|
|
9525
10004
|
xs = [{ source: w - dx, target: 0, length: dx }, { source: 0, target: dx, length: w - dx }];
|
|
9526
10005
|
ys = [{ source: h - dy, target: 0, length: dy }, { source: 0, target: dy, length: h - dy }];
|
|
9527
10006
|
} else if (token === "-splice") {
|
|
9528
|
-
const sw = Math.max(0, Math.round(g.width ?? 0)
|
|
10007
|
+
const sw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? w / 100 : 1)));
|
|
10008
|
+
const sh = Math.max(0, Math.round((g.height ?? 0) * (g.isPercent ? h / 100 : 1)));
|
|
9529
10009
|
const box = gravityAdjustBox(w, h, sw, sh, g.x, g.y, state.gravity);
|
|
9530
10010
|
const anchor = resolveGravityOffset(sw, sh, state.gravity);
|
|
9531
|
-
const x = Math.max(0, Math.min(w, box.x + anchor.left));
|
|
9532
|
-
const y = Math.max(0, Math.min(h, box.y + anchor.top));
|
|
9533
10011
|
width += sw;
|
|
9534
10012
|
height += sh;
|
|
9535
|
-
|
|
10013
|
+
const xOffset = box.x + anchor.left;
|
|
10014
|
+
const x = xOffset < 0 || xOffset > w ? width : xOffset;
|
|
10015
|
+
if (box.y + anchor.top > height) throw new Error("pixels are not authentic");
|
|
10016
|
+
const y = Math.max(0, Math.min(h, box.y + anchor.top));
|
|
10017
|
+
xs = [{ source: 0, target: 0, length: x }, { source: x, target: x + sw, length: Math.max(0, w - x) }];
|
|
9536
10018
|
ys = [{ source: 0, target: 0, length: y }, { source: y, target: y + sh, length: h - y }];
|
|
9537
10019
|
} else {
|
|
9538
10020
|
const cw = Math.max(0, Math.round((g.width ?? 0) * (g.isPercent ? w / 100 : 1)));
|
|
@@ -9551,9 +10033,18 @@ async function transformStoredMagickCoordinates(image, backend, token, geometry,
|
|
|
9551
10033
|
let work = 0;
|
|
9552
10034
|
for (const y of ys) for (let row = 0; row < y.length; row++) for (const x of xs) {
|
|
9553
10035
|
for (let offset = 0; offset < x.length; offset += 4096) {
|
|
9554
|
-
if (work++ % 64 === 0) await
|
|
10036
|
+
if (work++ % 64 === 0) await yieldTurn12(signal);
|
|
9555
10037
|
const length = Math.min(4096, x.length - offset) * 4;
|
|
9556
|
-
const
|
|
10038
|
+
const sourceX = Math.min(w - 1, x.source + offset);
|
|
10039
|
+
const sourceLength = Math.min(length, (w - sourceX) * 4);
|
|
10040
|
+
let bytes = await backend.storage.read(image.position + ((y.source + row) * w + sourceX) * 4, sourceLength);
|
|
10041
|
+
if (sourceLength < length) {
|
|
10042
|
+
const extended = new Uint8Array(length);
|
|
10043
|
+
extended.set(bytes);
|
|
10044
|
+
const edge = bytes.subarray(sourceLength - 4);
|
|
10045
|
+
for (let i = sourceLength; i < length; i += 4) extended.set(edge, i);
|
|
10046
|
+
bytes = extended;
|
|
10047
|
+
}
|
|
9557
10048
|
await backend.storage.write(position + ((y.target + row) * width + x.target + offset) * 4, bytes);
|
|
9558
10049
|
}
|
|
9559
10050
|
}
|
|
@@ -9572,7 +10063,7 @@ async function compositeStoredMagick(base, overlay, backend, signal, left, top,
|
|
|
9572
10063
|
let hasAlpha = base.hasAlpha || !generic && !compositeMode.delegated && !compositeMode.preservesAlpha;
|
|
9573
10064
|
const position = inPlace ? base.position : backend.storage.allocate(base.width * base.height * 4);
|
|
9574
10065
|
for (let start = 0; !inPlace && start < base.width * base.height * 4; start += 16384) {
|
|
9575
|
-
await
|
|
10066
|
+
await yieldTurn12(signal);
|
|
9576
10067
|
await backend.storage.write(position + start, await backend.storage.read(base.position + start, Math.min(16384, base.width * base.height * 4 - start)));
|
|
9577
10068
|
}
|
|
9578
10069
|
const maskDestination = !generic && ["dstin", "destin", "srcin", "in", "srcout", "out", "dstatop", "destatop"].includes(compositeMode.name);
|
|
@@ -9581,7 +10072,7 @@ async function compositeStoredMagick(base, overlay, backend, signal, left, top,
|
|
|
9581
10072
|
const bottom = tile || extendSource ? base.height : Math.min(base.height, top + overlay.height);
|
|
9582
10073
|
for (let y = extendSource ? 0 : Math.max(0, top); y < bottom; y++) {
|
|
9583
10074
|
for (let x = extendSource ? 0 : Math.max(0, left); x < right; ) {
|
|
9584
|
-
await
|
|
10075
|
+
await yieldTurn12(signal);
|
|
9585
10076
|
const sourceX = tile ? x % overlay.width : Math.max(0, Math.min(overlay.width - 1, x - left));
|
|
9586
10077
|
const sourceY = tile ? y % overlay.height : Math.max(0, Math.min(overlay.height - 1, y - top));
|
|
9587
10078
|
const repeatEdge = extendSource && !tile && (x < left || x >= left + overlay.width);
|
|
@@ -9620,24 +10111,37 @@ async function compositeStoredMagick(base, overlay, backend, signal, left, top,
|
|
|
9620
10111
|
}
|
|
9621
10112
|
return { ...base, position, hasAlpha, channels: hasAlpha ? base.channels : base.channels <= 2 ? 1 : 3 };
|
|
9622
10113
|
}
|
|
10114
|
+
function applyMagickProfile(image, name, profile) {
|
|
10115
|
+
if (profile) {
|
|
10116
|
+
if (profile.length < 128 || String.fromCharCode(...profile.subarray(36, 40)) !== "acsp") throw new Error(`invalid ICC profile '${name}'`);
|
|
10117
|
+
if (image.icc && (image.icc.length !== profile.length || image.icc.some((byte2, index) => byte2 !== profile[index]))) throw new Error("ICC color conversion is unsupported");
|
|
10118
|
+
return { ...image, icc: profile };
|
|
10119
|
+
}
|
|
10120
|
+
if (["icc", "icm", "*"].includes(name.toLowerCase())) {
|
|
10121
|
+
const { icc: ignored, ...rest } = image;
|
|
10122
|
+
return rest;
|
|
10123
|
+
}
|
|
10124
|
+
return image;
|
|
10125
|
+
}
|
|
9623
10126
|
async function tryConvertFiles(argv, input, stdinBytes, signal) {
|
|
9624
|
-
const analysis = { text: "", warnings: "" };
|
|
10127
|
+
const analysis = { text: "", warnings: "", bytes: [] };
|
|
9625
10128
|
const result = await tryConvertFilesResult(argv, input, stdinBytes, signal, analysis);
|
|
9626
|
-
return result ?
|
|
10129
|
+
return result ? combineConvertOutput(result, analysis) : void 0;
|
|
9627
10130
|
}
|
|
9628
10131
|
async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis) {
|
|
9629
10132
|
if (!input.filesystem.capabilities || !input.filesystem.open || !input.filesystem.removeFileConditional) return;
|
|
9630
|
-
|
|
10133
|
+
let outSpec = argv.at(-1) ?? "";
|
|
9631
10134
|
const optionArgs = argv.slice(0, argv.indexOf("--") < 0 ? argv.length : argv.indexOf("--"));
|
|
9632
10135
|
if (!outSpec || tryHandleMagickListOption(argv) || optionArgs.some((token) => ["--help", "-help", "-h", "--version", "-version"].includes(token))) {
|
|
9633
10136
|
await probeImageArguments(argv, input, stdinBytes, signal);
|
|
9634
10137
|
return drainSteps(runConvertCliSteps(argv, /* @__PURE__ */ new Map(), stdinBytes, signal), signal);
|
|
9635
10138
|
}
|
|
9636
10139
|
let output;
|
|
9637
|
-
await
|
|
10140
|
+
await yieldTurn12(signal);
|
|
9638
10141
|
let state = createDefaultState();
|
|
9639
10142
|
const tokens = argv.slice(0, -1), scopes = [];
|
|
9640
10143
|
const steps = [];
|
|
10144
|
+
const registers = /* @__PURE__ */ new Map();
|
|
9641
10145
|
const stackStep = (runStack) => {
|
|
9642
10146
|
steps.push({ runStack });
|
|
9643
10147
|
};
|
|
@@ -9645,7 +10149,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9645
10149
|
try {
|
|
9646
10150
|
output = inferOutputFormat(outSpec, "png");
|
|
9647
10151
|
for (let i = 0; i < tokens.length; i++) {
|
|
9648
|
-
if (i && i % 64 === 0) await
|
|
10152
|
+
if (i && i % 64 === 0) await yieldTurn12(signal);
|
|
9649
10153
|
const token = tokens[i];
|
|
9650
10154
|
if (token === "") continue;
|
|
9651
10155
|
if (!operandsOnly && token === "-sampling-factor") {
|
|
@@ -9701,20 +10205,20 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9701
10205
|
const length = source.length;
|
|
9702
10206
|
if (token.endsWith("clone") && length === 0) throw new Error(`UnableToCloneImage ${token}`);
|
|
9703
10207
|
for (let repeat = 0; repeat < count; repeat++) for (const index of parseMagickIndexSpec(spec, length, "clone")) {
|
|
9704
|
-
await
|
|
10208
|
+
await yieldTurn12(signal);
|
|
9705
10209
|
await stack.push(await source.get(index));
|
|
9706
10210
|
}
|
|
9707
10211
|
} else if (token.endsWith("delete")) await stack.remove(parseMagickIndexSpec(spec, stack.length, "delete"));
|
|
9708
10212
|
else if (token === "-reverse") {
|
|
9709
10213
|
for (let n = 0; n < Math.floor(stack.length / 2); n++) {
|
|
9710
|
-
await
|
|
10214
|
+
await yieldTurn12(signal);
|
|
9711
10215
|
await stack.swap(n, stack.length - 1 - n);
|
|
9712
10216
|
}
|
|
9713
10217
|
} else if (token.endsWith("insert")) {
|
|
9714
10218
|
const raw = token === "+insert" ? 0 : Number(spec), target = raw < 0 ? stack.length - 1 + raw : raw;
|
|
9715
10219
|
if (!Number.isInteger(target) || target < 0 || target >= stack.length || raw < 0 && target === 0) throw new Error(`invalid image index ${token}`);
|
|
9716
10220
|
for (let n = stack.length - 1; n > target; n--) {
|
|
9717
|
-
await
|
|
10221
|
+
await yieldTurn12(signal);
|
|
9718
10222
|
await stack.swap(n, n - 1);
|
|
9719
10223
|
}
|
|
9720
10224
|
} else {
|
|
@@ -9766,7 +10270,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9766
10270
|
const a = await stack.get(index), b = await stack.get(index + 1);
|
|
9767
10271
|
await result.push(a);
|
|
9768
10272
|
for (let step = 1; step <= count; step++) {
|
|
9769
|
-
await
|
|
10273
|
+
await yieldTurn12(signal);
|
|
9770
10274
|
const fraction = step / (count + 1), width = Math.max(1, Math.round(a.width * (1 - fraction) + b.width * fraction)), height = Math.max(1, Math.round(a.height * (1 - fraction) + b.height * fraction));
|
|
9771
10275
|
await result.push(await transformStoredMagickRaster(a, backend, morphPixelSteps(a, b, width, height, fraction), signal, { ...a, width, height }, [a, b]));
|
|
9772
10276
|
}
|
|
@@ -9794,6 +10298,22 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9794
10298
|
});
|
|
9795
10299
|
continue;
|
|
9796
10300
|
}
|
|
10301
|
+
if (!operandsOnly && token === "-orient") {
|
|
10302
|
+
const orientation = state.orientation = parseMagickOrientation(tokens[++i] ?? "");
|
|
10303
|
+
steps.push(async (image) => image ? { ...image, orientation } : void 0);
|
|
10304
|
+
continue;
|
|
10305
|
+
}
|
|
10306
|
+
if (!operandsOnly && token === "-units") {
|
|
10307
|
+
const units = state.units = parseMagickUnits(tokens[++i] ?? "");
|
|
10308
|
+
steps.push(async (image) => image ? applyMagickUnits(image, units) : void 0);
|
|
10309
|
+
continue;
|
|
10310
|
+
}
|
|
10311
|
+
if (!operandsOnly && token === "-density") {
|
|
10312
|
+
const value = tokens[++i] ?? "72";
|
|
10313
|
+
state.density = Math.max(1, Math.round(parseMagickGeometry(value).width ?? 72));
|
|
10314
|
+
steps.push(async (image) => image ? applyMagickDensity(image, value) : void 0);
|
|
10315
|
+
continue;
|
|
10316
|
+
}
|
|
9797
10317
|
if (!operandsOnly && token === "-set" && tokens[i + 1]?.toLowerCase() === "delay") {
|
|
9798
10318
|
const delay = Number(tokens[i + 2] ?? 0) * 10;
|
|
9799
10319
|
steps.push(async (image) => image ? {
|
|
@@ -9811,6 +10331,25 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9811
10331
|
i += 2;
|
|
9812
10332
|
continue;
|
|
9813
10333
|
}
|
|
10334
|
+
if (!operandsOnly && token === "-set" && !tokens[i + 1]?.toLowerCase().startsWith("option:") && !tokens[i + 1]?.toLowerCase().startsWith("filename:") && !tokens[i + 1]?.toLowerCase().startsWith("connected-components:")) {
|
|
10335
|
+
const key = tokens[++i] ?? "", value = tokens[++i] ?? "";
|
|
10336
|
+
steps.push(async (image, backend) => {
|
|
10337
|
+
if (!image) return;
|
|
10338
|
+
const expanded = await formatRetainedIdentify(value, image, image[magickInput] ?? {}, async () => ({ image, storage: backend.storage }), signal);
|
|
10339
|
+
return key.toLowerCase() === "density" ? applyMagickDensity(image, expanded) : { ...image, properties: { ...image.properties, [key]: expanded } };
|
|
10340
|
+
});
|
|
10341
|
+
continue;
|
|
10342
|
+
}
|
|
10343
|
+
if (!operandsOnly && token === "+set") {
|
|
10344
|
+
const key = tokens[++i] ?? "";
|
|
10345
|
+
steps.push(async (image) => {
|
|
10346
|
+
if (!image) return;
|
|
10347
|
+
const properties = { ...image.properties };
|
|
10348
|
+
delete properties[key];
|
|
10349
|
+
return { ...image, properties };
|
|
10350
|
+
});
|
|
10351
|
+
continue;
|
|
10352
|
+
}
|
|
9814
10353
|
const setting = operandsOnly ? void 0 : applyMagickReadSetting(tokens, state, i);
|
|
9815
10354
|
if (setting !== void 0) {
|
|
9816
10355
|
i = setting;
|
|
@@ -9868,7 +10407,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9868
10407
|
if (!image) return;
|
|
9869
10408
|
const histogram = Array.from({ length: analysisOperation.luminance ? 5 : 4 }, (_, channel) => new Float64Array(channel === 4 || analysisOperation.highDepth && image.storedData16 ? 65536 : 256)), size = image.width * image.height * 4;
|
|
9870
10409
|
for (let offset = 0; offset < size; offset += 16384) {
|
|
9871
|
-
if (offset % 1048576 === 0) await
|
|
10410
|
+
if (offset % 1048576 === 0) await yieldTurn12(signal);
|
|
9872
10411
|
const original = analysisOperation.highDepth ? image.storedData16 : void 0;
|
|
9873
10412
|
const bytes = await backend.storage.read((original?.position ?? image.position) + offset * (original ? 2 : 1), Math.min(16384, size - offset) * (original ? 2 : 1));
|
|
9874
10413
|
await drainSteps(accumulateMagickHistogram(original ? new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2) : bytes, histogram), signal);
|
|
@@ -9886,7 +10425,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9886
10425
|
const layout = smushLayoutSteps(images, token === "-smush", gap, settings.gravity);
|
|
9887
10426
|
let next = layout.next();
|
|
9888
10427
|
while (!next.done) {
|
|
9889
|
-
await
|
|
10428
|
+
await yieldTurn12(signal);
|
|
9890
10429
|
const request = next.value;
|
|
9891
10430
|
next = layout.next(await backend.storage.read(images[request.index].position + request.position, request.length));
|
|
9892
10431
|
}
|
|
@@ -9932,7 +10471,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9932
10471
|
if (append && stack.length === 1) return stack;
|
|
9933
10472
|
let width = 0, height = 0;
|
|
9934
10473
|
for (let n = 0; n < (flatten ? 1 : stack.length); n++) {
|
|
9935
|
-
await
|
|
10474
|
+
await yieldTurn12(signal);
|
|
9936
10475
|
const frame = await stack.get(n);
|
|
9937
10476
|
width = append && !vertical ? width + frame.width : Math.max(width, frame.width);
|
|
9938
10477
|
height = append && vertical ? height + frame.height : Math.max(height, frame.height);
|
|
@@ -9946,7 +10485,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9946
10485
|
const left = vertical ? offset.left : cursor, top = vertical ? cursor : offset.top;
|
|
9947
10486
|
for (let y = 0; y < frame.height; y++) {
|
|
9948
10487
|
for (let x = 0; x < frame.width; x += 4096) {
|
|
9949
|
-
await
|
|
10488
|
+
await yieldTurn12(signal);
|
|
9950
10489
|
const pixels = await backend.storage.read(frame.position + (y * frame.width + x) * 4, Math.min(4096, frame.width - x) * 4);
|
|
9951
10490
|
await backend.storage.write(result.position + ((top + y) * width + left + x) * 4, pixels);
|
|
9952
10491
|
}
|
|
@@ -9994,7 +10533,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9994
10533
|
let next = bounds.next();
|
|
9995
10534
|
while (!next.done) {
|
|
9996
10535
|
if (!next.value) {
|
|
9997
|
-
await
|
|
10536
|
+
await yieldTurn12(signal);
|
|
9998
10537
|
next = bounds.next();
|
|
9999
10538
|
} else {
|
|
10000
10539
|
const { image, position, length } = next.value;
|
|
@@ -10029,6 +10568,11 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10029
10568
|
});
|
|
10030
10569
|
continue;
|
|
10031
10570
|
}
|
|
10571
|
+
if (!operandsOnly && token === "-scene") {
|
|
10572
|
+
state.scene = Number(tokens[++i]);
|
|
10573
|
+
if (!Number.isSafeInteger(state.scene) || state.scene < 0) throw new Error("invalid scene number");
|
|
10574
|
+
continue;
|
|
10575
|
+
}
|
|
10032
10576
|
if (!operandsOnly && (token === "+adjoin" || token === "-adjoin")) {
|
|
10033
10577
|
state.adjoin = token === "-adjoin";
|
|
10034
10578
|
continue;
|
|
@@ -10041,8 +10585,31 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10041
10585
|
state.gravity = "northwest";
|
|
10042
10586
|
continue;
|
|
10043
10587
|
}
|
|
10588
|
+
if (!operandsOnly && (token === "-profile" || token === "+profile")) {
|
|
10589
|
+
const name = tokens[++i];
|
|
10590
|
+
if (!name) throw new Error(`missing argument '${token}'`);
|
|
10591
|
+
stackStep(async (stack, backend) => {
|
|
10592
|
+
const profile = token === "-profile" ? await backend.read(name, async (source) => {
|
|
10593
|
+
const bytes = new Uint8Array(source.size);
|
|
10594
|
+
for (let offset = 0; offset < source.size; offset += 16384) {
|
|
10595
|
+
await yieldTurn12(signal);
|
|
10596
|
+
bytes.set(await source.read(offset, Math.min(16384, source.size - offset), { signal }), offset);
|
|
10597
|
+
}
|
|
10598
|
+
return bytes;
|
|
10599
|
+
}) : void 0;
|
|
10600
|
+
if (token === "-profile" && !profile) throw new Error(`unable to open profile '${name}'`);
|
|
10601
|
+
for (let index = 0; index < stack.length; index++) await stack.set(index, applyMagickProfile(await stack.get(index), name, profile));
|
|
10602
|
+
return stack;
|
|
10603
|
+
});
|
|
10604
|
+
continue;
|
|
10605
|
+
}
|
|
10044
10606
|
if (!operandsOnly && token === "-strip") {
|
|
10045
10607
|
state.strip = true;
|
|
10608
|
+
steps.push(async (image) => {
|
|
10609
|
+
if (!image) return image;
|
|
10610
|
+
const { icc: ignored, properties: ignoredProperties, ...rest } = image;
|
|
10611
|
+
return rest;
|
|
10612
|
+
});
|
|
10046
10613
|
continue;
|
|
10047
10614
|
}
|
|
10048
10615
|
if (!operandsOnly && token === "+repage") {
|
|
@@ -10059,17 +10626,35 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10059
10626
|
continue;
|
|
10060
10627
|
}
|
|
10061
10628
|
if (!operandsOnly && (token === "-write" || token === "+write")) {
|
|
10062
|
-
|
|
10629
|
+
if (i + 1 >= tokens.length) {
|
|
10630
|
+
stackStep(async () => {
|
|
10631
|
+
throw new Error(`missing argument '${token}'`);
|
|
10632
|
+
});
|
|
10633
|
+
break;
|
|
10634
|
+
}
|
|
10635
|
+
const path = expandFilenameProperties(tokens[++i] ?? "", state), endian = state.inputEndian, quality = state.quality, omitPngResolution = state.strip || state.omitPngResolution === true, samplingFactor = state.samplingFactor, netpbmAscii = state.netpbmAscii ?? false, netpbmDepth = state.inputDepth === void 0 ? void 0 : Math.min(16, state.inputDepth), adjoin = state.adjoin, scene = state.scene, loop = state.loop, optimizeLayers = state.optimizeLayers;
|
|
10063
10636
|
stackStep(async (stack, backend) => {
|
|
10637
|
+
if (stack.length === 0) throw new Error(`no images for write '${token}'`);
|
|
10064
10638
|
const image = await stack.get(stack.length - 1);
|
|
10065
|
-
if (
|
|
10639
|
+
if (path.slice(0, 4).toLowerCase() === "mpr:") {
|
|
10640
|
+
const saved = new StoredImageStack(backend.storage, signal, stack);
|
|
10641
|
+
for (let index = 0; index < stack.length; index++) {
|
|
10642
|
+
await yieldTurn12(signal);
|
|
10643
|
+
await saved.push(await stack.get(index));
|
|
10644
|
+
}
|
|
10645
|
+
registers.set(path.slice(4), saved);
|
|
10646
|
+
} else if (image && path && path.toLowerCase() !== "null:") {
|
|
10066
10647
|
const output2 = inferOutputFormat(path, image.format);
|
|
10067
|
-
if (stack.length > 1 && (
|
|
10648
|
+
if (hasSceneOutputPattern(output2.path) || stack.length > 1 && (!adjoin || output2.path !== "-" && ["png", "jpeg", "bmp"].includes(output2.format))) {
|
|
10068
10649
|
for (let index = 0; index < stack.length; index++) {
|
|
10069
|
-
await
|
|
10070
|
-
await backend.stage(await
|
|
10650
|
+
await yieldTurn12(signal);
|
|
10651
|
+
await backend.stage(await prepareStoredMagickOutput(await stack.get(index), output2.format, backend, signal), formatSceneOutputPath(output2.path, scene + index), { format: output2.format, endian, omitPngResolution, netpbmAscii, ...netpbmDepth === void 0 ? {} : { netpbmDepth }, ...samplingFactor === void 0 ? {} : { samplingFactor }, chromaSubsampling: quality < 90 ? "4:2:0" : "4:4:4", quality });
|
|
10071
10652
|
}
|
|
10072
|
-
} else
|
|
10653
|
+
} else {
|
|
10654
|
+
const frames = stack.length > 1 && output2.format === "miff" ? prepareStoredMiffPages(stack, image, backend, signal) : stack.length > 1 && output2.format === "tiff" ? prepareStoredTiffPages(stack, image, backend, signal) : stack.length > 1 && output2.format === "gif" ? await prepareStoredGifFrames(stack, backend, signal) : await prepareStoredMagickOutput(image, output2.format, backend, signal);
|
|
10655
|
+
const bytes = await backend.stage(frames, output2.path, { format: output2.format, ...stack.length > 1 && output2.format === "gif" ? { pageHeight: frames.pageHeight } : {}, endian, omitPngResolution, netpbmAscii, ...netpbmDepth === void 0 ? {} : { netpbmDepth }, ...samplingFactor === void 0 ? {} : { samplingFactor }, chromaSubsampling: quality < 90 ? "4:2:0" : "4:4:4", quality, ...loop === void 0 ? {} : { loop }, ...optimizeLayers ? { optimizeFrames: true } : {} });
|
|
10656
|
+
if (bytes) analysis.bytes.push(bytes);
|
|
10657
|
+
}
|
|
10073
10658
|
}
|
|
10074
10659
|
return stack;
|
|
10075
10660
|
});
|
|
@@ -10112,7 +10697,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10112
10697
|
if (!image) return;
|
|
10113
10698
|
for (const step of magickDrawSteps(image, drawing, settings)) {
|
|
10114
10699
|
if (!step) {
|
|
10115
|
-
await
|
|
10700
|
+
await yieldTurn12(signal);
|
|
10116
10701
|
continue;
|
|
10117
10702
|
}
|
|
10118
10703
|
if ((image.space === "b-w" || image.space === "grey16") && !(step.kind === "floodfill" && step.alphaOnly))
|
|
@@ -10228,6 +10813,14 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10228
10813
|
} else if (!operandsOnly && ["-roll", "-splice", "-chop"].includes(token)) {
|
|
10229
10814
|
const geometry = tokens[++i] ?? (token === "-roll" ? "+0+0" : "0x0"), captured = { ...state };
|
|
10230
10815
|
steps.push(async (image, backend) => image ? transformStoredMagickCoordinates(image, backend, token, geometry, captured, signal) : void 0);
|
|
10816
|
+
} else if (!operandsOnly && token === "-resample") {
|
|
10817
|
+
const value = tokens[++i] ?? "72", kernel = state.kernel;
|
|
10818
|
+
steps.push(async (image, backend) => {
|
|
10819
|
+
if (!image) return;
|
|
10820
|
+
const options = magickResizeOptions(image, magickResampleGeometry(image, value), kernel);
|
|
10821
|
+
const resized = options ? await resizeStoredMagickImage(image, backend, options, signal) : image;
|
|
10822
|
+
return applyMagickDensity(resized, value);
|
|
10823
|
+
});
|
|
10231
10824
|
} else if (!operandsOnly && ["-resize", "-scale", "-sample", "-thumbnail"].includes(token)) {
|
|
10232
10825
|
const geometry = tokens[++i] ?? "100%", kernel = token === "-sample" ? "nearest" : state.kernel, thumbnail = token === "-thumbnail";
|
|
10233
10826
|
steps.push(async (image, backend) => {
|
|
@@ -10271,7 +10864,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10271
10864
|
for (let n = 0; n < stack.length; n++) {
|
|
10272
10865
|
const image = await stack.get(n);
|
|
10273
10866
|
for (const area of magickCropAreas(image, geometry, gravity)) {
|
|
10274
|
-
await
|
|
10867
|
+
await yieldTurn12(signal);
|
|
10275
10868
|
if (area === null) {
|
|
10276
10869
|
analysis.warnings += `magick: geometry does not contain image '${geometry}'
|
|
10277
10870
|
`;
|
|
@@ -10290,13 +10883,18 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10290
10883
|
return frames;
|
|
10291
10884
|
});
|
|
10292
10885
|
} else if (!operandsOnly && token === "-shave") {
|
|
10293
|
-
const geometry =
|
|
10886
|
+
const geometry = tokens[++i] ?? "0x0", parsed = parseMagickGeometry(geometry);
|
|
10887
|
+
const width = Math.max(0, Math.round(parsed.width ?? 0)), height = Math.max(0, Math.round(parsed.height ?? width));
|
|
10294
10888
|
steps.push(async (image, backend) => {
|
|
10295
10889
|
if (!image) return;
|
|
10296
|
-
|
|
10890
|
+
if (width * 2 >= image.width || height * 2 >= image.height) {
|
|
10891
|
+
analysis.warnings += `magick: geometry does not contain image '${geometry}'
|
|
10892
|
+
`;
|
|
10893
|
+
return image;
|
|
10894
|
+
}
|
|
10297
10895
|
return {
|
|
10298
|
-
...await transformStoredImage2(image, backend.storage, { kind: "extract", left, top, width:
|
|
10299
|
-
virtualCanvas: magickBorderCanvas(image, -
|
|
10896
|
+
...await transformStoredImage2(image, backend.storage, { kind: "extract", left: width, top: height, width: image.width - width * 2, height: image.height - height * 2 }, signal),
|
|
10897
|
+
virtualCanvas: magickBorderCanvas(image, -width, -height)
|
|
10300
10898
|
};
|
|
10301
10899
|
});
|
|
10302
10900
|
} else if (!operandsOnly && token === "-trim") {
|
|
@@ -10310,6 +10908,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10310
10908
|
steps.push(async (image, backend) => {
|
|
10311
10909
|
if (!image) return;
|
|
10312
10910
|
const layout = magickExtentLayout(image, geometry, captured);
|
|
10911
|
+
if (!layout) return image;
|
|
10313
10912
|
const virtualCanvas = magickResizeCanvas(image, layout.width, layout.height);
|
|
10314
10913
|
const source = image[magickInput];
|
|
10315
10914
|
const canvas = {
|
|
@@ -10350,19 +10949,34 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10350
10949
|
};
|
|
10351
10950
|
});
|
|
10352
10951
|
} else {
|
|
10353
|
-
if (!operandsOnly && (token.startsWith("-") && token !== "-" || token.startsWith("+")))
|
|
10952
|
+
if (!operandsOnly && (token.startsWith("-") && token !== "-" || token.startsWith("+"))) {
|
|
10953
|
+
stackStep(async () => {
|
|
10954
|
+
throw new Error(`unrecognized option '${token}'`);
|
|
10955
|
+
});
|
|
10956
|
+
break;
|
|
10957
|
+
}
|
|
10354
10958
|
if (!operandsOnly && (token === "(" || token === ")")) continue;
|
|
10355
10959
|
const captured = { ...state }, literal = operandsOnly, maxDecodeDimension = inferMaxDecodeDimensionFromUpcomingTokens(tokens, i + 1);
|
|
10356
10960
|
stackStep(async (stack, backend) => {
|
|
10961
|
+
if (token.slice(0, 4).toLowerCase() === "mpr:") {
|
|
10962
|
+
const saved = registers.get(token.slice(4));
|
|
10963
|
+
if (!saved) throw new Error(`unable to open image '${token}'`);
|
|
10964
|
+
for (let index = 0; index < saved.length; index++) {
|
|
10965
|
+
await yieldTurn12(signal);
|
|
10966
|
+
await stack.push(await saved.get(index));
|
|
10967
|
+
}
|
|
10968
|
+
return stack;
|
|
10969
|
+
}
|
|
10357
10970
|
const base = stack.length === 1 ? await stack.get(0) : void 0, lower = token.toLowerCase();
|
|
10358
10971
|
const merge = !literal && (lower.startsWith("label:") || lower.startsWith("caption:")) && base && captured.hasSize && base.width === captured.sizeWidth && base.height === captured.sizeHeight && Object.values(captured.background).every((value) => value === 255);
|
|
10359
10972
|
const settings = merge ? { ...captured, background: { r: 0, g: 0, b: 0, a: 0 } } : captured;
|
|
10360
|
-
await parseStoredCompareInput(token, settings, backend, signal, { visit: async (image) => {
|
|
10973
|
+
const loaded = await parseStoredCompareInput(token, settings, backend, signal, { visit: async (image) => {
|
|
10361
10974
|
if (merge) {
|
|
10362
10975
|
const composed = await compositeStoredMagick(base, image, backend, signal, 0, 0, "over");
|
|
10363
10976
|
await stack.set(0, { ...composed, hasAlpha: base.hasAlpha, channels: base.channels });
|
|
10364
10977
|
} else await stack.push(image);
|
|
10365
10978
|
}, ...maxDecodeDimension === void 0 ? {} : { maxDecodeDimension } });
|
|
10979
|
+
if (!loaded) throw new Error(`unable to open image '${token}'`);
|
|
10366
10980
|
return stack;
|
|
10367
10981
|
});
|
|
10368
10982
|
}
|
|
@@ -10403,8 +11017,10 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10403
11017
|
return { exitCode: 1, stdout: "", stderr: `magick: no images defined '${outSpec}'
|
|
10404
11018
|
` };
|
|
10405
11019
|
}
|
|
10406
|
-
await
|
|
10407
|
-
|
|
11020
|
+
await yieldTurn12(signal);
|
|
11021
|
+
outSpec = expandFilenameProperties(outSpec, state);
|
|
11022
|
+
output = inferOutputFormat(outSpec, "png");
|
|
11023
|
+
if (outSpec.toLowerCase() === "null:" || outSpec.toLowerCase().startsWith("mpr:")) {
|
|
10408
11024
|
await backend.publishPending();
|
|
10409
11025
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
10410
11026
|
}
|
|
@@ -10413,7 +11029,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10413
11029
|
async function* information() {
|
|
10414
11030
|
let last = "";
|
|
10415
11031
|
for (let index = 0; index < stack.length; index++) {
|
|
10416
|
-
await
|
|
11032
|
+
await yieldTurn12(signal);
|
|
10417
11033
|
const frame = await stack.get(index);
|
|
10418
11034
|
if (index && !state.formatStr) yield "\n";
|
|
10419
11035
|
const text = state.formatStr ? await formatRetainedIdentify(state.formatStr, frame, { ...frame[magickInput], sceneIdx: index, sceneCount: stack.length, quality: state.quality }, async () => ({ image: frame, storage: backend.storage }), signal) : `${frame.width}x${frame.height} ${frame.magickColorspace ?? "sRGB"} 8-bit`;
|
|
@@ -10437,60 +11053,24 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10437
11053
|
await backend.publishPending();
|
|
10438
11054
|
return { exitCode: 0, stdout, stderr: "" };
|
|
10439
11055
|
}
|
|
10440
|
-
if (stack.length > 1 && (
|
|
11056
|
+
if (hasSceneOutputPattern(output.path) || stack.length > 1 && (!state.adjoin || output.path !== "-" && ["png", "jpeg", "bmp"].includes(output.format))) {
|
|
10441
11057
|
for (let index = 0; index < stack.length; index++) {
|
|
10442
|
-
await
|
|
10443
|
-
await backend.stage(await
|
|
11058
|
+
await yieldTurn12(signal);
|
|
11059
|
+
await backend.stage(await prepareStoredMagickOutput(await stack.get(index), output.format, backend, signal), formatSceneOutputPath(output.path, state.scene + index), { format: output.format, netpbmAscii: state.netpbmAscii ?? false, ...state.inputDepth === void 0 ? {} : { netpbmDepth: Math.min(16, state.inputDepth) }, endian: state.inputEndian, omitPngResolution: state.strip || state.omitPngResolution === true, ...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor }, chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4", quality: state.quality });
|
|
10444
11060
|
}
|
|
10445
11061
|
await backend.publishPending();
|
|
10446
11062
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
10447
11063
|
}
|
|
11064
|
+
if (stack.length > 1 && output.format === "miff") image = prepareStoredMiffPages(stack, image, backend, signal);
|
|
11065
|
+
if (stack.length > 1 && output.format === "tiff") image = prepareStoredTiffPages(stack, image, backend, signal);
|
|
10448
11066
|
let pageHeight;
|
|
10449
11067
|
if (stack.length > 1 && output.format === "gif") {
|
|
10450
|
-
|
|
10451
|
-
|
|
10452
|
-
for (let index = 1; index < stack.length; index++) {
|
|
10453
|
-
const frame = await stack.get(index);
|
|
10454
|
-
width = Math.max(width, frame.width);
|
|
10455
|
-
height = Math.max(height, frame.height);
|
|
10456
|
-
}
|
|
10457
|
-
const size = width * height * 4, position = backend.storage.allocate(size * stack.length);
|
|
10458
|
-
for (let index = 0; index < stack.length; index++) {
|
|
10459
|
-
const frame = await prepareStoredHueOutput(await stack.get(index), output.format, backend, signal);
|
|
10460
|
-
for (let y = 0; y < height; y++) for (let x = 0; x < width; x += 4096) {
|
|
10461
|
-
await yieldTurn11(signal);
|
|
10462
|
-
const count = Math.min(4096, width - x), bytes = new Uint8Array(count * 4);
|
|
10463
|
-
if (y < frame.height && x < frame.width) bytes.set(await backend.storage.read(frame.position + (y * frame.width + x) * 4, Math.min(count, frame.width - x) * 4));
|
|
10464
|
-
await backend.storage.write(position + index * size + (y * width + x) * 4, bytes);
|
|
10465
|
-
}
|
|
10466
|
-
}
|
|
10467
|
-
pageHeight = height;
|
|
10468
|
-
const { storedData16: ignored, ...metadata } = first;
|
|
10469
|
-
image = {
|
|
10470
|
-
...metadata,
|
|
10471
|
-
position,
|
|
10472
|
-
width,
|
|
10473
|
-
height: height * stack.length,
|
|
10474
|
-
pages: stack.length,
|
|
10475
|
-
pageHeight,
|
|
10476
|
-
storedGifFrame: { async at(index) {
|
|
10477
|
-
const frame = await stack.get(index);
|
|
10478
|
-
return { width: frame.width, height: frame.height, x: frame.virtualCanvas?.x ?? 0, y: frame.virtualCanvas?.y ?? 0 };
|
|
10479
|
-
} },
|
|
10480
|
-
storedDisposal: { length: stack.length, async at(index) {
|
|
10481
|
-
const frame = await stack.get(index);
|
|
10482
|
-
return typeof frame.disposal === "number" ? frame.disposal : 1;
|
|
10483
|
-
} },
|
|
10484
|
-
storedDelay: { length: stack.length, async at(index) {
|
|
10485
|
-
const frame = await stack.get(index);
|
|
10486
|
-
const scene2 = frame[magickInput]?.sceneIdx ?? 0;
|
|
10487
|
-
return await frame.storedDelay?.at(scene2, { signal }) ?? frame.delay?.[scene2] ?? 100;
|
|
10488
|
-
} }
|
|
10489
|
-
};
|
|
11068
|
+
image = await prepareStoredGifFrames(stack, backend, signal);
|
|
11069
|
+
pageHeight = image.pageHeight;
|
|
10490
11070
|
}
|
|
10491
11071
|
const scene = pageHeight === void 0 ? (await stack.get(0))[magickInput]?.sceneIdx ?? 0 : 0;
|
|
10492
11072
|
const delay = pageHeight === void 0 ? await image.storedDelay?.at(scene, { signal }) ?? image.delay?.[scene] : void 0;
|
|
10493
|
-
const stdoutBytes = await backend.publish(await
|
|
11073
|
+
const stdoutBytes = await backend.publish(await prepareStoredMagickOutput(image, output.format, backend, signal), output.path, { format: output.format, netpbmAscii: state.netpbmAscii ?? false, ...state.inputDepth === void 0 ? {} : { netpbmDepth: Math.min(16, state.inputDepth) }, endian: state.inputEndian, omitPngResolution: state.strip || state.omitPngResolution === true, ...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor }, chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4", quality: state.quality, ...pageHeight === void 0 ? {} : { pageHeight }, ...delay === void 0 ? {} : { delay }, ...state.loop === void 0 ? {} : { loop: state.loop }, ...state.optimizeLayers ? { optimizeFrames: true } : {} });
|
|
10494
11074
|
return { exitCode: 0, stdout: "", stderr: "", ...stdoutBytes ? { stdoutBytes } : {} };
|
|
10495
11075
|
});
|
|
10496
11076
|
}
|
|
@@ -10522,6 +11102,7 @@ function* parseMogrifySteps(argv) {
|
|
|
10522
11102
|
const readSettings = [];
|
|
10523
11103
|
const targets = [];
|
|
10524
11104
|
const flagsWithOneArg = /* @__PURE__ */ new Set([
|
|
11105
|
+
"-resample",
|
|
10525
11106
|
"-resize",
|
|
10526
11107
|
"-scale",
|
|
10527
11108
|
"-sample",
|
|
@@ -10567,12 +11148,15 @@ function* parseMogrifySteps(argv) {
|
|
|
10567
11148
|
"-liquid-rescale",
|
|
10568
11149
|
"-adaptive-resize",
|
|
10569
11150
|
"-define",
|
|
11151
|
+
"+set",
|
|
10570
11152
|
"-write",
|
|
10571
11153
|
"+write",
|
|
10572
11154
|
"-compose",
|
|
10573
11155
|
"-geometry",
|
|
10574
11156
|
"-size",
|
|
10575
11157
|
"-depth",
|
|
11158
|
+
"-compress",
|
|
11159
|
+
"-endian",
|
|
10576
11160
|
"-units",
|
|
10577
11161
|
"-interlace",
|
|
10578
11162
|
"-sampling-factor",
|
|
@@ -10626,7 +11210,7 @@ function* parseMogrifySteps(argv) {
|
|
|
10626
11210
|
}
|
|
10627
11211
|
} else if (t === "-evaluate" || t === "-function" || t === "-morphology" || t === "-statistic" || t === "-set" || t === "-distort" || t === "+distort") {
|
|
10628
11212
|
opTokens.push(t, argv[++i] ?? "", argv[++i] ?? "");
|
|
10629
|
-
} else if (["-density", "-background", "-fuzz", "-filter", "-size"].includes(t)) {
|
|
11213
|
+
} else if (["-density", "-background", "-fuzz", "-filter", "-size", "-comment", "-label"].includes(t)) {
|
|
10630
11214
|
readSettings.push(t, argv[++i] ?? "");
|
|
10631
11215
|
} else if (flagsWithOneArg.has(t)) {
|
|
10632
11216
|
opTokens.push(t, argv[++i] ?? "");
|
|
@@ -10739,13 +11323,13 @@ async function probeImageArguments(argv, files, stdinBytes, active) {
|
|
|
10739
11323
|
await withImageInputs(files, stdinBytes, active, async (read) => {
|
|
10740
11324
|
const inspect = async (source) => {
|
|
10741
11325
|
for (let position = 0; position < source.size; position += 16384) {
|
|
10742
|
-
await
|
|
11326
|
+
await yieldTurn12(active);
|
|
10743
11327
|
await source.read(position, Math.min(16384, source.size - position), { signal: active });
|
|
10744
11328
|
}
|
|
10745
11329
|
};
|
|
10746
11330
|
let operandsOnly = false;
|
|
10747
11331
|
for (let index = 0; index < argv.length; index++) {
|
|
10748
|
-
await
|
|
11332
|
+
await yieldTurn12(active);
|
|
10749
11333
|
const token = argv[index];
|
|
10750
11334
|
if (!operandsOnly && token === "--") {
|
|
10751
11335
|
operandsOnly = true;
|
|
@@ -10796,6 +11380,19 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10796
11380
|
const pattern = await parseStoredCompareInput(baseToken.slice(5), state, backend, signal, { source: readOptions.source, lastPage: readOptions.lastPage === true });
|
|
10797
11381
|
if (!pattern) return;
|
|
10798
11382
|
image = await tile(pattern);
|
|
11383
|
+
} else if (lower.startsWith("rgb:")) {
|
|
11384
|
+
if (!state.hasSize) throw new Error("must specify image size for RGB input");
|
|
11385
|
+
const path = baseToken.slice(4);
|
|
11386
|
+
const consume = async (source) => {
|
|
11387
|
+
const raw = rawRgbInput(state.sizeWidth, state.sizeHeight, state.inputDepth ?? 16, state.inputEndian ?? "lsb", source.size);
|
|
11388
|
+
return parseStoredCompareInput(`ppm:${token.slice(4)}`, state, backend, signal, { ...readOptions, source: { size: raw.size, async read(position, length) {
|
|
11389
|
+
const steps = raw.read(position, length);
|
|
11390
|
+
let next = steps.next();
|
|
11391
|
+
while (!next.done) next = steps.next(await source.read(next.value.position, next.value.length, { signal }));
|
|
11392
|
+
return next.value;
|
|
11393
|
+
} } });
|
|
11394
|
+
};
|
|
11395
|
+
return readOptions.source === null ? void 0 : readOptions.source ? consume(readOptions.source) : backend.read(path, consume);
|
|
10799
11396
|
} else if (lower.startsWith("xc:") || lower.startsWith("canvas:") || lower === "null:") {
|
|
10800
11397
|
const color = lower === "null:" ? { r: 0, g: 0, b: 0, a: 0 } : parseColor(baseToken.slice(baseToken.indexOf(":") + 1) || "white"), width = lower === "null:" ? 1 : state.sizeWidth, height = lower === "null:" ? 1 : state.sizeHeight;
|
|
10801
11398
|
image = { ...await createStoredCanvas(width, height, color, backend, signal), hasAlpha: color.a < 255 };
|
|
@@ -10805,7 +11402,7 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10805
11402
|
const [first, last] = baseToken.slice(baseToken.indexOf(":") + 1).split("-"), a = parseColor(checker ? "white" : first || "#ffffff"), b = parseColor(checker ? "black" : last || "#000000");
|
|
10806
11403
|
const cx = (width - 1) / 2, cy = (height - 1) / 2, radius = Math.max(1, Math.hypot(cx, cy));
|
|
10807
11404
|
for (let start = 0; start < width * height; start += 4096) {
|
|
10808
|
-
if (start % 262144 === 0) await
|
|
11405
|
+
if (start % 262144 === 0) await yieldTurn12(signal);
|
|
10809
11406
|
const count = Math.min(4096, width * height - start), bytes = new Uint8Array(count * 4);
|
|
10810
11407
|
for (let i = 0; i < count; i++) {
|
|
10811
11408
|
const x = (start + i) % width, y = Math.floor((start + i) / width), offset = i * 4;
|
|
@@ -10867,7 +11464,7 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10867
11464
|
const width = state.sizeWidth, height = state.sizeHeight, position = backend.storage.allocate(width * height * 4);
|
|
10868
11465
|
let cachedPosition = -1, cached = new Uint8Array();
|
|
10869
11466
|
for (let start = 0; start < width * height; start += 4096) {
|
|
10870
|
-
if (start % 262144 === 0) await
|
|
11467
|
+
if (start % 262144 === 0) await yieldTurn12(signal);
|
|
10871
11468
|
const count = Math.min(4096, width * height - start), bytes = new Uint8Array(count * 4);
|
|
10872
11469
|
for (let offset = 0; offset < count; ) {
|
|
10873
11470
|
const x = (start + offset) % width, y = Math.floor((start + offset) / width), px = x % pattern.width, py = y % pattern.height, blockX = Math.floor(px / 4096) * 4096;
|
|
@@ -10885,6 +11482,15 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10885
11482
|
return { position, width, height, format: "png", channels: 4, depth: "uchar", space: "srgb", density: 72, hasAlpha: pattern.hasAlpha };
|
|
10886
11483
|
}
|
|
10887
11484
|
async function finish(image2) {
|
|
11485
|
+
if (state.orientation !== void 0) image2 = { ...image2, orientation: state.orientation };
|
|
11486
|
+
if (state.units !== void 0) image2 = applyMagickUnits(image2, state.units);
|
|
11487
|
+
for (const key of ["comment", "label"]) {
|
|
11488
|
+
const value = state[key];
|
|
11489
|
+
if (value !== void 0) {
|
|
11490
|
+
const expanded = await formatRetainedIdentify(value, image2, { filePath: baseToken }, async () => ({ image: image2, storage: backend.storage }), signal);
|
|
11491
|
+
image2 = { ...image2, properties: { ...image2.properties, [key]: expanded } };
|
|
11492
|
+
}
|
|
11493
|
+
}
|
|
10888
11494
|
if (state.delay !== void 0) {
|
|
10889
11495
|
const delay = state.delay;
|
|
10890
11496
|
image2 = { ...image2, storedDelay: { length: image2.storedDelay?.length ?? image2.delay?.length ?? 1, async at() {
|
|
@@ -11609,7 +12215,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11609
12215
|
} };
|
|
11610
12216
|
};
|
|
11611
12217
|
for (let index = 0; index < paths.length; index++) {
|
|
11612
|
-
await
|
|
12218
|
+
await yieldTurn12(signal);
|
|
11613
12219
|
const token = paths[index];
|
|
11614
12220
|
let path2 = parseInputToken(token.toLowerCase().startsWith("tile:") ? token.slice(5) : token).baseToken;
|
|
11615
12221
|
const colon = path2.indexOf(":");
|
|
@@ -11617,7 +12223,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11617
12223
|
await backend.read(path2, async (source2) => {
|
|
11618
12224
|
const position = backend.storage.allocate(source2.size);
|
|
11619
12225
|
for (let start = 0; start < source2.size; start += 16384) {
|
|
11620
|
-
await
|
|
12226
|
+
await yieldTurn12(signal);
|
|
11621
12227
|
await backend.storage.write(position + start, await source2.read(start, Math.min(16384, source2.size - start), { signal }));
|
|
11622
12228
|
}
|
|
11623
12229
|
await sources.set(BigInt(index * 5), BigInt(position));
|
|
@@ -11647,7 +12253,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11647
12253
|
await sources.set(BigInt(index * 5 + 3), BigInt(height));
|
|
11648
12254
|
let directPng = metadata.format === "png" && !metadata.isProgressive && prefix[24] === 8 && (prefix[25] === 2 || prefix[25] === 6), idat = false;
|
|
11649
12255
|
if (directPng) for (let offset = 8; offset + 8 <= source.size; ) {
|
|
11650
|
-
await
|
|
12256
|
+
await yieldTurn12(signal);
|
|
11651
12257
|
const header = await source.read(offset, 8), size = new DataView(header.buffer, header.byteOffset, 4).getUint32(0, false);
|
|
11652
12258
|
if (offset + 8 + size > source.size) break;
|
|
11653
12259
|
const name = String.fromCharCode(...header.subarray(4));
|
|
@@ -11711,7 +12317,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11711
12317
|
canvasWidth = canvasHeight = 0;
|
|
11712
12318
|
let rowWidth = 0, rowHeight = 0;
|
|
11713
12319
|
for (let index = 0; index < Math.min(n, cols * rows); index++) {
|
|
11714
|
-
await
|
|
12320
|
+
await yieldTurn12(signal);
|
|
11715
12321
|
const image = fast ? void 0 : await images.get(index);
|
|
11716
12322
|
const width = image ? image.width : Number(await sources.get(BigInt(index * 5 + 2)));
|
|
11717
12323
|
const height = image ? image.height : Number(await sources.get(BigInt(index * 5 + 3)));
|
|
@@ -11729,7 +12335,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11729
12335
|
let canvas = await createStoredCanvas(Math.max(1, canvasWidth), Math.max(1, canvasHeight), state.background, backend, signal);
|
|
11730
12336
|
let anyTransparent = state.background.a < 255 || borderW > 0 && state.borderColor.a < 255;
|
|
11731
12337
|
for (let index = 0; index < n; index++) {
|
|
11732
|
-
await
|
|
12338
|
+
await yieldTurn12(signal);
|
|
11733
12339
|
const col = index % cols, row = Math.floor(index / cols);
|
|
11734
12340
|
if (row >= rows) break;
|
|
11735
12341
|
let image, directPng = false;
|
|
@@ -11764,7 +12370,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11764
12370
|
const x = (variableCells ? tileX : col * slotW) + (concatenate ? borderW : 0) + padX + offset.left, y = (variableCells ? tileY : row * slotH) + (concatenate ? borderW : 0) + padY + offset.top;
|
|
11765
12371
|
tileX += width + padX * 2;
|
|
11766
12372
|
if (!anyTransparent) for (let start = 0; start < image.width * image.height * 4; start += 16384) {
|
|
11767
|
-
await
|
|
12373
|
+
await yieldTurn12(signal);
|
|
11768
12374
|
const bytes = await backend.storage.read(image.position + start, Math.min(16384, image.width * image.height * 4 - start));
|
|
11769
12375
|
for (let k = 3; k < bytes.length; k += 4) if (bytes[k] < 255) {
|
|
11770
12376
|
anyTransparent = true;
|
|
@@ -11856,7 +12462,7 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11856
12462
|
const hasOutputOperand = runner !== runIdentifyCli && !(runner === runMagickCli && argv[0] === "identify");
|
|
11857
12463
|
let operandsOnly = false;
|
|
11858
12464
|
for (const [index, token] of argv.entries()) {
|
|
11859
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12465
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11860
12466
|
if (!operandsOnly && token === "--") {
|
|
11861
12467
|
operandsOnly = true;
|
|
11862
12468
|
continue;
|
|
@@ -11891,7 +12497,7 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11891
12497
|
const chunks = [];
|
|
11892
12498
|
let total = 0;
|
|
11893
12499
|
for await (const chunk of readBytes2(context.stdin, signal)) {
|
|
11894
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12500
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11895
12501
|
chargeInput(chunk.byteLength);
|
|
11896
12502
|
chunks.push(chunk);
|
|
11897
12503
|
total += chunk.byteLength;
|
|
@@ -11899,7 +12505,7 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11899
12505
|
stdinBytes = new Uint8Array(total);
|
|
11900
12506
|
let off = 0;
|
|
11901
12507
|
for (const chunk of chunks) {
|
|
11902
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12508
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11903
12509
|
stdinBytes.set(chunk, off);
|
|
11904
12510
|
off += chunk.byteLength;
|
|
11905
12511
|
}
|
|
@@ -11919,10 +12525,17 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11919
12525
|
delivered = { ...result, stdout: "" };
|
|
11920
12526
|
}
|
|
11921
12527
|
for (const [key, val] of vfsFiles.entries()) {
|
|
11922
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12528
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11923
12529
|
if (existingSnap.get(key) !== val) {
|
|
11924
12530
|
const abs = resolvePath3(context.cwd, key);
|
|
11925
|
-
|
|
12531
|
+
try {
|
|
12532
|
+
await writeFileOutput2(context, val, (data) => context.fs.writeFile(abs, data, { signal }));
|
|
12533
|
+
} catch (error) {
|
|
12534
|
+
signal.throwIfAborted();
|
|
12535
|
+
if (error instanceof FsError4 && ["ENOENT", "ENOTDIR"].includes(error.code))
|
|
12536
|
+
throw new FsError4(error.code, { syscall: "write", path: key, cause: error });
|
|
12537
|
+
throw error;
|
|
12538
|
+
}
|
|
11926
12539
|
}
|
|
11927
12540
|
}
|
|
11928
12541
|
vfsFiles.clear();
|
|
@@ -11985,6 +12598,12 @@ async function executeVfsMagickTool(context, runner, maxInputBytes) {
|
|
|
11985
12598
|
await writeBytes2(stdout.output, new TextEncoder().encode(res.stdout), invocation.signal);
|
|
11986
12599
|
}
|
|
11987
12600
|
return { exitCode: res.exitCode };
|
|
12601
|
+
} catch (error) {
|
|
12602
|
+
invocation.signal.throwIfAborted();
|
|
12603
|
+
if (!(error instanceof FsError4) || !["ENOENT", "ENOTDIR"].includes(error.code)) throw error;
|
|
12604
|
+
await writeBytes2(context.stderr, new TextEncoder().encode(`magick: ${error.message}
|
|
12605
|
+
`), invocation.signal);
|
|
12606
|
+
return { exitCode: 1 };
|
|
11988
12607
|
} finally {
|
|
11989
12608
|
await invocation.close();
|
|
11990
12609
|
}
|