@poe-platform/safe-bash 0.1.845 → 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-CMGVQM4Y.js → chunk-CSJHADNR.js} +17 -3
- 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-4KM2VJRB.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 +433 -74
- 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.js +835 -247
- 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));
|
|
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
|
+
}
|
|
3420
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],
|
|
@@ -4057,6 +4208,7 @@ function createDefaultState() {
|
|
|
4057
4208
|
tile: void 0,
|
|
4058
4209
|
strip: false,
|
|
4059
4210
|
adjoin: true,
|
|
4211
|
+
scene: 0,
|
|
4060
4212
|
dither: true,
|
|
4061
4213
|
formatStr: void 0,
|
|
4062
4214
|
channels: { r: true, g: true, b: true, a: false },
|
|
@@ -4507,6 +4659,7 @@ function* formatMagickPropertyStringSteps(fmt, meta, getImage, context = {}, res
|
|
|
4507
4659
|
Q: String(context.quality ?? meta.quality ?? 92)
|
|
4508
4660
|
};
|
|
4509
4661
|
const properties = {
|
|
4662
|
+
...meta.properties,
|
|
4510
4663
|
orientation: ["Undefined", "TopLeft", "TopRight", "BottomRight", "BottomLeft", "LeftTop", "RightTop", "RightBottom", "LeftBottom"][meta.orientation ?? 0] ?? "Undefined",
|
|
4511
4664
|
...meta.jpegSamplingFactor === void 0 ? {} : { "jpeg:sampling-factor": meta.jpegSamplingFactor },
|
|
4512
4665
|
"exif:orientation": meta.orientation === void 0 ? "" : String(meta.orientation),
|
|
@@ -4953,19 +5106,32 @@ function hasSceneOutputPattern(path) {
|
|
|
4953
5106
|
return false;
|
|
4954
5107
|
}
|
|
4955
5108
|
function formatSceneOutputPath(pattern, index) {
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
|
|
4962
|
-
|
|
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];
|
|
4963
5128
|
}
|
|
4964
|
-
|
|
5129
|
+
if (hasScene) return path;
|
|
5130
|
+
const dot = path.lastIndexOf(".");
|
|
4965
5131
|
if (dot > 0) {
|
|
4966
|
-
return `${
|
|
5132
|
+
return `${path.slice(0, dot)}-${index}${path.slice(dot)}`;
|
|
4967
5133
|
}
|
|
4968
|
-
return `${
|
|
5134
|
+
return `${path}-${index}`;
|
|
4969
5135
|
}
|
|
4970
5136
|
function parseChannelMask(spec) {
|
|
4971
5137
|
const s = spec.toLowerCase().trim();
|
|
@@ -6939,7 +7105,7 @@ async function decodeStoredMagickSvg(svg, density, backend, signal) {
|
|
|
6939
7105
|
const encoder = new TextEncoder(), base = backend.storage.allocate(0);
|
|
6940
7106
|
let size = 0;
|
|
6941
7107
|
for (let offset = 0; offset < svg.length; ) {
|
|
6942
|
-
await
|
|
7108
|
+
await yieldTurn12(signal);
|
|
6943
7109
|
const bytes = new Uint8Array(4096), { read, written } = encoder.encodeInto(svg.slice(offset, offset + 4097), bytes);
|
|
6944
7110
|
await backend.storage.write(backend.storage.allocate(written), bytes.subarray(0, written));
|
|
6945
7111
|
offset += read;
|
|
@@ -7306,12 +7472,32 @@ function* appendStackImagesSteps(stack, vertical, state) {
|
|
|
7306
7472
|
}
|
|
7307
7473
|
return { ...canvas, hasAlpha };
|
|
7308
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
|
+
}
|
|
7309
7496
|
function inferOutputFormat(spec, fallback = "png") {
|
|
7310
7497
|
const prefixMatch = /^([a-zA-Z0-9]+):(.*)$/.exec(spec);
|
|
7311
7498
|
if (prefixMatch) {
|
|
7312
7499
|
const prefix = prefixMatch[1].toLowerCase();
|
|
7313
7500
|
const rest = prefixMatch[2];
|
|
7314
|
-
if (prefix === "rgba") throw new Error("unsupported output coder 'rgba'");
|
|
7315
7501
|
const fmt = extToImageFormat(prefix);
|
|
7316
7502
|
if (fmt) {
|
|
7317
7503
|
return { format: fmt, path: rest };
|
|
@@ -7326,7 +7512,11 @@ function inferOutputFormat(spec, fallback = "png") {
|
|
|
7326
7512
|
return { format: fallback, path: spec };
|
|
7327
7513
|
}
|
|
7328
7514
|
function extToImageFormat(ext) {
|
|
7515
|
+
const rawCoder = ext.toLowerCase();
|
|
7516
|
+
if (isRawCoder(rawCoder)) return rawCoder;
|
|
7329
7517
|
switch (ext.toLowerCase()) {
|
|
7518
|
+
case "miff":
|
|
7519
|
+
return "miff";
|
|
7330
7520
|
case "png":
|
|
7331
7521
|
return "png";
|
|
7332
7522
|
case "jpg":
|
|
@@ -7341,6 +7531,8 @@ function extToImageFormat(ext) {
|
|
|
7341
7531
|
case "tif":
|
|
7342
7532
|
case "tiff":
|
|
7343
7533
|
return "tiff";
|
|
7534
|
+
case "pam":
|
|
7535
|
+
return "pam";
|
|
7344
7536
|
case "ppm":
|
|
7345
7537
|
return "ppm";
|
|
7346
7538
|
case "pgm":
|
|
@@ -7449,6 +7641,15 @@ function* parseInputOperandsSteps(token, files, state, stdinBytes, maxDecodeDime
|
|
|
7449
7641
|
const { baseToken, pageSpec, inlineGeom } = parseInputToken(token);
|
|
7450
7642
|
function* applyMod(imgs) {
|
|
7451
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
|
+
}
|
|
7452
7653
|
if (state.delay !== void 0) im = { ...im, delay: Array(im.delay?.length ?? 1).fill(state.delay) };
|
|
7453
7654
|
return inlineGeom ? yield* applyInlineReadModifierSteps(im, inlineGeom, state.kernel) : im;
|
|
7454
7655
|
});
|
|
@@ -7495,14 +7696,28 @@ function* parseInputOperandsSteps(token, files, state, stdinBytes, maxDecodeDime
|
|
|
7495
7696
|
if (lower === "null:") {
|
|
7496
7697
|
return yield* applyMod([yield* createSolidRgbaImageSteps(1, 1, { r: 0, g: 0, b: 0, a: 0 })]);
|
|
7497
7698
|
}
|
|
7498
|
-
|
|
7699
|
+
const rgb = lower.startsWith("rgb:");
|
|
7700
|
+
let cleanToken = rgb ? baseToken.slice(4) : baseToken;
|
|
7499
7701
|
const prefixMatch = /^([a-zA-Z0-9]+):(.*)$/.exec(cleanToken);
|
|
7500
7702
|
if (prefixMatch && extToImageFormat(prefixMatch[1])) {
|
|
7501
7703
|
cleanToken = prefixMatch[2];
|
|
7502
7704
|
}
|
|
7503
|
-
|
|
7705
|
+
let rawBytes = cleanToken === "-" ? stdinBytes : files.get(cleanToken) ?? files.get(token);
|
|
7504
7706
|
if (!rawBytes)
|
|
7505
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
|
+
}
|
|
7506
7721
|
let totalPages = 1;
|
|
7507
7722
|
let inputMeta;
|
|
7508
7723
|
try {
|
|
@@ -7653,7 +7868,7 @@ async function drainIdentifySteps(steps, signal) {
|
|
|
7653
7868
|
while (!next.done) {
|
|
7654
7869
|
try {
|
|
7655
7870
|
if (next.value) await next.value.run();
|
|
7656
|
-
else await
|
|
7871
|
+
else await yieldTurn12(signal);
|
|
7657
7872
|
next = steps.next();
|
|
7658
7873
|
} catch (error) {
|
|
7659
7874
|
next = steps.throw(error);
|
|
@@ -8514,7 +8729,7 @@ async function transformStoredMagickPixels(image, backend, operation, signal, hi
|
|
|
8514
8729
|
let storedData16;
|
|
8515
8730
|
let storedHueSamples;
|
|
8516
8731
|
for (let offset = 0; offset < size; offset += 16384) {
|
|
8517
|
-
if (offset % 1048576 === 0) await
|
|
8732
|
+
if (offset % 1048576 === 0) await yieldTurn12(signal);
|
|
8518
8733
|
const data = await backend.storage.read(image.position + offset, Math.min(16384, size - offset));
|
|
8519
8734
|
const bytes16 = (highDepth || operation.highDepth) && image.storedData16 ? await backend.storage.read(image.storedData16.position + offset * 2, data.length * 2) : void 0;
|
|
8520
8735
|
const data16 = bytes16 ? new Uint16Array(bytes16.buffer, bytes16.byteOffset, bytes16.byteLength / 2) : void 0;
|
|
@@ -8536,9 +8751,118 @@ async function transformStoredMagickPixels(image, backend, operation, signal, hi
|
|
|
8536
8751
|
}
|
|
8537
8752
|
return result;
|
|
8538
8753
|
}
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
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]);
|
|
8542
8866
|
}
|
|
8543
8867
|
function parseMagickDisposal(value) {
|
|
8544
8868
|
const names = ["undefined", "none", "background", "previous"];
|
|
@@ -8547,6 +8871,49 @@ function parseMagickDisposal(value) {
|
|
|
8547
8871
|
if (["0", "1", "2", "3"].includes(value)) return Number(value);
|
|
8548
8872
|
return 0;
|
|
8549
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
|
+
}
|
|
8550
8917
|
function applyMagickReadSetting(tokens, state, start) {
|
|
8551
8918
|
let i = start;
|
|
8552
8919
|
const t = tokens[i];
|
|
@@ -8563,6 +8930,23 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8563
8930
|
} else if (t === "+channel") {
|
|
8564
8931
|
state.channels = { r: true, g: true, b: true, a: false };
|
|
8565
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;
|
|
8566
8950
|
} else if (t === "-size") {
|
|
8567
8951
|
const g = parseMagickGeometry(tokens[++i] ?? "1x1");
|
|
8568
8952
|
state.sizeWidth = Math.max(1, Math.round(g.width ?? 1));
|
|
@@ -8595,6 +8979,8 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8595
8979
|
state.gravity = parseGravity(tokens[++i] ?? "center");
|
|
8596
8980
|
} else if (t === "+gravity") {
|
|
8597
8981
|
state.gravity = "northwest";
|
|
8982
|
+
} else if (t === "-comment" || t === "-label") {
|
|
8983
|
+
state[t === "-comment" ? "comment" : "label"] = tokens[++i] ?? "";
|
|
8598
8984
|
} else if (t === "-sampling-factor") {
|
|
8599
8985
|
state.samplingFactor = tokens[++i] ?? "";
|
|
8600
8986
|
} else if (t === "+sampling-factor") {
|
|
@@ -8616,6 +9002,9 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8616
9002
|
state.compose = parseCompose(cRaw);
|
|
8617
9003
|
} else if (t === "-define") {
|
|
8618
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
|
+
}
|
|
8619
9008
|
if (defStr.toLowerCase().startsWith("connected-components:")) {
|
|
8620
9009
|
const [key, value, extra] = defStr.toLowerCase().split("=");
|
|
8621
9010
|
if (extra !== void 0 || key !== "connected-components:verbose" || value !== "true" && value !== "false") throw new Error(`Unsupported connected-components define: ${defStr}`);
|
|
@@ -8629,12 +9018,13 @@ function applyMagickReadSetting(tokens, state, start) {
|
|
|
8629
9018
|
const k = (tokens[++i] ?? "").toLowerCase();
|
|
8630
9019
|
const v = tokens[++i] ?? "";
|
|
8631
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 };
|
|
8632
9022
|
if (k === "option:compose:args")
|
|
8633
9023
|
state.composeArgs = v;
|
|
8634
9024
|
} else return void 0;
|
|
8635
9025
|
return i;
|
|
8636
9026
|
}
|
|
8637
|
-
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()) {
|
|
8638
9028
|
let cooperativeWork = 63;
|
|
8639
9029
|
let stack = [];
|
|
8640
9030
|
let operandsOnly = false;
|
|
@@ -8647,9 +9037,20 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8647
9037
|
i++;
|
|
8648
9038
|
continue;
|
|
8649
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
|
+
}
|
|
8650
9050
|
if (operandsOnly) {
|
|
8651
9051
|
const loaded = yield* parseInputOperandsSteps(t, files, state, stdinBytes);
|
|
8652
|
-
if (loaded)
|
|
9052
|
+
if (!loaded) throw new Error(`unable to open image '${t}'`);
|
|
9053
|
+
stack.push(...loaded);
|
|
8653
9054
|
i++;
|
|
8654
9055
|
continue;
|
|
8655
9056
|
}
|
|
@@ -8668,11 +9069,39 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8668
9069
|
const endIdx = depth === 0 ? j - 1 : j;
|
|
8669
9070
|
const subTokens = tokens.slice(i + 1, endIdx);
|
|
8670
9071
|
const subState = { ...state };
|
|
8671
|
-
const subResult = yield* evaluatePipelineTokensSteps(subTokens, files, subState, stack, stdinBytes, signal, analysis);
|
|
9072
|
+
const subResult = yield* evaluatePipelineTokensSteps(subTokens, files, subState, stack, stdinBytes, signal, analysis, registers);
|
|
8672
9073
|
stack.push(...subResult);
|
|
8673
9074
|
i = j;
|
|
8674
9075
|
continue;
|
|
8675
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
|
+
}
|
|
8676
9105
|
if (t === "-set" && tokens[i + 1]?.toLowerCase() === "delay") {
|
|
8677
9106
|
const delay = Number(tokens[i + 2] ?? 0) * 10;
|
|
8678
9107
|
stack = yield* mapSteps(stack, function* (image) {
|
|
@@ -8691,6 +9120,26 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8691
9120
|
i += 3;
|
|
8692
9121
|
continue;
|
|
8693
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
|
+
}
|
|
8694
9143
|
const setting = applyMagickReadSetting(tokens, state, i);
|
|
8695
9144
|
const pixelOperation = setting === void 0 ? parseMagickPixelOperation(tokens, state, i, signal) : void 0;
|
|
8696
9145
|
const warpOperation = setting === void 0 ? parseMagickWarpOperation(tokens, state, i) : void 0;
|
|
@@ -8732,35 +9181,59 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8732
9181
|
return { ...output, ..."space" in plan && plan.space ? { space: plan.space, channels: plan.space === "srgb" ? 4 : output.channels } : {}, ...plan.virtualCanvas ? { virtualCanvas: plan.virtualCanvas } : {} };
|
|
8733
9182
|
});
|
|
8734
9183
|
} else if (t === "-write" || t === "+write") {
|
|
8735
|
-
|
|
8736
|
-
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:") {
|
|
8737
9195
|
const top = stack[stack.length - 1];
|
|
8738
9196
|
const { format, path } = inferOutputFormat(writePath, top.format);
|
|
8739
|
-
if (stack.length > 1 && (
|
|
9197
|
+
if (hasSceneOutputPattern(path) || stack.length > 1 && (!state.adjoin || path !== "-" && ["png", "jpeg", "bmp"].includes(format))) {
|
|
8740
9198
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
8741
9199
|
if (++cooperativeWork % 65536 === 0)
|
|
8742
9200
|
yield;
|
|
8743
|
-
const framePath = formatSceneOutputPath(path, idx);
|
|
8744
|
-
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 });
|
|
8745
9203
|
files.set(framePath, frameBytes);
|
|
8746
9204
|
}
|
|
8747
9205
|
} else {
|
|
8748
|
-
const
|
|
8749
|
-
|
|
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);
|
|
8750
9210
|
}
|
|
8751
9211
|
}
|
|
8752
9212
|
} else if (t === "-geometry") {
|
|
8753
9213
|
state.geometry = tokens[++i] ?? "+0+0";
|
|
8754
9214
|
} else if (t === "-tile") {
|
|
8755
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));
|
|
8756
9222
|
} else if (t === "-strip") {
|
|
8757
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
|
+
}
|
|
8758
9228
|
} else if (t === "-format") {
|
|
8759
9229
|
state.formatStr = tokens[++i] ?? "";
|
|
8760
9230
|
} else if (t === "+adjoin") {
|
|
8761
9231
|
state.adjoin = false;
|
|
8762
9232
|
} else if (t === "-adjoin") {
|
|
8763
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");
|
|
8764
9237
|
} else if (t === "-delay") {
|
|
8765
9238
|
state.delay = Number(tokens[++i] ?? 0) * 10;
|
|
8766
9239
|
} else if (t === "-loop") {
|
|
@@ -8929,6 +9402,12 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
8929
9402
|
const { virtualCanvas: ignoredCanvas, ...reset } = image;
|
|
8930
9403
|
return reset;
|
|
8931
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
|
+
});
|
|
8932
9411
|
} else if (t === "-resize" || t === "-scale" || t === "-sample" || t === "-thumbnail") {
|
|
8933
9412
|
const geom = tokens[++i] ?? "100%";
|
|
8934
9413
|
const k = t === "-sample" ? "nearest" : state.kernel;
|
|
@@ -9307,25 +9786,36 @@ function* evaluatePipelineTokensSteps(tokens, files, state, parentStack, stdinBy
|
|
|
9307
9786
|
if (mergeOntoCanvas) {
|
|
9308
9787
|
state.background = prevBg;
|
|
9309
9788
|
}
|
|
9310
|
-
if (loaded) {
|
|
9311
|
-
|
|
9312
|
-
|
|
9313
|
-
|
|
9314
|
-
|
|
9315
|
-
|
|
9316
|
-
}
|
|
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);
|
|
9317
9795
|
}
|
|
9318
9796
|
}
|
|
9319
9797
|
i++;
|
|
9320
9798
|
}
|
|
9321
9799
|
return stack;
|
|
9322
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
|
+
}
|
|
9323
9813
|
function* runConvertCliSteps(argv, files, stdinBytes, signal) {
|
|
9324
|
-
const analysis = { text: "", warnings: "" };
|
|
9814
|
+
const analysis = { text: "", warnings: "", bytes: [] };
|
|
9325
9815
|
const result = yield* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis);
|
|
9326
|
-
return
|
|
9816
|
+
return combineConvertOutput(result, analysis);
|
|
9327
9817
|
}
|
|
9328
|
-
function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = { text: "", warnings: "" }) {
|
|
9818
|
+
function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = { text: "", warnings: "", bytes: [] }) {
|
|
9329
9819
|
const listRes = tryHandleMagickListOption(argv);
|
|
9330
9820
|
if (listRes) return listRes;
|
|
9331
9821
|
let cooperativeWork = 63;
|
|
@@ -9344,7 +9834,7 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9344
9834
|
stderr: ""
|
|
9345
9835
|
};
|
|
9346
9836
|
}
|
|
9347
|
-
|
|
9837
|
+
let outSpec = argv[argv.length - 1];
|
|
9348
9838
|
const pipelineTokens = argv.slice(0, -1);
|
|
9349
9839
|
const state = createDefaultState();
|
|
9350
9840
|
try {
|
|
@@ -9357,9 +9847,10 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9357
9847
|
`
|
|
9358
9848
|
};
|
|
9359
9849
|
}
|
|
9850
|
+
outSpec = expandFilenameProperties(outSpec, state);
|
|
9360
9851
|
const finalImg = stack[stack.length - 1];
|
|
9361
9852
|
const outLower = outSpec.toLowerCase();
|
|
9362
|
-
if (outLower === "null:") return { exitCode: 0, stdout: "", stderr: "" };
|
|
9853
|
+
if (outLower === "null:" || outLower.startsWith("mpr:")) return { exitCode: 0, stdout: "", stderr: "" };
|
|
9363
9854
|
if (outLower === "info:" || outLower === "info:-") {
|
|
9364
9855
|
const formatted = [];
|
|
9365
9856
|
for (const [idx, im] of stack.entries()) {
|
|
@@ -9392,50 +9883,21 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9392
9883
|
return { exitCode: 0, stdout: hist, stderr: "" };
|
|
9393
9884
|
}
|
|
9394
9885
|
const { format, path: outPath } = inferOutputFormat(outSpec, "png");
|
|
9395
|
-
if (stack.length > 1 && (
|
|
9886
|
+
if (hasSceneOutputPattern(outPath) || stack.length > 1 && (!state.adjoin || outPath !== "-" && ["png", "jpeg", "bmp"].includes(format))) {
|
|
9396
9887
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
9397
9888
|
if (++cooperativeWork % 64 === 0)
|
|
9398
9889
|
yield;
|
|
9399
|
-
const framePath = formatSceneOutputPath(outPath, idx);
|
|
9400
|
-
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 });
|
|
9401
9892
|
files.set(framePath, frameBytes);
|
|
9402
9893
|
}
|
|
9403
9894
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
9404
9895
|
}
|
|
9405
|
-
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);
|
|
9406
9897
|
let encodePageHeight;
|
|
9407
9898
|
if (stack.length > 1 && format === "gif") {
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
fw = Math.max(fw, frame.width);
|
|
9411
|
-
fh = Math.max(fh, frame.height);
|
|
9412
|
-
}
|
|
9413
|
-
const combined = new Uint8Array(fw * fh * stack.length * 4);
|
|
9414
|
-
const delays = [];
|
|
9415
|
-
const disposals = [];
|
|
9416
|
-
for (let idx = 0; idx < stack.length; idx++) {
|
|
9417
|
-
if (++cooperativeWork % 64 === 0)
|
|
9418
|
-
yield;
|
|
9419
|
-
const outputFrame = yield* prepareHueOutput(stack[idx], format);
|
|
9420
|
-
disposals.push(typeof outputFrame.disposal === "number" ? outputFrame.disposal : 1);
|
|
9421
|
-
delays.push(outputFrame.delay?.[stack[idx][magickInput]?.sceneIdx ?? 0] ?? 100);
|
|
9422
|
-
for (let y = 0; y < outputFrame.height; y++) {
|
|
9423
|
-
if (++cooperativeWork % 64 === 0) yield;
|
|
9424
|
-
combined.set(outputFrame.data.subarray(y * outputFrame.width * 4, (y + 1) * outputFrame.width * 4), (idx * fw * fh + y * fw) * 4);
|
|
9425
|
-
}
|
|
9426
|
-
}
|
|
9427
|
-
toEncode = {
|
|
9428
|
-
...yield* prepareHueOutput(stack[0], format),
|
|
9429
|
-
width: fw,
|
|
9430
|
-
height: fh * stack.length,
|
|
9431
|
-
pages: stack.length,
|
|
9432
|
-
pageHeight: fh,
|
|
9433
|
-
delay: delays,
|
|
9434
|
-
disposal: disposals,
|
|
9435
|
-
gifFrames: stack.map((frame) => ({ width: frame.width, height: frame.height, x: frame.virtualCanvas?.x ?? 0, y: frame.virtualCanvas?.y ?? 0 })),
|
|
9436
|
-
data: combined
|
|
9437
|
-
};
|
|
9438
|
-
encodePageHeight = fh;
|
|
9899
|
+
toEncode = yield* prepareGifFrames(stack);
|
|
9900
|
+
encodePageHeight = toEncode.pageHeight;
|
|
9439
9901
|
}
|
|
9440
9902
|
if (typeof globalThis.gc === "function") {
|
|
9441
9903
|
try {
|
|
@@ -9447,6 +9909,10 @@ function* runConvertCliResultSteps(argv, files, stdinBytes, signal, analysis = {
|
|
|
9447
9909
|
}
|
|
9448
9910
|
const { data: encoded } = encodeImage(toEncode, {
|
|
9449
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,
|
|
9450
9916
|
...state.samplingFactor === void 0 ? {} : { samplingFactor: state.samplingFactor },
|
|
9451
9917
|
chromaSubsampling: state.quality < 90 ? "4:2:0" : "4:4:4",
|
|
9452
9918
|
quality: state.quality,
|
|
@@ -9483,7 +9949,7 @@ async function transformStoredMagickRaster(image, backend, steps, signal, dimens
|
|
|
9483
9949
|
signal.throwIfAborted();
|
|
9484
9950
|
const request = next.value;
|
|
9485
9951
|
if (!request) {
|
|
9486
|
-
await
|
|
9952
|
+
await yieldTurn12(signal);
|
|
9487
9953
|
await checkpoint?.();
|
|
9488
9954
|
next = steps.next();
|
|
9489
9955
|
} else if (request.kind === "write") {
|
|
@@ -9515,7 +9981,7 @@ async function morphStoredMagickImage(image, backend, plan, signal) {
|
|
|
9515
9981
|
const position = backend.storage.allocate(size);
|
|
9516
9982
|
const a = images[step.a], b = images[step.b];
|
|
9517
9983
|
for (let offset = 0; offset < size; offset += 16384) {
|
|
9518
|
-
await
|
|
9984
|
+
await yieldTurn12(signal);
|
|
9519
9985
|
const length = Math.min(16384, size - offset);
|
|
9520
9986
|
const left = new Uint8Array(await backend.storage.read(a.position + offset, length));
|
|
9521
9987
|
const bytes = await drainSteps(subtractMagickPixelSteps(left, await backend.storage.read(b.position + offset, length), image.hasAlpha), signal);
|
|
@@ -9567,7 +10033,7 @@ async function transformStoredMagickCoordinates(image, backend, token, geometry,
|
|
|
9567
10033
|
let work = 0;
|
|
9568
10034
|
for (const y of ys) for (let row = 0; row < y.length; row++) for (const x of xs) {
|
|
9569
10035
|
for (let offset = 0; offset < x.length; offset += 4096) {
|
|
9570
|
-
if (work++ % 64 === 0) await
|
|
10036
|
+
if (work++ % 64 === 0) await yieldTurn12(signal);
|
|
9571
10037
|
const length = Math.min(4096, x.length - offset) * 4;
|
|
9572
10038
|
const sourceX = Math.min(w - 1, x.source + offset);
|
|
9573
10039
|
const sourceLength = Math.min(length, (w - sourceX) * 4);
|
|
@@ -9597,7 +10063,7 @@ async function compositeStoredMagick(base, overlay, backend, signal, left, top,
|
|
|
9597
10063
|
let hasAlpha = base.hasAlpha || !generic && !compositeMode.delegated && !compositeMode.preservesAlpha;
|
|
9598
10064
|
const position = inPlace ? base.position : backend.storage.allocate(base.width * base.height * 4);
|
|
9599
10065
|
for (let start = 0; !inPlace && start < base.width * base.height * 4; start += 16384) {
|
|
9600
|
-
await
|
|
10066
|
+
await yieldTurn12(signal);
|
|
9601
10067
|
await backend.storage.write(position + start, await backend.storage.read(base.position + start, Math.min(16384, base.width * base.height * 4 - start)));
|
|
9602
10068
|
}
|
|
9603
10069
|
const maskDestination = !generic && ["dstin", "destin", "srcin", "in", "srcout", "out", "dstatop", "destatop"].includes(compositeMode.name);
|
|
@@ -9606,7 +10072,7 @@ async function compositeStoredMagick(base, overlay, backend, signal, left, top,
|
|
|
9606
10072
|
const bottom = tile || extendSource ? base.height : Math.min(base.height, top + overlay.height);
|
|
9607
10073
|
for (let y = extendSource ? 0 : Math.max(0, top); y < bottom; y++) {
|
|
9608
10074
|
for (let x = extendSource ? 0 : Math.max(0, left); x < right; ) {
|
|
9609
|
-
await
|
|
10075
|
+
await yieldTurn12(signal);
|
|
9610
10076
|
const sourceX = tile ? x % overlay.width : Math.max(0, Math.min(overlay.width - 1, x - left));
|
|
9611
10077
|
const sourceY = tile ? y % overlay.height : Math.max(0, Math.min(overlay.height - 1, y - top));
|
|
9612
10078
|
const repeatEdge = extendSource && !tile && (x < left || x >= left + overlay.width);
|
|
@@ -9645,24 +10111,37 @@ async function compositeStoredMagick(base, overlay, backend, signal, left, top,
|
|
|
9645
10111
|
}
|
|
9646
10112
|
return { ...base, position, hasAlpha, channels: hasAlpha ? base.channels : base.channels <= 2 ? 1 : 3 };
|
|
9647
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
|
+
}
|
|
9648
10126
|
async function tryConvertFiles(argv, input, stdinBytes, signal) {
|
|
9649
|
-
const analysis = { text: "", warnings: "" };
|
|
10127
|
+
const analysis = { text: "", warnings: "", bytes: [] };
|
|
9650
10128
|
const result = await tryConvertFilesResult(argv, input, stdinBytes, signal, analysis);
|
|
9651
|
-
return result ?
|
|
10129
|
+
return result ? combineConvertOutput(result, analysis) : void 0;
|
|
9652
10130
|
}
|
|
9653
10131
|
async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis) {
|
|
9654
10132
|
if (!input.filesystem.capabilities || !input.filesystem.open || !input.filesystem.removeFileConditional) return;
|
|
9655
|
-
|
|
10133
|
+
let outSpec = argv.at(-1) ?? "";
|
|
9656
10134
|
const optionArgs = argv.slice(0, argv.indexOf("--") < 0 ? argv.length : argv.indexOf("--"));
|
|
9657
10135
|
if (!outSpec || tryHandleMagickListOption(argv) || optionArgs.some((token) => ["--help", "-help", "-h", "--version", "-version"].includes(token))) {
|
|
9658
10136
|
await probeImageArguments(argv, input, stdinBytes, signal);
|
|
9659
10137
|
return drainSteps(runConvertCliSteps(argv, /* @__PURE__ */ new Map(), stdinBytes, signal), signal);
|
|
9660
10138
|
}
|
|
9661
10139
|
let output;
|
|
9662
|
-
await
|
|
10140
|
+
await yieldTurn12(signal);
|
|
9663
10141
|
let state = createDefaultState();
|
|
9664
10142
|
const tokens = argv.slice(0, -1), scopes = [];
|
|
9665
10143
|
const steps = [];
|
|
10144
|
+
const registers = /* @__PURE__ */ new Map();
|
|
9666
10145
|
const stackStep = (runStack) => {
|
|
9667
10146
|
steps.push({ runStack });
|
|
9668
10147
|
};
|
|
@@ -9670,7 +10149,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9670
10149
|
try {
|
|
9671
10150
|
output = inferOutputFormat(outSpec, "png");
|
|
9672
10151
|
for (let i = 0; i < tokens.length; i++) {
|
|
9673
|
-
if (i && i % 64 === 0) await
|
|
10152
|
+
if (i && i % 64 === 0) await yieldTurn12(signal);
|
|
9674
10153
|
const token = tokens[i];
|
|
9675
10154
|
if (token === "") continue;
|
|
9676
10155
|
if (!operandsOnly && token === "-sampling-factor") {
|
|
@@ -9726,20 +10205,20 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9726
10205
|
const length = source.length;
|
|
9727
10206
|
if (token.endsWith("clone") && length === 0) throw new Error(`UnableToCloneImage ${token}`);
|
|
9728
10207
|
for (let repeat = 0; repeat < count; repeat++) for (const index of parseMagickIndexSpec(spec, length, "clone")) {
|
|
9729
|
-
await
|
|
10208
|
+
await yieldTurn12(signal);
|
|
9730
10209
|
await stack.push(await source.get(index));
|
|
9731
10210
|
}
|
|
9732
10211
|
} else if (token.endsWith("delete")) await stack.remove(parseMagickIndexSpec(spec, stack.length, "delete"));
|
|
9733
10212
|
else if (token === "-reverse") {
|
|
9734
10213
|
for (let n = 0; n < Math.floor(stack.length / 2); n++) {
|
|
9735
|
-
await
|
|
10214
|
+
await yieldTurn12(signal);
|
|
9736
10215
|
await stack.swap(n, stack.length - 1 - n);
|
|
9737
10216
|
}
|
|
9738
10217
|
} else if (token.endsWith("insert")) {
|
|
9739
10218
|
const raw = token === "+insert" ? 0 : Number(spec), target = raw < 0 ? stack.length - 1 + raw : raw;
|
|
9740
10219
|
if (!Number.isInteger(target) || target < 0 || target >= stack.length || raw < 0 && target === 0) throw new Error(`invalid image index ${token}`);
|
|
9741
10220
|
for (let n = stack.length - 1; n > target; n--) {
|
|
9742
|
-
await
|
|
10221
|
+
await yieldTurn12(signal);
|
|
9743
10222
|
await stack.swap(n, n - 1);
|
|
9744
10223
|
}
|
|
9745
10224
|
} else {
|
|
@@ -9791,7 +10270,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9791
10270
|
const a = await stack.get(index), b = await stack.get(index + 1);
|
|
9792
10271
|
await result.push(a);
|
|
9793
10272
|
for (let step = 1; step <= count; step++) {
|
|
9794
|
-
await
|
|
10273
|
+
await yieldTurn12(signal);
|
|
9795
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));
|
|
9796
10275
|
await result.push(await transformStoredMagickRaster(a, backend, morphPixelSteps(a, b, width, height, fraction), signal, { ...a, width, height }, [a, b]));
|
|
9797
10276
|
}
|
|
@@ -9819,6 +10298,22 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9819
10298
|
});
|
|
9820
10299
|
continue;
|
|
9821
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
|
+
}
|
|
9822
10317
|
if (!operandsOnly && token === "-set" && tokens[i + 1]?.toLowerCase() === "delay") {
|
|
9823
10318
|
const delay = Number(tokens[i + 2] ?? 0) * 10;
|
|
9824
10319
|
steps.push(async (image) => image ? {
|
|
@@ -9836,6 +10331,25 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9836
10331
|
i += 2;
|
|
9837
10332
|
continue;
|
|
9838
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
|
+
}
|
|
9839
10353
|
const setting = operandsOnly ? void 0 : applyMagickReadSetting(tokens, state, i);
|
|
9840
10354
|
if (setting !== void 0) {
|
|
9841
10355
|
i = setting;
|
|
@@ -9893,7 +10407,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9893
10407
|
if (!image) return;
|
|
9894
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;
|
|
9895
10409
|
for (let offset = 0; offset < size; offset += 16384) {
|
|
9896
|
-
if (offset % 1048576 === 0) await
|
|
10410
|
+
if (offset % 1048576 === 0) await yieldTurn12(signal);
|
|
9897
10411
|
const original = analysisOperation.highDepth ? image.storedData16 : void 0;
|
|
9898
10412
|
const bytes = await backend.storage.read((original?.position ?? image.position) + offset * (original ? 2 : 1), Math.min(16384, size - offset) * (original ? 2 : 1));
|
|
9899
10413
|
await drainSteps(accumulateMagickHistogram(original ? new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2) : bytes, histogram), signal);
|
|
@@ -9911,7 +10425,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9911
10425
|
const layout = smushLayoutSteps(images, token === "-smush", gap, settings.gravity);
|
|
9912
10426
|
let next = layout.next();
|
|
9913
10427
|
while (!next.done) {
|
|
9914
|
-
await
|
|
10428
|
+
await yieldTurn12(signal);
|
|
9915
10429
|
const request = next.value;
|
|
9916
10430
|
next = layout.next(await backend.storage.read(images[request.index].position + request.position, request.length));
|
|
9917
10431
|
}
|
|
@@ -9957,7 +10471,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9957
10471
|
if (append && stack.length === 1) return stack;
|
|
9958
10472
|
let width = 0, height = 0;
|
|
9959
10473
|
for (let n = 0; n < (flatten ? 1 : stack.length); n++) {
|
|
9960
|
-
await
|
|
10474
|
+
await yieldTurn12(signal);
|
|
9961
10475
|
const frame = await stack.get(n);
|
|
9962
10476
|
width = append && !vertical ? width + frame.width : Math.max(width, frame.width);
|
|
9963
10477
|
height = append && vertical ? height + frame.height : Math.max(height, frame.height);
|
|
@@ -9971,7 +10485,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
9971
10485
|
const left = vertical ? offset.left : cursor, top = vertical ? cursor : offset.top;
|
|
9972
10486
|
for (let y = 0; y < frame.height; y++) {
|
|
9973
10487
|
for (let x = 0; x < frame.width; x += 4096) {
|
|
9974
|
-
await
|
|
10488
|
+
await yieldTurn12(signal);
|
|
9975
10489
|
const pixels = await backend.storage.read(frame.position + (y * frame.width + x) * 4, Math.min(4096, frame.width - x) * 4);
|
|
9976
10490
|
await backend.storage.write(result.position + ((top + y) * width + left + x) * 4, pixels);
|
|
9977
10491
|
}
|
|
@@ -10019,7 +10533,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10019
10533
|
let next = bounds.next();
|
|
10020
10534
|
while (!next.done) {
|
|
10021
10535
|
if (!next.value) {
|
|
10022
|
-
await
|
|
10536
|
+
await yieldTurn12(signal);
|
|
10023
10537
|
next = bounds.next();
|
|
10024
10538
|
} else {
|
|
10025
10539
|
const { image, position, length } = next.value;
|
|
@@ -10054,6 +10568,11 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10054
10568
|
});
|
|
10055
10569
|
continue;
|
|
10056
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
|
+
}
|
|
10057
10576
|
if (!operandsOnly && (token === "+adjoin" || token === "-adjoin")) {
|
|
10058
10577
|
state.adjoin = token === "-adjoin";
|
|
10059
10578
|
continue;
|
|
@@ -10066,8 +10585,31 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10066
10585
|
state.gravity = "northwest";
|
|
10067
10586
|
continue;
|
|
10068
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
|
+
}
|
|
10069
10606
|
if (!operandsOnly && token === "-strip") {
|
|
10070
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
|
+
});
|
|
10071
10613
|
continue;
|
|
10072
10614
|
}
|
|
10073
10615
|
if (!operandsOnly && token === "+repage") {
|
|
@@ -10084,17 +10626,35 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10084
10626
|
continue;
|
|
10085
10627
|
}
|
|
10086
10628
|
if (!operandsOnly && (token === "-write" || token === "+write")) {
|
|
10087
|
-
|
|
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;
|
|
10088
10636
|
stackStep(async (stack, backend) => {
|
|
10637
|
+
if (stack.length === 0) throw new Error(`no images for write '${token}'`);
|
|
10089
10638
|
const image = await stack.get(stack.length - 1);
|
|
10090
|
-
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:") {
|
|
10091
10647
|
const output2 = inferOutputFormat(path, image.format);
|
|
10092
|
-
if (stack.length > 1 && (
|
|
10648
|
+
if (hasSceneOutputPattern(output2.path) || stack.length > 1 && (!adjoin || output2.path !== "-" && ["png", "jpeg", "bmp"].includes(output2.format))) {
|
|
10093
10649
|
for (let index = 0; index < stack.length; index++) {
|
|
10094
|
-
await
|
|
10095
|
-
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 });
|
|
10096
10652
|
}
|
|
10097
|
-
} 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
|
+
}
|
|
10098
10658
|
}
|
|
10099
10659
|
return stack;
|
|
10100
10660
|
});
|
|
@@ -10137,7 +10697,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10137
10697
|
if (!image) return;
|
|
10138
10698
|
for (const step of magickDrawSteps(image, drawing, settings)) {
|
|
10139
10699
|
if (!step) {
|
|
10140
|
-
await
|
|
10700
|
+
await yieldTurn12(signal);
|
|
10141
10701
|
continue;
|
|
10142
10702
|
}
|
|
10143
10703
|
if ((image.space === "b-w" || image.space === "grey16") && !(step.kind === "floodfill" && step.alphaOnly))
|
|
@@ -10253,6 +10813,14 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10253
10813
|
} else if (!operandsOnly && ["-roll", "-splice", "-chop"].includes(token)) {
|
|
10254
10814
|
const geometry = tokens[++i] ?? (token === "-roll" ? "+0+0" : "0x0"), captured = { ...state };
|
|
10255
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
|
+
});
|
|
10256
10824
|
} else if (!operandsOnly && ["-resize", "-scale", "-sample", "-thumbnail"].includes(token)) {
|
|
10257
10825
|
const geometry = tokens[++i] ?? "100%", kernel = token === "-sample" ? "nearest" : state.kernel, thumbnail = token === "-thumbnail";
|
|
10258
10826
|
steps.push(async (image, backend) => {
|
|
@@ -10296,7 +10864,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10296
10864
|
for (let n = 0; n < stack.length; n++) {
|
|
10297
10865
|
const image = await stack.get(n);
|
|
10298
10866
|
for (const area of magickCropAreas(image, geometry, gravity)) {
|
|
10299
|
-
await
|
|
10867
|
+
await yieldTurn12(signal);
|
|
10300
10868
|
if (area === null) {
|
|
10301
10869
|
analysis.warnings += `magick: geometry does not contain image '${geometry}'
|
|
10302
10870
|
`;
|
|
@@ -10381,19 +10949,34 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10381
10949
|
};
|
|
10382
10950
|
});
|
|
10383
10951
|
} else {
|
|
10384
|
-
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
|
+
}
|
|
10385
10958
|
if (!operandsOnly && (token === "(" || token === ")")) continue;
|
|
10386
10959
|
const captured = { ...state }, literal = operandsOnly, maxDecodeDimension = inferMaxDecodeDimensionFromUpcomingTokens(tokens, i + 1);
|
|
10387
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
|
+
}
|
|
10388
10970
|
const base = stack.length === 1 ? await stack.get(0) : void 0, lower = token.toLowerCase();
|
|
10389
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);
|
|
10390
10972
|
const settings = merge ? { ...captured, background: { r: 0, g: 0, b: 0, a: 0 } } : captured;
|
|
10391
|
-
await parseStoredCompareInput(token, settings, backend, signal, { visit: async (image) => {
|
|
10973
|
+
const loaded = await parseStoredCompareInput(token, settings, backend, signal, { visit: async (image) => {
|
|
10392
10974
|
if (merge) {
|
|
10393
10975
|
const composed = await compositeStoredMagick(base, image, backend, signal, 0, 0, "over");
|
|
10394
10976
|
await stack.set(0, { ...composed, hasAlpha: base.hasAlpha, channels: base.channels });
|
|
10395
10977
|
} else await stack.push(image);
|
|
10396
10978
|
}, ...maxDecodeDimension === void 0 ? {} : { maxDecodeDimension } });
|
|
10979
|
+
if (!loaded) throw new Error(`unable to open image '${token}'`);
|
|
10397
10980
|
return stack;
|
|
10398
10981
|
});
|
|
10399
10982
|
}
|
|
@@ -10434,8 +11017,10 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10434
11017
|
return { exitCode: 1, stdout: "", stderr: `magick: no images defined '${outSpec}'
|
|
10435
11018
|
` };
|
|
10436
11019
|
}
|
|
10437
|
-
await
|
|
10438
|
-
|
|
11020
|
+
await yieldTurn12(signal);
|
|
11021
|
+
outSpec = expandFilenameProperties(outSpec, state);
|
|
11022
|
+
output = inferOutputFormat(outSpec, "png");
|
|
11023
|
+
if (outSpec.toLowerCase() === "null:" || outSpec.toLowerCase().startsWith("mpr:")) {
|
|
10439
11024
|
await backend.publishPending();
|
|
10440
11025
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
10441
11026
|
}
|
|
@@ -10444,7 +11029,7 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10444
11029
|
async function* information() {
|
|
10445
11030
|
let last = "";
|
|
10446
11031
|
for (let index = 0; index < stack.length; index++) {
|
|
10447
|
-
await
|
|
11032
|
+
await yieldTurn12(signal);
|
|
10448
11033
|
const frame = await stack.get(index);
|
|
10449
11034
|
if (index && !state.formatStr) yield "\n";
|
|
10450
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`;
|
|
@@ -10468,60 +11053,24 @@ async function tryConvertFilesResult(argv, input, stdinBytes, signal, analysis)
|
|
|
10468
11053
|
await backend.publishPending();
|
|
10469
11054
|
return { exitCode: 0, stdout, stderr: "" };
|
|
10470
11055
|
}
|
|
10471
|
-
if (stack.length > 1 && (
|
|
11056
|
+
if (hasSceneOutputPattern(output.path) || stack.length > 1 && (!state.adjoin || output.path !== "-" && ["png", "jpeg", "bmp"].includes(output.format))) {
|
|
10472
11057
|
for (let index = 0; index < stack.length; index++) {
|
|
10473
|
-
await
|
|
10474
|
-
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 });
|
|
10475
11060
|
}
|
|
10476
11061
|
await backend.publishPending();
|
|
10477
11062
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
10478
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);
|
|
10479
11066
|
let pageHeight;
|
|
10480
11067
|
if (stack.length > 1 && output.format === "gif") {
|
|
10481
|
-
|
|
10482
|
-
|
|
10483
|
-
for (let index = 1; index < stack.length; index++) {
|
|
10484
|
-
const frame = await stack.get(index);
|
|
10485
|
-
width = Math.max(width, frame.width);
|
|
10486
|
-
height = Math.max(height, frame.height);
|
|
10487
|
-
}
|
|
10488
|
-
const size = width * height * 4, position = backend.storage.allocate(size * stack.length);
|
|
10489
|
-
for (let index = 0; index < stack.length; index++) {
|
|
10490
|
-
const frame = await prepareStoredHueOutput(await stack.get(index), output.format, backend, signal);
|
|
10491
|
-
for (let y = 0; y < height; y++) for (let x = 0; x < width; x += 4096) {
|
|
10492
|
-
await yieldTurn11(signal);
|
|
10493
|
-
const count = Math.min(4096, width - x), bytes = new Uint8Array(count * 4);
|
|
10494
|
-
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));
|
|
10495
|
-
await backend.storage.write(position + index * size + (y * width + x) * 4, bytes);
|
|
10496
|
-
}
|
|
10497
|
-
}
|
|
10498
|
-
pageHeight = height;
|
|
10499
|
-
const { storedData16: ignored, ...metadata } = first;
|
|
10500
|
-
image = {
|
|
10501
|
-
...metadata,
|
|
10502
|
-
position,
|
|
10503
|
-
width,
|
|
10504
|
-
height: height * stack.length,
|
|
10505
|
-
pages: stack.length,
|
|
10506
|
-
pageHeight,
|
|
10507
|
-
storedGifFrame: { async at(index) {
|
|
10508
|
-
const frame = await stack.get(index);
|
|
10509
|
-
return { width: frame.width, height: frame.height, x: frame.virtualCanvas?.x ?? 0, y: frame.virtualCanvas?.y ?? 0 };
|
|
10510
|
-
} },
|
|
10511
|
-
storedDisposal: { length: stack.length, async at(index) {
|
|
10512
|
-
const frame = await stack.get(index);
|
|
10513
|
-
return typeof frame.disposal === "number" ? frame.disposal : 1;
|
|
10514
|
-
} },
|
|
10515
|
-
storedDelay: { length: stack.length, async at(index) {
|
|
10516
|
-
const frame = await stack.get(index);
|
|
10517
|
-
const scene2 = frame[magickInput]?.sceneIdx ?? 0;
|
|
10518
|
-
return await frame.storedDelay?.at(scene2, { signal }) ?? frame.delay?.[scene2] ?? 100;
|
|
10519
|
-
} }
|
|
10520
|
-
};
|
|
11068
|
+
image = await prepareStoredGifFrames(stack, backend, signal);
|
|
11069
|
+
pageHeight = image.pageHeight;
|
|
10521
11070
|
}
|
|
10522
11071
|
const scene = pageHeight === void 0 ? (await stack.get(0))[magickInput]?.sceneIdx ?? 0 : 0;
|
|
10523
11072
|
const delay = pageHeight === void 0 ? await image.storedDelay?.at(scene, { signal }) ?? image.delay?.[scene] : void 0;
|
|
10524
|
-
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 } : {} });
|
|
10525
11074
|
return { exitCode: 0, stdout: "", stderr: "", ...stdoutBytes ? { stdoutBytes } : {} };
|
|
10526
11075
|
});
|
|
10527
11076
|
}
|
|
@@ -10553,6 +11102,7 @@ function* parseMogrifySteps(argv) {
|
|
|
10553
11102
|
const readSettings = [];
|
|
10554
11103
|
const targets = [];
|
|
10555
11104
|
const flagsWithOneArg = /* @__PURE__ */ new Set([
|
|
11105
|
+
"-resample",
|
|
10556
11106
|
"-resize",
|
|
10557
11107
|
"-scale",
|
|
10558
11108
|
"-sample",
|
|
@@ -10598,12 +11148,15 @@ function* parseMogrifySteps(argv) {
|
|
|
10598
11148
|
"-liquid-rescale",
|
|
10599
11149
|
"-adaptive-resize",
|
|
10600
11150
|
"-define",
|
|
11151
|
+
"+set",
|
|
10601
11152
|
"-write",
|
|
10602
11153
|
"+write",
|
|
10603
11154
|
"-compose",
|
|
10604
11155
|
"-geometry",
|
|
10605
11156
|
"-size",
|
|
10606
11157
|
"-depth",
|
|
11158
|
+
"-compress",
|
|
11159
|
+
"-endian",
|
|
10607
11160
|
"-units",
|
|
10608
11161
|
"-interlace",
|
|
10609
11162
|
"-sampling-factor",
|
|
@@ -10657,7 +11210,7 @@ function* parseMogrifySteps(argv) {
|
|
|
10657
11210
|
}
|
|
10658
11211
|
} else if (t === "-evaluate" || t === "-function" || t === "-morphology" || t === "-statistic" || t === "-set" || t === "-distort" || t === "+distort") {
|
|
10659
11212
|
opTokens.push(t, argv[++i] ?? "", argv[++i] ?? "");
|
|
10660
|
-
} else if (["-density", "-background", "-fuzz", "-filter", "-size"].includes(t)) {
|
|
11213
|
+
} else if (["-density", "-background", "-fuzz", "-filter", "-size", "-comment", "-label"].includes(t)) {
|
|
10661
11214
|
readSettings.push(t, argv[++i] ?? "");
|
|
10662
11215
|
} else if (flagsWithOneArg.has(t)) {
|
|
10663
11216
|
opTokens.push(t, argv[++i] ?? "");
|
|
@@ -10770,13 +11323,13 @@ async function probeImageArguments(argv, files, stdinBytes, active) {
|
|
|
10770
11323
|
await withImageInputs(files, stdinBytes, active, async (read) => {
|
|
10771
11324
|
const inspect = async (source) => {
|
|
10772
11325
|
for (let position = 0; position < source.size; position += 16384) {
|
|
10773
|
-
await
|
|
11326
|
+
await yieldTurn12(active);
|
|
10774
11327
|
await source.read(position, Math.min(16384, source.size - position), { signal: active });
|
|
10775
11328
|
}
|
|
10776
11329
|
};
|
|
10777
11330
|
let operandsOnly = false;
|
|
10778
11331
|
for (let index = 0; index < argv.length; index++) {
|
|
10779
|
-
await
|
|
11332
|
+
await yieldTurn12(active);
|
|
10780
11333
|
const token = argv[index];
|
|
10781
11334
|
if (!operandsOnly && token === "--") {
|
|
10782
11335
|
operandsOnly = true;
|
|
@@ -10827,6 +11380,19 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10827
11380
|
const pattern = await parseStoredCompareInput(baseToken.slice(5), state, backend, signal, { source: readOptions.source, lastPage: readOptions.lastPage === true });
|
|
10828
11381
|
if (!pattern) return;
|
|
10829
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);
|
|
10830
11396
|
} else if (lower.startsWith("xc:") || lower.startsWith("canvas:") || lower === "null:") {
|
|
10831
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;
|
|
10832
11398
|
image = { ...await createStoredCanvas(width, height, color, backend, signal), hasAlpha: color.a < 255 };
|
|
@@ -10836,7 +11402,7 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10836
11402
|
const [first, last] = baseToken.slice(baseToken.indexOf(":") + 1).split("-"), a = parseColor(checker ? "white" : first || "#ffffff"), b = parseColor(checker ? "black" : last || "#000000");
|
|
10837
11403
|
const cx = (width - 1) / 2, cy = (height - 1) / 2, radius = Math.max(1, Math.hypot(cx, cy));
|
|
10838
11404
|
for (let start = 0; start < width * height; start += 4096) {
|
|
10839
|
-
if (start % 262144 === 0) await
|
|
11405
|
+
if (start % 262144 === 0) await yieldTurn12(signal);
|
|
10840
11406
|
const count = Math.min(4096, width * height - start), bytes = new Uint8Array(count * 4);
|
|
10841
11407
|
for (let i = 0; i < count; i++) {
|
|
10842
11408
|
const x = (start + i) % width, y = Math.floor((start + i) / width), offset = i * 4;
|
|
@@ -10898,7 +11464,7 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10898
11464
|
const width = state.sizeWidth, height = state.sizeHeight, position = backend.storage.allocate(width * height * 4);
|
|
10899
11465
|
let cachedPosition = -1, cached = new Uint8Array();
|
|
10900
11466
|
for (let start = 0; start < width * height; start += 4096) {
|
|
10901
|
-
if (start % 262144 === 0) await
|
|
11467
|
+
if (start % 262144 === 0) await yieldTurn12(signal);
|
|
10902
11468
|
const count = Math.min(4096, width * height - start), bytes = new Uint8Array(count * 4);
|
|
10903
11469
|
for (let offset = 0; offset < count; ) {
|
|
10904
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;
|
|
@@ -10916,6 +11482,15 @@ async function parseStoredCompareInput(token, state, backend, signal, readOption
|
|
|
10916
11482
|
return { position, width, height, format: "png", channels: 4, depth: "uchar", space: "srgb", density: 72, hasAlpha: pattern.hasAlpha };
|
|
10917
11483
|
}
|
|
10918
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
|
+
}
|
|
10919
11494
|
if (state.delay !== void 0) {
|
|
10920
11495
|
const delay = state.delay;
|
|
10921
11496
|
image2 = { ...image2, storedDelay: { length: image2.storedDelay?.length ?? image2.delay?.length ?? 1, async at() {
|
|
@@ -11640,7 +12215,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11640
12215
|
} };
|
|
11641
12216
|
};
|
|
11642
12217
|
for (let index = 0; index < paths.length; index++) {
|
|
11643
|
-
await
|
|
12218
|
+
await yieldTurn12(signal);
|
|
11644
12219
|
const token = paths[index];
|
|
11645
12220
|
let path2 = parseInputToken(token.toLowerCase().startsWith("tile:") ? token.slice(5) : token).baseToken;
|
|
11646
12221
|
const colon = path2.indexOf(":");
|
|
@@ -11648,7 +12223,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11648
12223
|
await backend.read(path2, async (source2) => {
|
|
11649
12224
|
const position = backend.storage.allocate(source2.size);
|
|
11650
12225
|
for (let start = 0; start < source2.size; start += 16384) {
|
|
11651
|
-
await
|
|
12226
|
+
await yieldTurn12(signal);
|
|
11652
12227
|
await backend.storage.write(position + start, await source2.read(start, Math.min(16384, source2.size - start), { signal }));
|
|
11653
12228
|
}
|
|
11654
12229
|
await sources.set(BigInt(index * 5), BigInt(position));
|
|
@@ -11678,7 +12253,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11678
12253
|
await sources.set(BigInt(index * 5 + 3), BigInt(height));
|
|
11679
12254
|
let directPng = metadata.format === "png" && !metadata.isProgressive && prefix[24] === 8 && (prefix[25] === 2 || prefix[25] === 6), idat = false;
|
|
11680
12255
|
if (directPng) for (let offset = 8; offset + 8 <= source.size; ) {
|
|
11681
|
-
await
|
|
12256
|
+
await yieldTurn12(signal);
|
|
11682
12257
|
const header = await source.read(offset, 8), size = new DataView(header.buffer, header.byteOffset, 4).getUint32(0, false);
|
|
11683
12258
|
if (offset + 8 + size > source.size) break;
|
|
11684
12259
|
const name = String.fromCharCode(...header.subarray(4));
|
|
@@ -11742,7 +12317,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11742
12317
|
canvasWidth = canvasHeight = 0;
|
|
11743
12318
|
let rowWidth = 0, rowHeight = 0;
|
|
11744
12319
|
for (let index = 0; index < Math.min(n, cols * rows); index++) {
|
|
11745
|
-
await
|
|
12320
|
+
await yieldTurn12(signal);
|
|
11746
12321
|
const image = fast ? void 0 : await images.get(index);
|
|
11747
12322
|
const width = image ? image.width : Number(await sources.get(BigInt(index * 5 + 2)));
|
|
11748
12323
|
const height = image ? image.height : Number(await sources.get(BigInt(index * 5 + 3)));
|
|
@@ -11760,7 +12335,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11760
12335
|
let canvas = await createStoredCanvas(Math.max(1, canvasWidth), Math.max(1, canvasHeight), state.background, backend, signal);
|
|
11761
12336
|
let anyTransparent = state.background.a < 255 || borderW > 0 && state.borderColor.a < 255;
|
|
11762
12337
|
for (let index = 0; index < n; index++) {
|
|
11763
|
-
await
|
|
12338
|
+
await yieldTurn12(signal);
|
|
11764
12339
|
const col = index % cols, row = Math.floor(index / cols);
|
|
11765
12340
|
if (row >= rows) break;
|
|
11766
12341
|
let image, directPng = false;
|
|
@@ -11795,7 +12370,7 @@ async function runMontageFiles(argv, input, stdinBytes, signal) {
|
|
|
11795
12370
|
const x = (variableCells ? tileX : col * slotW) + (concatenate ? borderW : 0) + padX + offset.left, y = (variableCells ? tileY : row * slotH) + (concatenate ? borderW : 0) + padY + offset.top;
|
|
11796
12371
|
tileX += width + padX * 2;
|
|
11797
12372
|
if (!anyTransparent) for (let start = 0; start < image.width * image.height * 4; start += 16384) {
|
|
11798
|
-
await
|
|
12373
|
+
await yieldTurn12(signal);
|
|
11799
12374
|
const bytes = await backend.storage.read(image.position + start, Math.min(16384, image.width * image.height * 4 - start));
|
|
11800
12375
|
for (let k = 3; k < bytes.length; k += 4) if (bytes[k] < 255) {
|
|
11801
12376
|
anyTransparent = true;
|
|
@@ -11887,7 +12462,7 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11887
12462
|
const hasOutputOperand = runner !== runIdentifyCli && !(runner === runMagickCli && argv[0] === "identify");
|
|
11888
12463
|
let operandsOnly = false;
|
|
11889
12464
|
for (const [index, token] of argv.entries()) {
|
|
11890
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12465
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11891
12466
|
if (!operandsOnly && token === "--") {
|
|
11892
12467
|
operandsOnly = true;
|
|
11893
12468
|
continue;
|
|
@@ -11922,7 +12497,7 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11922
12497
|
const chunks = [];
|
|
11923
12498
|
let total = 0;
|
|
11924
12499
|
for await (const chunk of readBytes2(context.stdin, signal)) {
|
|
11925
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12500
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11926
12501
|
chargeInput(chunk.byteLength);
|
|
11927
12502
|
chunks.push(chunk);
|
|
11928
12503
|
total += chunk.byteLength;
|
|
@@ -11930,7 +12505,7 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11930
12505
|
stdinBytes = new Uint8Array(total);
|
|
11931
12506
|
let off = 0;
|
|
11932
12507
|
for (const chunk of chunks) {
|
|
11933
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12508
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11934
12509
|
stdinBytes.set(chunk, off);
|
|
11935
12510
|
off += chunk.byteLength;
|
|
11936
12511
|
}
|
|
@@ -11950,10 +12525,17 @@ async function runBufferedImageFiles(argv, input, runner, stdinBytes, signal) {
|
|
|
11950
12525
|
delivered = { ...result, stdout: "" };
|
|
11951
12526
|
}
|
|
11952
12527
|
for (const [key, val] of vfsFiles.entries()) {
|
|
11953
|
-
if (++cooperativeWork % 64 === 0) await
|
|
12528
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn12(context.signal);
|
|
11954
12529
|
if (existingSnap.get(key) !== val) {
|
|
11955
12530
|
const abs = resolvePath3(context.cwd, key);
|
|
11956
|
-
|
|
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
|
+
}
|
|
11957
12539
|
}
|
|
11958
12540
|
}
|
|
11959
12541
|
vfsFiles.clear();
|
|
@@ -12016,6 +12598,12 @@ async function executeVfsMagickTool(context, runner, maxInputBytes) {
|
|
|
12016
12598
|
await writeBytes2(stdout.output, new TextEncoder().encode(res.stdout), invocation.signal);
|
|
12017
12599
|
}
|
|
12018
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 };
|
|
12019
12607
|
} finally {
|
|
12020
12608
|
await invocation.close();
|
|
12021
12609
|
}
|