@poe-platform/safe-bash 0.1.787 → 0.1.789
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/safe-bash/chunks/{chunk-WHURJBET.js → chunk-2MUJ7RLZ.js} +1 -1
- package/dist/safe-bash/chunks/{chunk-PYTLIUST.js → chunk-CTUHLNJM.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-Z3HX3ZBA.js → chunk-D4PHJK4T.js} +1 -1
- package/dist/safe-bash/chunks/{chunk-O6356Z27.js → chunk-H7MMJS26.js} +2 -2
- package/dist/safe-bash/chunks/{chunk-Q3E6C3DX.js → chunk-KHJGUF2W.js} +14 -0
- package/dist/safe-bash/chunks/{chunk-FJZNUUOQ.js → chunk-VUVKC6HV.js} +1 -1
- package/dist/safe-bash/chunks/{chunk-ZMYVCRAF.js → chunk-X5ZCECM6.js} +2 -2
- package/dist/safe-bash/chunks/{git-UFNPAOYZ.js → git-HO7WDPHZ.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-PFBJR2PY.js → chunk-2KRKKW5S.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-4DSJDVBM.js → chunk-32F3RBUW.js} +10 -749
- package/dist/safe-bash/command-chunks/{chunk-WVWWRMFD.js → chunk-3KROFHBT.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-L3MLMXL4.js → chunk-3ZK5F23O.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-4QX6XCDD.js → chunk-4RNIZ3RT.js} +79 -0
- package/dist/safe-bash/command-chunks/{chunk-IFUNAM4D.js → chunk-5L62A5RO.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-D7TADAYG.js → chunk-64LG3EVJ.js} +17 -0
- package/dist/safe-bash/command-chunks/{chunk-JUDOV5MJ.js → chunk-6F7QJMJ3.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-IJ3FXP4Q.js → chunk-A3ZX6SCY.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-DREUDEQG.js → chunk-AT6ZSOE6.js} +3 -3
- package/dist/safe-bash/command-chunks/{chunk-BUKYQBXO.js → chunk-BJ6DGYJA.js} +12 -12
- package/dist/safe-bash/command-chunks/{chunk-KSIGF4AG.js → chunk-BK4CMEE6.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-NSEUBSOD.js → chunk-CXMOCPPH.js} +2 -2
- package/dist/safe-bash/command-chunks/{chunk-XGMWWUHV.js → chunk-CZ5DAK4K.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-Z57TV6TC.js → chunk-EZ2DTOLI.js} +4 -2
- package/dist/safe-bash/command-chunks/{chunk-ADCGH6A7.js → chunk-FH3D75FC.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-WYJTWJZ5.js → chunk-G3G6W5ZE.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-3HDIDEUJ.js → chunk-GF54KE2M.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-3JS4FOLB.js → chunk-HETU7MYN.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-Z7TYZG3A.js → chunk-IHHTTQX6.js} +5 -3
- package/dist/safe-bash/command-chunks/{chunk-INDIFLBW.js → chunk-JTAGNROA.js} +4 -0
- package/dist/safe-bash/command-chunks/{chunk-Z47EO74H.js → chunk-MYKK3Q5G.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-GZOUGVVV.js → chunk-OYZ534IK.js} +1 -1
- package/dist/safe-bash/command-chunks/chunk-PGEYORBZ.js +25 -0
- package/dist/safe-bash/command-chunks/chunk-QM4UZF3C.js +753 -0
- package/dist/safe-bash/command-chunks/{chunk-TOSM3T3A.js → chunk-UJOO6DKY.js} +20 -9
- package/dist/safe-bash/command-chunks/{chunk-TFZEYNMX.js → chunk-VQLFJCG7.js} +1 -1
- package/dist/safe-bash/command-chunks/{chunk-BIXN77VL.js → chunk-VUG324ER.js} +10 -0
- package/dist/safe-bash/command-chunks/{chunk-2LP3VMPA.js → chunk-WFDW4XXD.js} +1 -17
- package/dist/safe-bash/command-chunks/chunk-WR37IS4O.js +318 -0
- package/dist/safe-bash/command-chunks/{chunk-Y5IHIAY3.js → chunk-XNHSCU6I.js} +7 -3
- package/dist/safe-bash/commands/basic.js +148 -48
- package/dist/safe-bash/commands/bytes/compression/index.js +5 -6
- package/dist/safe-bash/commands/cmp.d.ts +2 -3
- package/dist/safe-bash/commands/cmp.js +2 -689
- package/dist/safe-bash/commands/docx/index.browser.js +3 -46
- package/dist/safe-bash/commands/docx/index.d.ts +2 -24
- package/dist/safe-bash/commands/docx/index.js +2 -41
- package/dist/safe-bash/commands/docx/io.d.ts +1 -14
- package/dist/safe-bash/commands/docx/io.js +1 -15
- package/dist/safe-bash/commands/llm/index.browser.js +3 -3
- package/dist/safe-bash/commands/network/index.browser.js +3 -3
- package/dist/safe-bash/commands/node/index.browser.js +3 -3
- package/dist/safe-bash/commands/pptx/index.d.ts +2 -28
- package/dist/safe-bash/commands/pptx/index.js +2 -152
- package/dist/safe-bash/commands/printf-float.d.ts +1 -0
- package/dist/safe-bash/commands/printf-float.js +48 -38
- package/dist/safe-bash/commands/printf-format.js +9 -6
- package/dist/safe-bash/commands/printf-quote.d.ts +3 -0
- package/dist/safe-bash/commands/printf-quote.js +62 -0
- package/dist/safe-bash/commands/printf-wide.d.ts +5 -0
- package/dist/safe-bash/commands/printf-wide.js +41 -0
- package/dist/safe-bash/commands/python/index.browser.js +2 -2
- package/dist/safe-bash/commands/truncate.d.ts +2 -3
- package/dist/safe-bash/commands/truncate.js +2 -686
- package/dist/safe-bash/contracts/diagnostics.d.ts +2 -0
- package/dist/safe-bash/contracts/diagnostics.js +2 -0
- package/dist/safe-bash/contracts/runtime-control.d.ts +2 -0
- package/dist/safe-bash/contracts/runtime-control.js +2 -0
- package/dist/safe-bash/core.browser.d.ts +1 -1
- package/dist/safe-bash/core.browser.js +2651 -4871
- package/dist/safe-bash/core.d.ts +10 -0
- package/dist/safe-bash/opt-in/commands/cmp/index.d.ts +6 -2
- package/dist/safe-bash/opt-in/commands/cmp/index.js +776 -79
- package/dist/safe-bash/opt-in/commands/cmp/options.d.ts +0 -12
- package/dist/safe-bash/opt-in/commands/cmp/options.js +0 -153
- package/dist/safe-bash/opt-in/commands/truncate/index.d.ts +8 -3
- package/dist/safe-bash/opt-in/commands/truncate/index.js +790 -272
- package/dist/safe-bash/opt-in/commands/truncate/sync.d.ts +1 -0
- package/dist/safe-bash/opt-in/commands/truncate/sync.js +60 -0
- package/dist/safe-bash/optional-host.browser.js +9 -1
- package/dist/safe-bash/optional-host.d.ts +3 -1
- package/dist/safe-bash/optional-host.js +3 -1
- package/dist/safe-bash/shell/runtime.js +10 -6
- package/dist/safe-bash-checksum-engine/index.d.ts +1 -1
- package/dist/safe-bash-checksum-engine/index.js +14 -2
- package/dist/safe-bash-command-bzip2/index.js +2 -1
- package/dist/safe-bash-command-cmp/index.d.ts +10 -0
- package/dist/safe-bash-command-cmp/index.js +796 -0
- package/dist/safe-bash-command-cmp/options.d.ts +12 -0
- package/dist/safe-bash-command-cmp/options.js +42 -0
- package/dist/safe-bash-command-csvcut/index.js +11 -8
- package/dist/safe-bash-command-csvgrep/index.js +35 -7
- package/dist/safe-bash-command-csvkit/codecs/python.js +4 -3
- package/dist/safe-bash-command-csvkit/codecs/utf8.js +3 -2
- package/dist/safe-bash-command-csvkit/index.js +80 -324
- package/dist/safe-bash-command-csvkit/python-regex.d.ts +5 -0
- package/dist/safe-bash-command-csvkit/python-regex.js +14 -0
- package/dist/safe-bash-command-csvkit/runtime.d.ts +1 -0
- package/dist/safe-bash-command-csvkit/sync-support.js +4 -2
- package/dist/safe-bash-command-diff3/index.js +3 -0
- package/dist/safe-bash-command-docx/LICENSE +21 -0
- package/dist/safe-bash-command-docx/index.d.ts +30 -0
- package/dist/safe-bash-command-docx/index.js +67 -0
- package/dist/safe-bash-command-docx/io.d.ts +14 -0
- package/dist/safe-bash-command-docx/io.js +26 -0
- package/dist/safe-bash-command-envsubst/index.js +34 -3
- package/dist/safe-bash-command-exiftool/index.js +3 -0
- package/dist/safe-bash-command-ffmpeg/index.js +1102 -1088
- package/dist/safe-bash-command-fold/family.js +1 -1
- package/dist/safe-bash-command-fold/index.js +1 -1
- package/dist/safe-bash-command-htmlq/index.js +5 -0
- package/dist/safe-bash-command-imagemagick/index.d.ts +25 -21
- package/dist/safe-bash-command-imagemagick/index.js +669 -271
- package/dist/safe-bash-command-mmdc/index.js +48 -10
- package/dist/safe-bash-command-mmdc/svg.d.ts +1 -0
- package/dist/safe-bash-command-op/index.js +19 -14
- package/dist/safe-bash-command-pandoc/command.js +1 -1
- package/dist/safe-bash-command-pandoc/index.js +1 -1
- package/dist/safe-bash-command-pdfimages/index.d.ts +7 -1
- package/dist/safe-bash-command-pdfimages/index.js +63 -33
- package/dist/safe-bash-command-pdfinfo/index.d.ts +24 -20
- package/dist/safe-bash-command-pdfinfo/index.js +370 -161
- package/dist/safe-bash-command-pdftk/index.d.ts +7 -3
- package/dist/safe-bash-command-pdftk/index.js +114 -45
- package/dist/safe-bash-command-pdftoppm/index.d.ts +15 -7
- package/dist/safe-bash-command-pdftoppm/index.js +179 -109
- package/dist/safe-bash-command-pdftotext/index.d.ts +9 -5
- package/dist/safe-bash-command-pdftotext/index.js +90 -27
- package/dist/safe-bash-command-pptx/LICENSE +21 -0
- package/dist/safe-bash-command-pptx/index.d.ts +33 -0
- package/dist/safe-bash-command-pptx/index.js +168 -0
- package/dist/safe-bash-command-qpdf/index.d.ts +9 -3
- package/dist/safe-bash-command-qpdf/index.js +80 -29
- package/dist/safe-bash-command-sha512sum/index.js +12 -475
- package/dist/safe-bash-command-sips/index.d.ts +9 -5
- package/dist/safe-bash-command-sips/index.js +63 -44
- package/dist/safe-bash-command-soffice/index.d.ts +9 -3
- package/dist/safe-bash-command-soffice/index.js +65 -24
- package/dist/safe-bash-command-sqlite3/engine.d.ts +9 -0
- package/dist/safe-bash-command-sqlite3/index.d.ts +1 -0
- package/dist/safe-bash-command-sqlite3/index.js +851 -352
- package/dist/safe-bash-command-ssconvert/formats/xls.js +3 -3
- package/dist/safe-bash-command-timeout/index.js +3 -3
- package/dist/safe-bash-command-truncate/index.d.ts +8 -3
- package/dist/safe-bash-command-truncate/index.js +790 -272
- package/dist/safe-bash-command-truncate/sync.d.ts +1 -0
- package/dist/safe-bash-command-truncate/sync.js +60 -0
- package/dist/safe-bash-command-wkhtmltopdf/index.js +92 -38
- package/dist/safe-bash-command-wkhtmltopdf/pdf-renderer.d.ts +1 -1
- package/dist/safe-bash-command-xxd/index.js +78 -20
- package/dist/safe-bash-command-xz/command.d.ts +4 -0
- package/dist/safe-bash-command-xz/index.d.ts +1 -1
- package/dist/safe-bash-command-xz/index.js +1 -1
- package/dist/safe-bash-compression-engine/bounded-codec.js +3 -3
- package/dist/safe-bash-compression-engine/codec-loader.js +2 -2
- package/dist/safe-bash-compression-engine/files.js +6 -6
- package/dist/safe-bash-compression-engine/index.js +5 -5
- package/dist/safe-bash-compression-engine/operand.js +6 -6
- package/dist/safe-bash-compression-engine/stream.js +5 -5
- package/dist/safe-bash-compression-engine/zstd-decode.js +4 -4
- package/dist/safe-bash-contracts/command.js +3 -3
- package/dist/safe-bash-contracts/diagnostics.js +3 -3
- package/dist/safe-bash-contracts/escaping.js +9 -9
- package/dist/safe-bash-contracts/filesystem-descriptor.js +3 -3
- package/dist/safe-bash-contracts/filesystem-output.js +8 -8
- package/dist/safe-bash-contracts/index.js +21 -19
- package/dist/safe-bash-contracts/io.d.ts +12 -0
- package/dist/safe-bash-contracts/io.js +4 -1
- package/dist/safe-bash-contracts/output.js +3 -2
- package/dist/safe-bash-contracts/runtime-control.js +2 -2
- package/dist/safe-bash-contracts/signals.js +1 -1
- package/dist/safe-bash-contracts/yield.d.ts +1 -0
- package/dist/safe-bash-contracts/yield.js +3 -1
- package/dist/safe-bash-csv-engine/index.d.ts +10 -1
- package/dist/safe-bash-csv-engine/index.js +78 -6
- package/dist/safe-bash-io-engine/commands/search/requirements.js +3 -3
- package/dist/safe-bash-io-engine/commands/text-programs/shared.js +3 -3
- package/dist/safe-bash-io-engine/gnu-information.js +1 -1
- package/dist/safe-bash-io-engine/internal.d.ts +1 -1
- package/dist/safe-bash-io-engine/internal.js +2 -2
- package/dist/safe-bash-mcp/index.browser.d.ts +875 -0
- package/dist/safe-bash-mcp/index.browser.js +8740 -0
- package/dist/safe-bash-mcp/index.js +32 -31
- package/dist/safe-bash-query-engine/capture.js +3 -3
- package/dist/safe-bash-query-engine/delpaths.js +3 -3
- package/dist/safe-bash-query-engine/formats.js +2 -2
- package/dist/safe-bash-query-engine/index.js +12 -12
- package/dist/safe-bash-query-engine/indices.js +3 -3
- package/dist/safe-bash-query-engine/input.js +1 -1
- package/dist/safe-bash-query-engine/interpreter.js +10 -10
- package/dist/safe-bash-query-engine/query-core.js +12 -12
- package/dist/safe-bash-query-engine/regex.js +3 -3
- package/dist/safe-bash-query-engine/splits.js +4 -4
- package/dist/safe-bash-query-engine/values.js +2 -2
- package/package.json +9 -3
- package/dist/safe-bash/opt-in/commands/cmp/compare.js +0 -95
- package/dist/safe-bash/opt-in/commands/cmp/io.js +0 -218
- package/dist/safe-bash/command-chunks/{chunk-FXYWQ6S4.js → chunk-2VTMZTV3.js} +0 -0
- package/dist/safe-bash/command-chunks/{chunk-DEH3CMGL.js → chunk-QJ3ONEBI.js} +3 -3
|
@@ -36,6 +36,8 @@ import {
|
|
|
36
36
|
|
|
37
37
|
// packages/safe-bash-command-imagemagick/dist/index.js
|
|
38
38
|
init_buffer();
|
|
39
|
+
import { yieldTurn, drainCooperativeSteps as drainSteps } from "../safe-bash-contracts/yield.js";
|
|
40
|
+
import { InputByteBudget } from "../safe-bash-contracts/io.js";
|
|
39
41
|
import { writeFileOutput } from "../safe-bash-contracts/filesystem-output-budget.js";
|
|
40
42
|
import {
|
|
41
43
|
commandRuntimeIdentity,
|
|
@@ -445,7 +447,8 @@ function createDefaultState() {
|
|
|
445
447
|
channelExplicit: false
|
|
446
448
|
};
|
|
447
449
|
}
|
|
448
|
-
function
|
|
450
|
+
function* applyMagickMorphology4ChSteps(img, methodRaw, kernelSpec, signal) {
|
|
451
|
+
let cooperativeWork = 0;
|
|
449
452
|
const m = methodRaw.toLowerCase();
|
|
450
453
|
let rx = 1;
|
|
451
454
|
let ry = 1;
|
|
@@ -504,13 +507,23 @@ function applyMagickMorphology4Ch(img, methodRaw, kernelSpec) {
|
|
|
504
507
|
const out = new Uint8Array(img.data.length);
|
|
505
508
|
const win = [];
|
|
506
509
|
for (let y = 0; y < h; y++) {
|
|
510
|
+
if (++cooperativeWork % 65536 === 0)
|
|
511
|
+
yield;
|
|
507
512
|
for (let x = 0; x < w; x++) {
|
|
513
|
+
if (++cooperativeWork % 65536 === 0)
|
|
514
|
+
yield;
|
|
508
515
|
const dstOff = (y * w + x) * 4;
|
|
509
516
|
for (let c = 0; c < 4; c++) {
|
|
517
|
+
if (++cooperativeWork % 65536 === 0)
|
|
518
|
+
yield;
|
|
510
519
|
win.length = 0;
|
|
511
520
|
for (let dy = -ry; dy <= ry; dy++) {
|
|
521
|
+
if (++cooperativeWork % 65536 === 0)
|
|
522
|
+
yield;
|
|
512
523
|
const sy = Math.max(0, Math.min(h - 1, y + dy));
|
|
513
524
|
for (let dx = -rx; dx <= rx; dx++) {
|
|
525
|
+
if (++cooperativeWork % 65536 === 0)
|
|
526
|
+
yield;
|
|
514
527
|
const sx = Math.max(0, Math.min(w - 1, x + dx));
|
|
515
528
|
win.push(img.data[(sy * w + sx) * 4 + c]);
|
|
516
529
|
}
|
|
@@ -552,7 +565,8 @@ function createRoseImage() {
|
|
|
552
565
|
data
|
|
553
566
|
};
|
|
554
567
|
}
|
|
555
|
-
function
|
|
568
|
+
function* applyMagickFloodfillSteps(img, geomStr, targetColor, replacement, fuzz, signal) {
|
|
569
|
+
let cooperativeWork = 0;
|
|
556
570
|
const g = parseMagickGeometry(geomStr);
|
|
557
571
|
const w = img.width;
|
|
558
572
|
const h = img.height;
|
|
@@ -580,6 +594,8 @@ function applyMagickFloodfill(img, geomStr, targetColor, replacement, fuzz) {
|
|
|
580
594
|
queue[tail++] = startIdx;
|
|
581
595
|
visited[startIdx] = 1;
|
|
582
596
|
while (head < tail) {
|
|
597
|
+
if (++cooperativeWork % 65536 === 0)
|
|
598
|
+
yield;
|
|
583
599
|
const cur = queue[head++];
|
|
584
600
|
const off = cur * 4;
|
|
585
601
|
out[off] = replacement.r;
|
|
@@ -595,6 +611,8 @@ function applyMagickFloodfill(img, geomStr, targetColor, replacement, fuzz) {
|
|
|
595
611
|
cy + 1 < h ? cur + w : -1
|
|
596
612
|
];
|
|
597
613
|
for (const nb of neighbors) {
|
|
614
|
+
if (++cooperativeWork % 65536 === 0)
|
|
615
|
+
yield;
|
|
598
616
|
if (nb >= 0 && visited[nb] === 0 && matchesRef(nb)) {
|
|
599
617
|
visited[nb] = 1;
|
|
600
618
|
queue[tail++] = nb;
|
|
@@ -603,7 +621,8 @@ function applyMagickFloodfill(img, geomStr, targetColor, replacement, fuzz) {
|
|
|
603
621
|
}
|
|
604
622
|
return { ...img, data: out, hasAlpha: true };
|
|
605
623
|
}
|
|
606
|
-
function
|
|
624
|
+
function* applyMagickEvaluateSequenceSteps(stack, opRaw, signal) {
|
|
625
|
+
let cooperativeWork = 0;
|
|
607
626
|
if (stack.length === 0) {
|
|
608
627
|
throw new Error("evaluate-sequence requires at least one image");
|
|
609
628
|
}
|
|
@@ -611,25 +630,28 @@ function applyMagickEvaluateSequence(stack, opRaw) {
|
|
|
611
630
|
const base = stack[0];
|
|
612
631
|
const w = base.width;
|
|
613
632
|
const h = base.height;
|
|
614
|
-
const normalized = stack.map(
|
|
615
|
-
(im) => im.width === w && im.height === h ? im : applyMagickResize(im, `${w}x${h}!`, "bilinear")
|
|
616
|
-
);
|
|
633
|
+
const normalized = stack.map((im) => im.width === w && im.height === h ? im : applyMagickResize(im, `${w}x${h}!`, "bilinear"));
|
|
617
634
|
const n = normalized.length;
|
|
618
635
|
const out = new Uint8Array(w * h * 4);
|
|
619
636
|
const op = opRaw.toLowerCase().replace(/[-_]/g, "");
|
|
620
637
|
const vals = new Float64Array(n);
|
|
621
638
|
for (let i = 0; i < out.length; i++) {
|
|
639
|
+
if (++cooperativeWork % 65536 === 0)
|
|
640
|
+
yield;
|
|
622
641
|
if ((i & 3) === 3) {
|
|
623
642
|
out[i] = base.data[i];
|
|
624
643
|
continue;
|
|
625
644
|
}
|
|
626
645
|
for (let k = 0; k < n; k++) {
|
|
646
|
+
if (++cooperativeWork % 65536 === 0)
|
|
647
|
+
yield;
|
|
627
648
|
vals[k] = normalized[k].data[i];
|
|
628
649
|
}
|
|
629
650
|
let res = vals[0];
|
|
630
651
|
if (op === "mean" || op === "average") {
|
|
631
652
|
let s = 0;
|
|
632
|
-
for (let k = 0; k < n; k++)
|
|
653
|
+
for (let k = 0; k < n; k++)
|
|
654
|
+
s += vals[k];
|
|
633
655
|
res = s / n;
|
|
634
656
|
} else if (op === "median") {
|
|
635
657
|
const baseOff = i & ~3;
|
|
@@ -647,33 +669,47 @@ function applyMagickEvaluateSequence(stack, opRaw) {
|
|
|
647
669
|
res = Math.max(...vals);
|
|
648
670
|
} else if (op === "add") {
|
|
649
671
|
let s = 0;
|
|
650
|
-
for (let k = 0; k < n; k++)
|
|
672
|
+
for (let k = 0; k < n; k++)
|
|
673
|
+
s += vals[k];
|
|
651
674
|
res = s;
|
|
652
675
|
} else if (op === "multiply") {
|
|
653
676
|
let p = 1;
|
|
654
|
-
for (let k = 0; k < n; k++)
|
|
677
|
+
for (let k = 0; k < n; k++)
|
|
678
|
+
p *= vals[k] / 255;
|
|
655
679
|
res = p * 255;
|
|
656
680
|
}
|
|
657
681
|
out[i] = clampByteVal(res);
|
|
658
682
|
}
|
|
659
683
|
return { ...base, data: out };
|
|
660
684
|
}
|
|
661
|
-
function
|
|
685
|
+
function* applyMagickCustomConvolveSteps(img, spec, signal) {
|
|
686
|
+
let cooperativeWork = 0;
|
|
662
687
|
const afterColon = spec.includes(":") ? spec.slice(spec.indexOf(":") + 1) : spec;
|
|
663
688
|
const coeffs = afterColon.trim().split(/[\s,]+/).filter((s) => s.length > 0).map(Number).filter((n) => Number.isFinite(n));
|
|
664
|
-
if (coeffs.length === 0)
|
|
689
|
+
if (coeffs.length === 0)
|
|
690
|
+
return img;
|
|
665
691
|
const side = Math.max(1, Math.round(Math.sqrt(coeffs.length)));
|
|
666
692
|
const half = Math.floor(side / 2);
|
|
667
693
|
const w = img.width;
|
|
668
694
|
const h = img.height;
|
|
669
695
|
const out = new Uint8Array(img.data);
|
|
670
696
|
for (let y = 0; y < h; y++) {
|
|
697
|
+
if (++cooperativeWork % 65536 === 0)
|
|
698
|
+
yield;
|
|
671
699
|
for (let x = 0; x < w; x++) {
|
|
700
|
+
if (++cooperativeWork % 65536 === 0)
|
|
701
|
+
yield;
|
|
672
702
|
for (let c = 0; c < 3; c++) {
|
|
703
|
+
if (++cooperativeWork % 65536 === 0)
|
|
704
|
+
yield;
|
|
673
705
|
let sum = 0;
|
|
674
706
|
for (let ky = 0; ky < side; ky++) {
|
|
707
|
+
if (++cooperativeWork % 65536 === 0)
|
|
708
|
+
yield;
|
|
675
709
|
const sy = Math.max(0, Math.min(h - 1, y + ky - half));
|
|
676
710
|
for (let kx = 0; kx < side; kx++) {
|
|
711
|
+
if (++cooperativeWork % 65536 === 0)
|
|
712
|
+
yield;
|
|
677
713
|
const sx = Math.max(0, Math.min(w - 1, x + kx - half));
|
|
678
714
|
const weight = coeffs[ky * side + kx] ?? 0;
|
|
679
715
|
sum += img.data[(sy * w + sx) * 4 + c] * weight;
|
|
@@ -685,51 +721,66 @@ function applyMagickCustomConvolve(img, spec) {
|
|
|
685
721
|
}
|
|
686
722
|
return { ...img, data: out };
|
|
687
723
|
}
|
|
688
|
-
function
|
|
724
|
+
function* applyMagickColorMatrixSteps(img, spec, signal) {
|
|
725
|
+
let cooperativeWork = 0;
|
|
689
726
|
const afterColon = spec.includes(":") ? spec.slice(spec.indexOf(":") + 1) : spec;
|
|
690
727
|
const m = afterColon.trim().split(/[\s,]+/).filter((s) => s.length > 0).map(Number);
|
|
691
|
-
if (m.length < 9)
|
|
728
|
+
if (m.length < 9)
|
|
729
|
+
return img;
|
|
692
730
|
const out = new Uint8Array(img.data);
|
|
693
731
|
const cols = m.length >= 16 ? Math.round(Math.sqrt(m.length)) : 3;
|
|
694
732
|
for (let i = 0; i < out.length; i += 4) {
|
|
733
|
+
if (++cooperativeWork % 65536 === 0)
|
|
734
|
+
yield;
|
|
695
735
|
const r = out[i];
|
|
696
736
|
const g = out[i + 1];
|
|
697
737
|
const b = out[i + 2];
|
|
698
738
|
out[i] = clampByteVal((m[0] ?? 1) * r + (m[1] ?? 0) * g + (m[2] ?? 0) * b);
|
|
699
739
|
out[i + 1] = clampByteVal((m[cols] ?? 0) * r + (m[cols + 1] ?? 1) * g + (m[cols + 2] ?? 0) * b);
|
|
700
|
-
out[i + 2] = clampByteVal(
|
|
701
|
-
(m[cols * 2] ?? 0) * r + (m[cols * 2 + 1] ?? 0) * g + (m[cols * 2 + 2] ?? 1) * b
|
|
702
|
-
);
|
|
740
|
+
out[i + 2] = clampByteVal((m[cols * 2] ?? 0) * r + (m[cols * 2 + 1] ?? 0) * g + (m[cols * 2 + 2] ?? 1) * b);
|
|
703
741
|
}
|
|
704
742
|
return { ...img, data: out };
|
|
705
743
|
}
|
|
706
|
-
function
|
|
744
|
+
function* applyMagickEqualizeSteps(img, signal) {
|
|
745
|
+
let cooperativeWork = 0;
|
|
707
746
|
const out = new Uint8Array(img.data);
|
|
708
747
|
const totalPixels = Math.max(1, img.width * img.height);
|
|
709
748
|
for (let c = 0; c < 3; c++) {
|
|
749
|
+
if (++cooperativeWork % 65536 === 0)
|
|
750
|
+
yield;
|
|
710
751
|
const hist = new Uint32Array(256);
|
|
711
752
|
for (let i = c; i < out.length; i += 4) {
|
|
753
|
+
if (++cooperativeWork % 65536 === 0)
|
|
754
|
+
yield;
|
|
712
755
|
hist[out[i]]++;
|
|
713
756
|
}
|
|
714
757
|
const lut = new Uint8Array(256);
|
|
715
758
|
let cdf = 0;
|
|
716
759
|
let cdfMin = 0;
|
|
717
760
|
for (let v = 0; v < 256; v++) {
|
|
761
|
+
if (++cooperativeWork % 65536 === 0)
|
|
762
|
+
yield;
|
|
718
763
|
cdf += hist[v];
|
|
719
|
-
if (cdfMin === 0 && cdf > 0)
|
|
764
|
+
if (cdfMin === 0 && cdf > 0)
|
|
765
|
+
cdfMin = cdf;
|
|
720
766
|
const denom = Math.max(1, totalPixels - cdfMin);
|
|
721
767
|
lut[v] = clampByteVal((cdf - cdfMin) / denom * 255);
|
|
722
768
|
}
|
|
723
769
|
for (let i = c; i < out.length; i += 4) {
|
|
770
|
+
if (++cooperativeWork % 65536 === 0)
|
|
771
|
+
yield;
|
|
724
772
|
out[i] = lut[out[i]];
|
|
725
773
|
}
|
|
726
774
|
}
|
|
727
775
|
return { ...img, data: out };
|
|
728
776
|
}
|
|
729
|
-
function
|
|
777
|
+
function* applyMagickRemapSteps(img, palImg, dither, signal) {
|
|
778
|
+
let cooperativeWork = 0;
|
|
730
779
|
const palette = [];
|
|
731
780
|
const seen = /* @__PURE__ */ new Set();
|
|
732
781
|
for (let i = 0; i < palImg.data.length; i += 4) {
|
|
782
|
+
if (++cooperativeWork % 65536 === 0)
|
|
783
|
+
yield;
|
|
733
784
|
const r = palImg.data[i];
|
|
734
785
|
const g = palImg.data[i + 1];
|
|
735
786
|
const b = palImg.data[i + 2];
|
|
@@ -737,16 +788,22 @@ function applyMagickRemap(img, palImg, dither) {
|
|
|
737
788
|
if (!seen.has(key)) {
|
|
738
789
|
seen.add(key);
|
|
739
790
|
palette.push({ r, g, b });
|
|
740
|
-
if (palette.length >= 256)
|
|
791
|
+
if (palette.length >= 256)
|
|
792
|
+
break;
|
|
741
793
|
}
|
|
742
794
|
}
|
|
743
|
-
if (palette.length === 0)
|
|
795
|
+
if (palette.length === 0)
|
|
796
|
+
return img;
|
|
744
797
|
const w = img.width;
|
|
745
798
|
const h = img.height;
|
|
746
799
|
const buf = new Float32Array(img.data);
|
|
747
800
|
const out = new Uint8Array(img.data);
|
|
748
801
|
for (let y = 0; y < h; y++) {
|
|
802
|
+
if (++cooperativeWork % 65536 === 0)
|
|
803
|
+
yield;
|
|
749
804
|
for (let x = 0; x < w; x++) {
|
|
805
|
+
if (++cooperativeWork % 65536 === 0)
|
|
806
|
+
yield;
|
|
750
807
|
const idx = (y * w + x) * 4;
|
|
751
808
|
const oldR = Math.max(0, Math.min(255, buf[idx]));
|
|
752
809
|
const oldG = Math.max(0, Math.min(255, buf[idx + 1]));
|
|
@@ -754,6 +811,8 @@ function applyMagickRemap(img, palImg, dither) {
|
|
|
754
811
|
let best = palette[0];
|
|
755
812
|
let bestDist = Infinity;
|
|
756
813
|
for (const p of palette) {
|
|
814
|
+
if (++cooperativeWork % 65536 === 0)
|
|
815
|
+
yield;
|
|
757
816
|
const d = (oldR - p.r) ** 2 + (oldG - p.g) ** 2 + (oldB - p.b) ** 2;
|
|
758
817
|
if (d < bestDist) {
|
|
759
818
|
bestDist = d;
|
|
@@ -768,7 +827,8 @@ function applyMagickRemap(img, palImg, dither) {
|
|
|
768
827
|
const errG = oldG - best.g;
|
|
769
828
|
const errB = oldB - best.b;
|
|
770
829
|
const spread = (nx, ny, wgt) => {
|
|
771
|
-
if (nx < 0 || nx >= w || ny < 0 || ny >= h)
|
|
830
|
+
if (nx < 0 || nx >= w || ny < 0 || ny >= h)
|
|
831
|
+
return;
|
|
772
832
|
const nIdx = (ny * w + nx) * 4;
|
|
773
833
|
buf[nIdx] = buf[nIdx] + errR * wgt;
|
|
774
834
|
buf[nIdx + 1] = buf[nIdx + 1] + errG * wgt;
|
|
@@ -909,7 +969,8 @@ function createCheckerboardImage(width, height) {
|
|
|
909
969
|
data
|
|
910
970
|
};
|
|
911
971
|
}
|
|
912
|
-
function
|
|
972
|
+
function* applyMagickSpliceSteps(img, geomStr, bg, gravity = "northwest", signal) {
|
|
973
|
+
let cooperativeWork = 0;
|
|
913
974
|
const g = parseMagickGeometry(geomStr);
|
|
914
975
|
const sw = Math.max(0, Math.round(g.width ?? 0));
|
|
915
976
|
const sh = Math.max(0, Math.round(g.height ?? 0));
|
|
@@ -922,7 +983,11 @@ function applyMagickSplice(img, geomStr, bg, gravity = "northwest") {
|
|
|
922
983
|
const outH = img.height + sh;
|
|
923
984
|
const out = new Uint8Array(outW * outH * 4);
|
|
924
985
|
for (let y = 0; y < outH; y++) {
|
|
986
|
+
if (++cooperativeWork % 65536 === 0)
|
|
987
|
+
yield;
|
|
925
988
|
for (let x = 0; x < outW; x++) {
|
|
989
|
+
if (++cooperativeWork % 65536 === 0)
|
|
990
|
+
yield;
|
|
926
991
|
const dstIdx = (y * outW + x) * 4;
|
|
927
992
|
if (x >= sx && x < sx + sw || y >= sy && y < sy + sh) {
|
|
928
993
|
out[dstIdx] = bg.r;
|
|
@@ -942,7 +1007,8 @@ function applyMagickSplice(img, geomStr, bg, gravity = "northwest") {
|
|
|
942
1007
|
}
|
|
943
1008
|
return { ...img, width: outW, height: outH, data: out, hasAlpha: true };
|
|
944
1009
|
}
|
|
945
|
-
function
|
|
1010
|
+
function* applyMagickChopSteps(img, geomStr, gravity = "northwest", signal) {
|
|
1011
|
+
let cooperativeWork = 0;
|
|
946
1012
|
const g = parseMagickGeometry(geomStr);
|
|
947
1013
|
const cw = Math.max(0, Math.round(g.width ?? 0));
|
|
948
1014
|
const ch = Math.max(0, Math.round(g.height ?? 0));
|
|
@@ -963,8 +1029,12 @@ function applyMagickChop(img, geomStr, gravity = "northwest") {
|
|
|
963
1029
|
const outH = img.height - choppedH;
|
|
964
1030
|
const out = new Uint8Array(outW * outH * 4);
|
|
965
1031
|
for (let y = 0; y < outH; y++) {
|
|
1032
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1033
|
+
yield;
|
|
966
1034
|
const srcY = y < cy0 ? y : Math.min(img.height - 1, y + choppedH);
|
|
967
1035
|
for (let x = 0; x < outW; x++) {
|
|
1036
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1037
|
+
yield;
|
|
968
1038
|
const srcX = x < cx0 ? x : Math.min(img.width - 1, x + choppedW);
|
|
969
1039
|
const dstIdx = (y * outW + x) * 4;
|
|
970
1040
|
const srcIdx = (srcY * img.width + srcX) * 4;
|
|
@@ -976,7 +1046,8 @@ function applyMagickChop(img, geomStr, gravity = "northwest") {
|
|
|
976
1046
|
}
|
|
977
1047
|
return { ...img, width: outW, height: outH, data: out };
|
|
978
1048
|
}
|
|
979
|
-
function
|
|
1049
|
+
function* applyMagickRollSteps(img, geomStr, signal) {
|
|
1050
|
+
let cooperativeWork = 0;
|
|
980
1051
|
const g = parseMagickGeometry(geomStr);
|
|
981
1052
|
const rx = Math.round(g.x || g.width || 0);
|
|
982
1053
|
const ry = Math.round(g.y || g.height || 0);
|
|
@@ -984,8 +1055,12 @@ function applyMagickRoll(img, geomStr) {
|
|
|
984
1055
|
const h = img.height;
|
|
985
1056
|
const out = new Uint8Array(img.data.length);
|
|
986
1057
|
for (let y = 0; y < h; y++) {
|
|
1058
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1059
|
+
yield;
|
|
987
1060
|
const sy = ((y - ry) % h + h) % h;
|
|
988
1061
|
for (let x = 0; x < w; x++) {
|
|
1062
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1063
|
+
yield;
|
|
989
1064
|
const sx = ((x - rx) % w + w) % w;
|
|
990
1065
|
const dstIdx = (y * w + x) * 4;
|
|
991
1066
|
const srcIdx = (sy * w + sx) * 4;
|
|
@@ -997,15 +1072,21 @@ function applyMagickRoll(img, geomStr) {
|
|
|
997
1072
|
}
|
|
998
1073
|
return { ...img, data: out };
|
|
999
1074
|
}
|
|
1000
|
-
function
|
|
1075
|
+
function* applyMagickMorphSteps(stack, countRaw, signal) {
|
|
1076
|
+
let cooperativeWork = 0;
|
|
1001
1077
|
const count = Math.max(0, Math.round(countRaw));
|
|
1002
|
-
if (stack.length < 2 || count === 0)
|
|
1078
|
+
if (stack.length < 2 || count === 0)
|
|
1079
|
+
return [...stack];
|
|
1003
1080
|
const out = [];
|
|
1004
1081
|
for (let idx = 0; idx < stack.length - 1; idx++) {
|
|
1082
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1083
|
+
yield;
|
|
1005
1084
|
const a = stack[idx];
|
|
1006
1085
|
const b = stack[idx + 1];
|
|
1007
1086
|
out.push(a);
|
|
1008
1087
|
for (let step = 1; step <= count; step++) {
|
|
1088
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1089
|
+
yield;
|
|
1009
1090
|
const t = step / (count + 1);
|
|
1010
1091
|
const w = Math.max(1, Math.round(a.width * (1 - t) + b.width * t));
|
|
1011
1092
|
const h = Math.max(1, Math.round(a.height * (1 - t) + b.height * t));
|
|
@@ -1013,6 +1094,8 @@ function applyMagickMorph(stack, countRaw) {
|
|
|
1013
1094
|
const rb = b.width === w && b.height === h ? b : applyMagickResize(b, `${w}x${h}!`, "bilinear");
|
|
1014
1095
|
const data = new Uint8Array(w * h * 4);
|
|
1015
1096
|
for (let p = 0; p < data.length; p++) {
|
|
1097
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1098
|
+
yield;
|
|
1016
1099
|
data[p] = clampByteVal(ra.data[p] * (1 - t) + rb.data[p] * t);
|
|
1017
1100
|
}
|
|
1018
1101
|
out.push({ ...ra, width: w, height: h, data });
|
|
@@ -1060,9 +1143,12 @@ function clampByteVal(n) {
|
|
|
1060
1143
|
if (!Number.isFinite(n)) return 0;
|
|
1061
1144
|
return Math.max(0, Math.min(255, Math.round(n)));
|
|
1062
1145
|
}
|
|
1063
|
-
function
|
|
1146
|
+
function* applyMagickOpaqueSteps(img, target, replacement, fuzz, invert, signal) {
|
|
1147
|
+
let cooperativeWork = 0;
|
|
1064
1148
|
const out = new Uint8Array(img.data);
|
|
1065
1149
|
for (let i = 0; i < out.length; i += 4) {
|
|
1150
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1151
|
+
yield;
|
|
1066
1152
|
const dr = Math.abs(out[i] - target.r);
|
|
1067
1153
|
const dg = Math.abs(out[i + 1] - target.g);
|
|
1068
1154
|
const db = Math.abs(out[i + 2] - target.b);
|
|
@@ -1076,9 +1162,12 @@ function applyMagickOpaque(img, target, replacement, fuzz, invert) {
|
|
|
1076
1162
|
}
|
|
1077
1163
|
return { ...img, data: out, hasAlpha: true };
|
|
1078
1164
|
}
|
|
1079
|
-
function
|
|
1165
|
+
function* applyMagickTransparentSteps(img, target, fuzz, invert, signal) {
|
|
1166
|
+
let cooperativeWork = 0;
|
|
1080
1167
|
const out = new Uint8Array(img.data);
|
|
1081
1168
|
for (let i = 0; i < out.length; i += 4) {
|
|
1169
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1170
|
+
yield;
|
|
1082
1171
|
const dr = Math.abs(out[i] - target.r);
|
|
1083
1172
|
const dg = Math.abs(out[i + 1] - target.g);
|
|
1084
1173
|
const db = Math.abs(out[i + 2] - target.b);
|
|
@@ -1089,7 +1178,8 @@ function applyMagickTransparent(img, target, fuzz, invert) {
|
|
|
1089
1178
|
}
|
|
1090
1179
|
return { ...img, data: out, hasAlpha: true };
|
|
1091
1180
|
}
|
|
1092
|
-
function
|
|
1181
|
+
function* applyMagickEvaluateSteps(img, opRaw, valStr, channels, signal) {
|
|
1182
|
+
let cooperativeWork = 0;
|
|
1093
1183
|
const op = opRaw.toLowerCase().replace(/[-_]/g, "");
|
|
1094
1184
|
const isPct = valStr.trim().endsWith("%");
|
|
1095
1185
|
const rawNum = parseFloat(valStr);
|
|
@@ -1098,8 +1188,13 @@ function applyMagickEvaluate(img, opRaw, valStr, channels) {
|
|
|
1098
1188
|
const out = new Uint8Array(img.data);
|
|
1099
1189
|
const mask = [channels.r, channels.g, channels.b, channels.a];
|
|
1100
1190
|
for (let i = 0; i < out.length; i += 4) {
|
|
1191
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1192
|
+
yield;
|
|
1101
1193
|
for (let c = 0; c < 4; c++) {
|
|
1102
|
-
if (
|
|
1194
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1195
|
+
yield;
|
|
1196
|
+
if (!mask[c])
|
|
1197
|
+
continue;
|
|
1103
1198
|
const cur = out[i + c];
|
|
1104
1199
|
let next = cur;
|
|
1105
1200
|
switch (op) {
|
|
@@ -1177,14 +1272,20 @@ function applyMagickEvaluate(img, opRaw, valStr, channels) {
|
|
|
1177
1272
|
}
|
|
1178
1273
|
return { ...img, data: out };
|
|
1179
1274
|
}
|
|
1180
|
-
function
|
|
1275
|
+
function* applyMagickFunctionSteps(img, funcRaw, paramsRaw, channels, signal) {
|
|
1276
|
+
let cooperativeWork = 0;
|
|
1181
1277
|
const fn = funcRaw.toLowerCase();
|
|
1182
1278
|
const params = paramsRaw.split(",").map((s) => Number(s.trim()));
|
|
1183
1279
|
const out = new Uint8Array(img.data);
|
|
1184
1280
|
const mask = [channels.r, channels.g, channels.b, channels.a];
|
|
1185
1281
|
for (let i = 0; i < out.length; i += 4) {
|
|
1282
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1283
|
+
yield;
|
|
1186
1284
|
for (let c = 0; c < 4; c++) {
|
|
1187
|
-
if (
|
|
1285
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1286
|
+
yield;
|
|
1287
|
+
if (!mask[c])
|
|
1288
|
+
continue;
|
|
1188
1289
|
const x = out[i + c] / 255;
|
|
1189
1290
|
let y = x;
|
|
1190
1291
|
if (fn === "polynomial") {
|
|
@@ -1214,14 +1315,20 @@ function applyMagickFunction(img, funcRaw, paramsRaw, channels) {
|
|
|
1214
1315
|
}
|
|
1215
1316
|
return { ...img, data: out };
|
|
1216
1317
|
}
|
|
1217
|
-
function
|
|
1318
|
+
function* applyMagickClutSteps(baseImg, lutImg, channels, signal) {
|
|
1319
|
+
let cooperativeWork = 0;
|
|
1218
1320
|
const out = new Uint8Array(baseImg.data);
|
|
1219
1321
|
const horiz = lutImg.width >= lutImg.height;
|
|
1220
1322
|
const len = Math.max(1, horiz ? lutImg.width : lutImg.height);
|
|
1221
1323
|
const mask = [channels.r, channels.g, channels.b, channels.a];
|
|
1222
1324
|
for (let i = 0; i < out.length; i += 4) {
|
|
1325
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1326
|
+
yield;
|
|
1223
1327
|
for (let c = 0; c < 4; c++) {
|
|
1224
|
-
if (
|
|
1328
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1329
|
+
yield;
|
|
1330
|
+
if (!mask[c])
|
|
1331
|
+
continue;
|
|
1225
1332
|
const t = out[i + c] / 255;
|
|
1226
1333
|
const pos = Math.max(0, Math.min(len - 1, Math.round(t * (len - 1))));
|
|
1227
1334
|
const lx = horiz ? pos : 0;
|
|
@@ -1614,17 +1721,25 @@ function compileSingleFxExpr(src) {
|
|
|
1614
1721
|
}
|
|
1615
1722
|
return parseTernary();
|
|
1616
1723
|
}
|
|
1617
|
-
function
|
|
1724
|
+
function* applyMagickFxSteps(stack, exprStr, channels, signal) {
|
|
1725
|
+
let cooperativeWork = 0;
|
|
1618
1726
|
const base = stack[0];
|
|
1619
1727
|
const out = new Uint8Array(base.data);
|
|
1620
1728
|
const evalFn = compileFxExpression(exprStr);
|
|
1621
1729
|
const mask = [channels.r, channels.g, channels.b, channels.a];
|
|
1622
1730
|
const vars = /* @__PURE__ */ new Map();
|
|
1623
1731
|
for (let y = 0; y < base.height; y++) {
|
|
1732
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1733
|
+
yield;
|
|
1624
1734
|
for (let x = 0; x < base.width; x++) {
|
|
1735
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1736
|
+
yield;
|
|
1625
1737
|
const idx = (y * base.width + x) * 4;
|
|
1626
1738
|
for (let c = 0; c < 4; c++) {
|
|
1627
|
-
if (
|
|
1739
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1740
|
+
yield;
|
|
1741
|
+
if (!mask[c])
|
|
1742
|
+
continue;
|
|
1628
1743
|
vars.clear();
|
|
1629
1744
|
const val = evalFn({
|
|
1630
1745
|
stack,
|
|
@@ -1665,7 +1780,8 @@ function sampleBilinear(img, sx, sy, bg, out, outOff) {
|
|
|
1665
1780
|
out[outOff + c] = clampByteVal(v0 * (1 - fy) + v1 * fy);
|
|
1666
1781
|
}
|
|
1667
1782
|
}
|
|
1668
|
-
function
|
|
1783
|
+
function* applyMagickShearSteps(img, geomStr, bg, signal) {
|
|
1784
|
+
let cooperativeWork = 0;
|
|
1669
1785
|
const g = parseMagickGeometry(geomStr);
|
|
1670
1786
|
const degX = g.width ?? 0;
|
|
1671
1787
|
const degY = g.height ?? 0;
|
|
@@ -1680,7 +1796,11 @@ function applyMagickShear(img, geomStr, bg) {
|
|
|
1680
1796
|
const cyDst = (outH - 1) / 2;
|
|
1681
1797
|
const det = 1 - tanX * tanY || 1;
|
|
1682
1798
|
for (let y = 0; y < outH; y++) {
|
|
1799
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1800
|
+
yield;
|
|
1683
1801
|
for (let x = 0; x < outW; x++) {
|
|
1802
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1803
|
+
yield;
|
|
1684
1804
|
const dx = x - cxDst;
|
|
1685
1805
|
const dy = y - cyDst;
|
|
1686
1806
|
const sx = cxSrc + (dx - tanX * dy) / det;
|
|
@@ -1714,7 +1834,8 @@ function solveLinearSystem(A, b) {
|
|
|
1714
1834
|
}
|
|
1715
1835
|
return M.map((row) => row[n]);
|
|
1716
1836
|
}
|
|
1717
|
-
function
|
|
1837
|
+
function* applyMagickDistortSteps(img, methodRaw, argsRaw, bg, signal) {
|
|
1838
|
+
let cooperativeWork = 0;
|
|
1718
1839
|
const method = methodRaw.toLowerCase().replace(/[-_]/g, "");
|
|
1719
1840
|
const nums = argsRaw.trim().split(/[\s,]+/).filter((s) => s.length > 0).map(Number);
|
|
1720
1841
|
const w = img.width;
|
|
@@ -1768,7 +1889,11 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1768
1889
|
const cosA = Math.cos(rad);
|
|
1769
1890
|
const sinA = Math.sin(rad);
|
|
1770
1891
|
for (let y = 0; y < h; y++) {
|
|
1892
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1893
|
+
yield;
|
|
1771
1894
|
for (let x = 0; x < w; x++) {
|
|
1895
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1896
|
+
yield;
|
|
1772
1897
|
const dx = x - nx;
|
|
1773
1898
|
const dy = y - ny;
|
|
1774
1899
|
const sx = cx + (dx * cosA + dy * sinA) / scaleX;
|
|
@@ -1786,6 +1911,8 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1786
1911
|
const A = [];
|
|
1787
1912
|
const bVec = [];
|
|
1788
1913
|
for (let p = 0; p < 4; p++) {
|
|
1914
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1915
|
+
yield;
|
|
1789
1916
|
const sx = nums[p * 4];
|
|
1790
1917
|
const sy = nums[p * 4 + 1];
|
|
1791
1918
|
const dx = nums[p * 4 + 2];
|
|
@@ -1802,7 +1929,11 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1802
1929
|
}
|
|
1803
1930
|
const [c0, c1, c2, c3, c4, c5, c6, c7] = hCoeff;
|
|
1804
1931
|
for (let y = 0; y < h; y++) {
|
|
1932
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1933
|
+
yield;
|
|
1805
1934
|
for (let x = 0; x < w; x++) {
|
|
1935
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1936
|
+
yield;
|
|
1806
1937
|
const denom = c6 * x + c7 * y + 1 || 1e-9;
|
|
1807
1938
|
const sx = (c0 * x + c1 * y + c2) / denom;
|
|
1808
1939
|
const sy = (c3 * x + c4 * y + c5) / denom;
|
|
@@ -1816,6 +1947,8 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1816
1947
|
const bx = [];
|
|
1817
1948
|
const by = [];
|
|
1818
1949
|
for (let p = 0; p < 3; p++) {
|
|
1950
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1951
|
+
yield;
|
|
1819
1952
|
const sx = nums[p * 4];
|
|
1820
1953
|
const sy = nums[p * 4 + 1];
|
|
1821
1954
|
const dx = nums[p * 4 + 2];
|
|
@@ -1827,7 +1960,11 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1827
1960
|
const rx = solveLinearSystem(A, bx);
|
|
1828
1961
|
const ry = solveLinearSystem(A, by);
|
|
1829
1962
|
for (let y = 0; y < h; y++) {
|
|
1963
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1964
|
+
yield;
|
|
1830
1965
|
for (let x = 0; x < w; x++) {
|
|
1966
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1967
|
+
yield;
|
|
1831
1968
|
const sx = rx[0] * x + rx[1] * y + rx[2];
|
|
1832
1969
|
const sy = ry[0] * x + ry[1] * y + ry[2];
|
|
1833
1970
|
sampleBilinear(img, sx, sy, bg, out, (y * w + x) * 4);
|
|
@@ -1844,7 +1981,11 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1844
1981
|
const cy = nums[5] ?? (h - 1) / 2;
|
|
1845
1982
|
const rNorm = Math.min(w, h) / 2;
|
|
1846
1983
|
for (let y = 0; y < h; y++) {
|
|
1984
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1985
|
+
yield;
|
|
1847
1986
|
for (let x = 0; x < w; x++) {
|
|
1987
|
+
if (++cooperativeWork % 65536 === 0)
|
|
1988
|
+
yield;
|
|
1848
1989
|
const dx = (x - cx) / rNorm;
|
|
1849
1990
|
const dy = (y - cy) / rNorm;
|
|
1850
1991
|
const r = Math.hypot(dx, dy);
|
|
@@ -1858,7 +1999,8 @@ function applyMagickDistort(img, methodRaw, argsRaw, bg) {
|
|
|
1858
1999
|
}
|
|
1859
2000
|
return img;
|
|
1860
2001
|
}
|
|
1861
|
-
function
|
|
2002
|
+
function* applyMagickSwirlSteps(img, degrees, bg, signal) {
|
|
2003
|
+
let cooperativeWork = 0;
|
|
1862
2004
|
const w = img.width;
|
|
1863
2005
|
const h = img.height;
|
|
1864
2006
|
const out = new Uint8Array(w * h * 4);
|
|
@@ -1867,7 +2009,11 @@ function applyMagickSwirl(img, degrees, bg) {
|
|
|
1867
2009
|
const maxR = Math.max(cx, cy, 1);
|
|
1868
2010
|
const radTotal = degrees * Math.PI / 180;
|
|
1869
2011
|
for (let y = 0; y < h; y++) {
|
|
2012
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2013
|
+
yield;
|
|
1870
2014
|
for (let x = 0; x < w; x++) {
|
|
2015
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2016
|
+
yield;
|
|
1871
2017
|
const dx = x - cx;
|
|
1872
2018
|
const dy = y - cy;
|
|
1873
2019
|
const r = Math.hypot(dx, dy);
|
|
@@ -1886,7 +2032,8 @@ function applyMagickSwirl(img, degrees, bg) {
|
|
|
1886
2032
|
}
|
|
1887
2033
|
return { ...img, data: out };
|
|
1888
2034
|
}
|
|
1889
|
-
function
|
|
2035
|
+
function* applyMagickImplodeSteps(img, amount, bg, signal) {
|
|
2036
|
+
let cooperativeWork = 0;
|
|
1890
2037
|
const w = img.width;
|
|
1891
2038
|
const h = img.height;
|
|
1892
2039
|
const out = new Uint8Array(w * h * 4);
|
|
@@ -1896,7 +2043,11 @@ function applyMagickImplode(img, amount, bg) {
|
|
|
1896
2043
|
const clamped = Math.max(-0.95, Math.min(0.95, amount));
|
|
1897
2044
|
const exp = 1 / (1 - clamped);
|
|
1898
2045
|
for (let y = 0; y < h; y++) {
|
|
2046
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2047
|
+
yield;
|
|
1899
2048
|
for (let x = 0; x < w; x++) {
|
|
2049
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2050
|
+
yield;
|
|
1900
2051
|
const dx = x - cx;
|
|
1901
2052
|
const dy = y - cy;
|
|
1902
2053
|
const r = Math.hypot(dx, dy);
|
|
@@ -1911,7 +2062,8 @@ function applyMagickImplode(img, amount, bg) {
|
|
|
1911
2062
|
}
|
|
1912
2063
|
return { ...img, data: out };
|
|
1913
2064
|
}
|
|
1914
|
-
function
|
|
2065
|
+
function* applyMagickWaveSteps(img, geomStr, bg, signal) {
|
|
2066
|
+
let cooperativeWork = 0;
|
|
1915
2067
|
const g = parseMagickGeometry(geomStr);
|
|
1916
2068
|
const amp = g.width ?? 5;
|
|
1917
2069
|
const waveLen = Math.max(1, g.height ?? 50);
|
|
@@ -1921,14 +2073,19 @@ function applyMagickWave(img, geomStr, bg) {
|
|
|
1921
2073
|
const out = new Uint8Array(outW * outH * 4);
|
|
1922
2074
|
const yPad = Math.abs(amp);
|
|
1923
2075
|
for (let y = 0; y < outH; y++) {
|
|
2076
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2077
|
+
yield;
|
|
1924
2078
|
for (let x = 0; x < outW; x++) {
|
|
2079
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2080
|
+
yield;
|
|
1925
2081
|
const sy = y - yPad - amp * Math.sin(2 * Math.PI * x / waveLen);
|
|
1926
2082
|
sampleBilinear(img, x, sy, bg, out, (y * outW + x) * 4);
|
|
1927
2083
|
}
|
|
1928
2084
|
}
|
|
1929
2085
|
return { ...img, width: outW, height: outH, data: out, hasAlpha: true };
|
|
1930
2086
|
}
|
|
1931
|
-
function
|
|
2087
|
+
function* applyMagickShadowSteps(img, geomStr, shadowColor, signal) {
|
|
2088
|
+
let cooperativeWork = 0;
|
|
1932
2089
|
const g = parseMagickGeometry(geomStr);
|
|
1933
2090
|
const opacity = Math.max(0, Math.min(100, g.width ?? 80)) / 100;
|
|
1934
2091
|
const sigma = Math.max(0.5, g.height ?? 3);
|
|
@@ -1939,10 +2096,15 @@ function applyMagickShadow(img, geomStr, shadowColor) {
|
|
|
1939
2096
|
const offX = pad + Math.round(g.x);
|
|
1940
2097
|
const offY = pad + Math.round(g.y);
|
|
1941
2098
|
for (let y = 0; y < img.height; y++) {
|
|
2099
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2100
|
+
yield;
|
|
1942
2101
|
for (let x = 0; x < img.width; x++) {
|
|
2102
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2103
|
+
yield;
|
|
1943
2104
|
const dx = x + offX;
|
|
1944
2105
|
const dy = y + offY;
|
|
1945
|
-
if (dx < 0 || dy < 0 || dx >= outW || dy >= outH)
|
|
2106
|
+
if (dx < 0 || dy < 0 || dx >= outW || dy >= outH)
|
|
2107
|
+
continue;
|
|
1946
2108
|
const srcA = img.data[(y * img.width + x) * 4 + 3];
|
|
1947
2109
|
const dstIdx = (dy * outW + dx) * 4;
|
|
1948
2110
|
data[dstIdx] = shadowColor.r;
|
|
@@ -1960,14 +2122,19 @@ function applyMagickShadow(img, geomStr, shadowColor) {
|
|
|
1960
2122
|
};
|
|
1961
2123
|
return blurImage(shadowBase, sigma);
|
|
1962
2124
|
}
|
|
1963
|
-
function
|
|
2125
|
+
function* applyMagickVignetteSteps(img, _geomStr, bg, signal) {
|
|
2126
|
+
let cooperativeWork = 0;
|
|
1964
2127
|
const w = img.width;
|
|
1965
2128
|
const h = img.height;
|
|
1966
2129
|
const out = new Uint8Array(img.data);
|
|
1967
2130
|
const cx = (w - 1) / 2;
|
|
1968
2131
|
const cy = (h - 1) / 2;
|
|
1969
2132
|
for (let y = 0; y < h; y++) {
|
|
2133
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2134
|
+
yield;
|
|
1970
2135
|
for (let x = 0; x < w; x++) {
|
|
2136
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2137
|
+
yield;
|
|
1971
2138
|
const nx = (x - cx) / Math.max(1, cx);
|
|
1972
2139
|
const ny = (y - cy) / Math.max(1, cy);
|
|
1973
2140
|
const d = Math.hypot(nx, ny);
|
|
@@ -1980,11 +2147,14 @@ function applyMagickVignette(img, _geomStr, bg) {
|
|
|
1980
2147
|
}
|
|
1981
2148
|
return { ...img, data: out };
|
|
1982
2149
|
}
|
|
1983
|
-
function
|
|
2150
|
+
function* applyMagickSepiaToneSteps(img, threshStr, signal) {
|
|
2151
|
+
let cooperativeWork = 0;
|
|
1984
2152
|
const raw = parseFloat(threshStr);
|
|
1985
2153
|
const strength = Math.max(0, Math.min(1, (threshStr.endsWith("%") ? raw : raw / 255) / 100 || 0.8));
|
|
1986
2154
|
const out = new Uint8Array(img.data);
|
|
1987
2155
|
for (let i = 0; i < out.length; i += 4) {
|
|
2156
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2157
|
+
yield;
|
|
1988
2158
|
const r = out[i];
|
|
1989
2159
|
const g = out[i + 1];
|
|
1990
2160
|
const b = out[i + 2];
|
|
@@ -1997,40 +2167,60 @@ function applyMagickSepiaTone(img, threshStr) {
|
|
|
1997
2167
|
}
|
|
1998
2168
|
return { ...img, data: out };
|
|
1999
2169
|
}
|
|
2000
|
-
function
|
|
2170
|
+
function* applyMagickSolarizeSteps(img, threshStr, signal) {
|
|
2171
|
+
let cooperativeWork = 0;
|
|
2001
2172
|
const raw = parseFloat(threshStr);
|
|
2002
2173
|
const thresh = threshStr.endsWith("%") ? raw / 100 * 255 : raw;
|
|
2003
2174
|
const out = new Uint8Array(img.data);
|
|
2004
2175
|
for (let i = 0; i < out.length; i += 4) {
|
|
2005
|
-
if (
|
|
2006
|
-
|
|
2007
|
-
if (out[i
|
|
2176
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2177
|
+
yield;
|
|
2178
|
+
if (out[i] > thresh)
|
|
2179
|
+
out[i] = 255 - out[i];
|
|
2180
|
+
if (out[i + 1] > thresh)
|
|
2181
|
+
out[i + 1] = 255 - out[i + 1];
|
|
2182
|
+
if (out[i + 2] > thresh)
|
|
2183
|
+
out[i + 2] = 255 - out[i + 2];
|
|
2008
2184
|
}
|
|
2009
2185
|
return { ...img, data: out };
|
|
2010
2186
|
}
|
|
2011
|
-
function
|
|
2187
|
+
function* applyMagickPosterizeSteps(img, levelsRaw, signal) {
|
|
2188
|
+
let cooperativeWork = 0;
|
|
2012
2189
|
const levels = Math.max(2, Math.min(256, Math.round(levelsRaw)));
|
|
2013
2190
|
const step = 255 / (levels - 1);
|
|
2014
2191
|
const out = new Uint8Array(img.data);
|
|
2015
2192
|
for (let i = 0; i < out.length; i += 4) {
|
|
2193
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2194
|
+
yield;
|
|
2016
2195
|
out[i] = clampByteVal(Math.round(out[i] / 255 * (levels - 1)) * step);
|
|
2017
2196
|
out[i + 1] = clampByteVal(Math.round(out[i + 1] / 255 * (levels - 1)) * step);
|
|
2018
2197
|
out[i + 2] = clampByteVal(Math.round(out[i + 2] / 255 * (levels - 1)) * step);
|
|
2019
2198
|
}
|
|
2020
2199
|
return { ...img, data: out };
|
|
2021
2200
|
}
|
|
2022
|
-
function
|
|
2201
|
+
function* applyMagickConvolve3x3Steps(img, kernel, bias = 0, signal) {
|
|
2202
|
+
let cooperativeWork = 0;
|
|
2023
2203
|
const w = img.width;
|
|
2024
2204
|
const h = img.height;
|
|
2025
2205
|
const out = new Uint8Array(img.data);
|
|
2026
2206
|
for (let y = 0; y < h; y++) {
|
|
2207
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2208
|
+
yield;
|
|
2027
2209
|
for (let x = 0; x < w; x++) {
|
|
2210
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2211
|
+
yield;
|
|
2028
2212
|
for (let c = 0; c < 3; c++) {
|
|
2213
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2214
|
+
yield;
|
|
2029
2215
|
let sum = bias;
|
|
2030
2216
|
let kIdx = 0;
|
|
2031
2217
|
for (let ky = -1; ky <= 1; ky++) {
|
|
2218
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2219
|
+
yield;
|
|
2032
2220
|
const sy = Math.max(0, Math.min(h - 1, y + ky));
|
|
2033
2221
|
for (let kx = -1; kx <= 1; kx++) {
|
|
2222
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2223
|
+
yield;
|
|
2034
2224
|
const sx = Math.max(0, Math.min(w - 1, x + kx));
|
|
2035
2225
|
sum += img.data[(sy * w + sx) * 4 + c] * kernel[kIdx++];
|
|
2036
2226
|
}
|
|
@@ -2175,7 +2365,8 @@ function parseCompose(raw) {
|
|
|
2175
2365
|
return "over";
|
|
2176
2366
|
}
|
|
2177
2367
|
}
|
|
2178
|
-
function
|
|
2368
|
+
function* applyMagickCompositeLayerSteps(dst, src, modeRaw, left, top, composeArgs, signal) {
|
|
2369
|
+
let cooperativeWork = 0;
|
|
2179
2370
|
const norm = modeRaw.toLowerCase().replace(/[-_\s]/g, "");
|
|
2180
2371
|
const out = new Uint8Array(dst.data);
|
|
2181
2372
|
const dw = dst.width;
|
|
@@ -2183,11 +2374,17 @@ function applyMagickCompositeLayer(dst, src, modeRaw, left, top, composeArgs) {
|
|
|
2183
2374
|
const sw = src.width;
|
|
2184
2375
|
const sh = src.height;
|
|
2185
2376
|
for (let sy = 0; sy < sh; sy++) {
|
|
2377
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2378
|
+
yield;
|
|
2186
2379
|
const dy = top + sy;
|
|
2187
|
-
if (dy < 0 || dy >= dh)
|
|
2380
|
+
if (dy < 0 || dy >= dh)
|
|
2381
|
+
continue;
|
|
2188
2382
|
for (let sx = 0; sx < sw; sx++) {
|
|
2383
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2384
|
+
yield;
|
|
2189
2385
|
const dx = left + sx;
|
|
2190
|
-
if (dx < 0 || dx >= dw)
|
|
2386
|
+
if (dx < 0 || dx >= dw)
|
|
2387
|
+
continue;
|
|
2191
2388
|
const sIdx = (sy * sw + sx) * 4;
|
|
2192
2389
|
const dIdx = (dy * dw + dx) * 4;
|
|
2193
2390
|
const sr = src.data[sIdx];
|
|
@@ -2329,6 +2526,8 @@ function applyMagickCompositeLayer(dst, src, modeRaw, left, top, composeArgs) {
|
|
|
2329
2526
|
const sChan = [sr / 255, sg / 255, sb / 255];
|
|
2330
2527
|
const dChan = [dr / 255, dg / 255, db / 255];
|
|
2331
2528
|
for (let c = 0; c < 3; c++) {
|
|
2529
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2530
|
+
yield;
|
|
2332
2531
|
const sc = sChan[c];
|
|
2333
2532
|
const dc = dChan[c];
|
|
2334
2533
|
if (norm === "darken") {
|
|
@@ -2342,9 +2541,12 @@ function applyMagickCompositeLayer(dst, src, modeRaw, left, top, composeArgs) {
|
|
|
2342
2541
|
out[dIdx + c] = clampByteVal(comp * 255);
|
|
2343
2542
|
} else {
|
|
2344
2543
|
let f = 0;
|
|
2345
|
-
if (norm === "multiply")
|
|
2346
|
-
|
|
2347
|
-
else
|
|
2544
|
+
if (norm === "multiply")
|
|
2545
|
+
f = sc * dc;
|
|
2546
|
+
else if (norm === "screen")
|
|
2547
|
+
f = sc + dc - sc * dc;
|
|
2548
|
+
else
|
|
2549
|
+
f = dc <= 0.5 ? 2 * sc * dc : 1 - 2 * (1 - sc) * (1 - dc);
|
|
2348
2550
|
const comp = f * sa * da + sc * sa * (1 - da) + dc * da * (1 - sa);
|
|
2349
2551
|
const unpremul = gamma > 1e-6 && norm === "overlay" ? comp / gamma : comp;
|
|
2350
2552
|
out[dIdx + c] = clampByteVal(unpremul * 255);
|
|
@@ -2365,7 +2567,8 @@ function applyMagickCompositeLayer(dst, src, modeRaw, left, top, composeArgs) {
|
|
|
2365
2567
|
const sy0 = Math.max(0, -oy);
|
|
2366
2568
|
const sx1 = Math.min(src.width, dst.width - ox);
|
|
2367
2569
|
const sy1 = Math.min(src.height, dst.height - oy);
|
|
2368
|
-
if (sx1 <= sx0 || sy1 <= sy0)
|
|
2570
|
+
if (sx1 <= sx0 || sy1 <= sy0)
|
|
2571
|
+
return dst;
|
|
2369
2572
|
const clipped = extractImage(src, { left: sx0, top: sy0, width: sx1 - sx0, height: sy1 - sy0 });
|
|
2370
2573
|
return compositeImage(dst, [rgbaToCompositeLayer(clipped, Math.max(0, ox), Math.max(0, oy), parseCompose(modeRaw))]);
|
|
2371
2574
|
}
|
|
@@ -2537,7 +2740,8 @@ function applyMagickCropToStack(img, geomStr, gravity) {
|
|
|
2537
2740
|
})
|
|
2538
2741
|
];
|
|
2539
2742
|
}
|
|
2540
|
-
function
|
|
2743
|
+
function* applyMagickExtentSteps(img, geomStr, state, signal) {
|
|
2744
|
+
yield;
|
|
2541
2745
|
const g = parseMagickGeometry(geomStr);
|
|
2542
2746
|
const targetW = Math.max(1, Math.round(g.width ?? img.width));
|
|
2543
2747
|
const targetH = Math.max(1, Math.round(g.height ?? img.height));
|
|
@@ -2562,7 +2766,9 @@ function applyMagickExtent(img, geomStr, state) {
|
|
|
2562
2766
|
});
|
|
2563
2767
|
return compositeImage(canvas, [rgbaToCompositeLayer(subImg, dstX0, dstY0, "over")]);
|
|
2564
2768
|
}
|
|
2565
|
-
function
|
|
2769
|
+
function* applyMagickDrawSteps(img, drawCmd, state, signal) {
|
|
2770
|
+
yield;
|
|
2771
|
+
let cooperativeWork = 0;
|
|
2566
2772
|
const svgElements = [];
|
|
2567
2773
|
let fill = rgbaToCss(state.fill);
|
|
2568
2774
|
let stroke = rgbaToCss(state.stroke);
|
|
@@ -2571,12 +2777,17 @@ function applyMagickDraw(img, drawCmd, state) {
|
|
|
2571
2777
|
const tokens = [];
|
|
2572
2778
|
let m;
|
|
2573
2779
|
while ((m = tokenRe.exec(drawCmd)) !== null) {
|
|
2574
|
-
if (
|
|
2780
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2781
|
+
yield;
|
|
2782
|
+
if (m[0] === ",")
|
|
2783
|
+
continue;
|
|
2575
2784
|
tokens.push(m[1] ?? m[2] ?? m[3] ?? "");
|
|
2576
2785
|
}
|
|
2577
2786
|
let i = 0;
|
|
2578
2787
|
const num = () => Number(tokens[i++] ?? 0);
|
|
2579
2788
|
while (i < tokens.length) {
|
|
2789
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2790
|
+
yield;
|
|
2580
2791
|
const cmd = tokens[i++].toLowerCase();
|
|
2581
2792
|
if (cmd === "fill") {
|
|
2582
2793
|
fill = rgbaToCss(parseColor2(tokens[i++] ?? "#000000"));
|
|
@@ -2594,14 +2805,10 @@ function applyMagickDraw(img, drawCmd, state) {
|
|
|
2594
2805
|
const rw = Math.max(1, Math.abs(x1 - x0) + 1);
|
|
2595
2806
|
const rh = Math.max(1, Math.abs(y1 - y0) + 1);
|
|
2596
2807
|
if (fill !== "none") {
|
|
2597
|
-
svgElements.push(
|
|
2598
|
-
`<rect x="${rx}" y="${ry}" width="${rw}" height="${rh}" fill="${fill}"/>`
|
|
2599
|
-
);
|
|
2808
|
+
svgElements.push(`<rect x="${rx}" y="${ry}" width="${rw}" height="${rh}" fill="${fill}"/>`);
|
|
2600
2809
|
}
|
|
2601
2810
|
if (stroke !== "none" && strokeWidth > 0) {
|
|
2602
|
-
svgElements.push(
|
|
2603
|
-
`<polygon points="${rx},${ry} ${rx + rw - 1},${ry} ${rx + rw - 1},${ry + rh - 1} ${rx},${ry + rh - 1}" fill="none" stroke="${stroke}" stroke-width="${strokeWidth}"/>`
|
|
2604
|
-
);
|
|
2811
|
+
svgElements.push(`<polygon points="${rx},${ry} ${rx + rw - 1},${ry} ${rx + rw - 1},${ry + rh - 1} ${rx},${ry + rh - 1}" fill="none" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
2605
2812
|
}
|
|
2606
2813
|
} else if (cmd === "roundrectangle") {
|
|
2607
2814
|
const x0 = num();
|
|
@@ -2615,14 +2822,10 @@ function applyMagickDraw(img, drawCmd, state) {
|
|
|
2615
2822
|
const rw = Math.max(1, Math.abs(x1 - x0) + 1);
|
|
2616
2823
|
const rh = Math.max(1, Math.abs(y1 - y0) + 1);
|
|
2617
2824
|
if (fill !== "none") {
|
|
2618
|
-
svgElements.push(
|
|
2619
|
-
`<rect x="${rx}" y="${ry}" width="${rw}" height="${rh}" rx="${wc}" ry="${hc}" fill="${fill}"/>`
|
|
2620
|
-
);
|
|
2825
|
+
svgElements.push(`<rect x="${rx}" y="${ry}" width="${rw}" height="${rh}" rx="${wc}" ry="${hc}" fill="${fill}"/>`);
|
|
2621
2826
|
}
|
|
2622
2827
|
if (stroke !== "none" && strokeWidth > 0) {
|
|
2623
|
-
svgElements.push(
|
|
2624
|
-
`<polygon points="${rx},${ry} ${rx + rw - 1},${ry} ${rx + rw - 1},${ry + rh - 1} ${rx},${ry + rh - 1}" fill="none" stroke="${stroke}" stroke-width="${strokeWidth}"/>`
|
|
2625
|
-
);
|
|
2828
|
+
svgElements.push(`<polygon points="${rx},${ry} ${rx + rw - 1},${ry} ${rx + rw - 1},${ry + rh - 1} ${rx},${ry + rh - 1}" fill="none" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
2626
2829
|
}
|
|
2627
2830
|
} else if (cmd === "circle") {
|
|
2628
2831
|
const cx = num();
|
|
@@ -2630,9 +2833,7 @@ function applyMagickDraw(img, drawCmd, state) {
|
|
|
2630
2833
|
const px = num();
|
|
2631
2834
|
const py = num();
|
|
2632
2835
|
const r = Math.max(1, Math.hypot(px - cx, py - cy));
|
|
2633
|
-
svgElements.push(
|
|
2634
|
-
`<circle cx="${cx}" cy="${cy}" r="${r}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`
|
|
2635
|
-
);
|
|
2836
|
+
svgElements.push(`<circle cx="${cx}" cy="${cy}" r="${r}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
2636
2837
|
} else if (cmd === "ellipse") {
|
|
2637
2838
|
const cx = num();
|
|
2638
2839
|
const cy = num();
|
|
@@ -2640,18 +2841,14 @@ function applyMagickDraw(img, drawCmd, state) {
|
|
|
2640
2841
|
const ry = num();
|
|
2641
2842
|
num();
|
|
2642
2843
|
num();
|
|
2643
|
-
svgElements.push(
|
|
2644
|
-
`<ellipse cx="${cx}" cy="${cy}" rx="${rx}" ry="${ry}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`
|
|
2645
|
-
);
|
|
2844
|
+
svgElements.push(`<ellipse cx="${cx}" cy="${cy}" rx="${rx}" ry="${ry}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
2646
2845
|
} else if (cmd === "line") {
|
|
2647
2846
|
const x0 = num();
|
|
2648
2847
|
const y0 = num();
|
|
2649
2848
|
const x1 = num();
|
|
2650
2849
|
const y1 = num();
|
|
2651
2850
|
const lineStroke = stroke === "none" ? fill : stroke;
|
|
2652
|
-
svgElements.push(
|
|
2653
|
-
`<line x1="${x0}" y1="${y0}" x2="${x1}" y2="${y1}" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`
|
|
2654
|
-
);
|
|
2851
|
+
svgElements.push(`<line x1="${x0}" y1="${y0}" x2="${x1}" y2="${y1}" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`);
|
|
2655
2852
|
} else if (cmd === "point") {
|
|
2656
2853
|
const x = num();
|
|
2657
2854
|
const y = num();
|
|
@@ -2660,58 +2857,52 @@ function applyMagickDraw(img, drawCmd, state) {
|
|
|
2660
2857
|
const x = num();
|
|
2661
2858
|
const y = num();
|
|
2662
2859
|
const txt = tokens[i++] ?? "";
|
|
2663
|
-
svgElements.push(
|
|
2664
|
-
`<text x="${x}" y="${y}" font-size="${state.pointsize}" fill="${fill}">${escapeXml(txt)}</text>`
|
|
2665
|
-
);
|
|
2860
|
+
svgElements.push(`<text x="${x}" y="${y}" font-size="${state.pointsize}" fill="${fill}">${escapeXml(txt)}</text>`);
|
|
2666
2861
|
} else if (cmd === "polygon" || cmd === "polyline") {
|
|
2667
2862
|
const pts = [];
|
|
2668
2863
|
while (i < tokens.length && !Number.isNaN(Number(tokens[i]))) {
|
|
2864
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2865
|
+
yield;
|
|
2669
2866
|
const px = num();
|
|
2670
2867
|
const py = num();
|
|
2671
2868
|
pts.push(`${px},${py}`);
|
|
2672
2869
|
}
|
|
2673
2870
|
if (pts.length >= 2) {
|
|
2674
2871
|
if (cmd === "polygon") {
|
|
2675
|
-
svgElements.push(
|
|
2676
|
-
`<polygon points="${pts.join(" ")}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`
|
|
2677
|
-
);
|
|
2872
|
+
svgElements.push(`<polygon points="${pts.join(" ")}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
2678
2873
|
} else {
|
|
2679
2874
|
const lineStroke = stroke === "none" ? fill : stroke;
|
|
2680
|
-
svgElements.push(
|
|
2681
|
-
`<polyline points="${pts.join(" ")}" fill="none" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`
|
|
2682
|
-
);
|
|
2875
|
+
svgElements.push(`<polyline points="${pts.join(" ")}" fill="none" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`);
|
|
2683
2876
|
}
|
|
2684
2877
|
}
|
|
2685
2878
|
} else if (cmd === "bezier") {
|
|
2686
2879
|
const pts = [];
|
|
2687
2880
|
while (i < tokens.length && !Number.isNaN(Number(tokens[i]))) {
|
|
2881
|
+
if (++cooperativeWork % 65536 === 0)
|
|
2882
|
+
yield;
|
|
2688
2883
|
pts.push({ x: num(), y: num() });
|
|
2689
2884
|
}
|
|
2690
2885
|
if (pts.length === 3) {
|
|
2691
2886
|
const lineStroke = stroke === "none" ? fill : stroke;
|
|
2692
|
-
svgElements.push(
|
|
2693
|
-
`<path d="M ${pts[0].x} ${pts[0].y} Q ${pts[1].x} ${pts[1].y} ${pts[2].x} ${pts[2].y}" fill="none" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`
|
|
2694
|
-
);
|
|
2887
|
+
svgElements.push(`<path d="M ${pts[0].x} ${pts[0].y} Q ${pts[1].x} ${pts[1].y} ${pts[2].x} ${pts[2].y}" fill="none" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`);
|
|
2695
2888
|
} else if (pts.length >= 4) {
|
|
2696
2889
|
const lineStroke = stroke === "none" ? fill : stroke;
|
|
2697
2890
|
const rest = pts.slice(1).map((p) => `${p.x} ${p.y}`).join(" ");
|
|
2698
|
-
svgElements.push(
|
|
2699
|
-
`<path d="M ${pts[0].x} ${pts[0].y} C ${rest}" fill="none" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`
|
|
2700
|
-
);
|
|
2891
|
+
svgElements.push(`<path d="M ${pts[0].x} ${pts[0].y} C ${rest}" fill="none" stroke="${lineStroke}" stroke-width="${Math.max(1, strokeWidth)}"/>`);
|
|
2701
2892
|
}
|
|
2702
2893
|
} else if (cmd === "path") {
|
|
2703
2894
|
const d = tokens[i++] ?? "";
|
|
2704
|
-
svgElements.push(
|
|
2705
|
-
`<path d="${escapeXml(d)}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`
|
|
2706
|
-
);
|
|
2895
|
+
svgElements.push(`<path d="${escapeXml(d)}" fill="${fill}" stroke="${stroke}" stroke-width="${strokeWidth}"/>`);
|
|
2707
2896
|
}
|
|
2708
2897
|
}
|
|
2709
|
-
if (svgElements.length === 0)
|
|
2898
|
+
if (svgElements.length === 0)
|
|
2899
|
+
return img;
|
|
2710
2900
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${img.width}" height="${img.height}">${svgElements.join("")}</svg>`;
|
|
2711
2901
|
const overlay = decodeImage(new TextEncoder().encode(svg), { density: state.density });
|
|
2712
2902
|
return compositeImage(img, [rgbaToCompositeLayer(overlay, 0, 0, "over")]);
|
|
2713
2903
|
}
|
|
2714
|
-
function
|
|
2904
|
+
function* applyMagickAnnotateSteps(img, offsetStr, text, state, signal) {
|
|
2905
|
+
yield;
|
|
2715
2906
|
const g = parseMagickGeometry(offsetStr);
|
|
2716
2907
|
const fontSize = Math.max(8, state.pointsize);
|
|
2717
2908
|
const estW = Math.max(8, Math.ceil(text.length * fontSize * 0.6));
|
|
@@ -2929,14 +3120,14 @@ function formatIdentifyCustom(fmt, filePath, meta, byteLen, rawBytes) {
|
|
|
2929
3120
|
}
|
|
2930
3121
|
return out;
|
|
2931
3122
|
}
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
}
|
|
2935
|
-
function runIdentifyCliSync(argv, files, stdinBytes) {
|
|
3123
|
+
function* runIdentifyCliSteps(argv, files, stdinBytes, signal) {
|
|
3124
|
+
let cooperativeWork = 63;
|
|
2936
3125
|
let verbose = false;
|
|
2937
3126
|
let customFormat;
|
|
2938
3127
|
const targets = [];
|
|
2939
3128
|
for (let i = 0; i < argv.length; i++) {
|
|
3129
|
+
if (++cooperativeWork % 64 === 0)
|
|
3130
|
+
yield;
|
|
2940
3131
|
const a = argv[i];
|
|
2941
3132
|
if (a === "--help" || a === "-help" || a === "-h") {
|
|
2942
3133
|
return {
|
|
@@ -2972,6 +3163,7 @@ function runIdentifyCliSync(argv, files, stdinBytes) {
|
|
|
2972
3163
|
const errParts = [];
|
|
2973
3164
|
let exitCode = 0;
|
|
2974
3165
|
for (const inPath of targets) {
|
|
3166
|
+
yield;
|
|
2975
3167
|
const bracketMatch = /^(.*)\[(\d+)\]$/.exec(inPath);
|
|
2976
3168
|
let baseInPath = bracketMatch ? bracketMatch[1] : inPath;
|
|
2977
3169
|
const colon = baseInPath.indexOf(":");
|
|
@@ -2995,8 +3187,7 @@ function runIdentifyCliSync(argv, files, stdinBytes) {
|
|
|
2995
3187
|
outParts.push(formatIdentifyCustom(customFormat, baseInPath, meta, bytes.byteLength, bytes));
|
|
2996
3188
|
} else if (verbose) {
|
|
2997
3189
|
const stats = computeImageStats(decodeImage(bytes, inputOptions));
|
|
2998
|
-
outParts.push(
|
|
2999
|
-
`Image: ${inPath}
|
|
3190
|
+
outParts.push(`Image: ${inPath}
|
|
3000
3191
|
Format: ${meta.format.toUpperCase()}
|
|
3001
3192
|
Geometry: ${meta.width}x${meta.height}+0+0
|
|
3002
3193
|
Resolution: ${meta.density}x${meta.density}
|
|
@@ -3006,13 +3197,10 @@ function runIdentifyCliSync(argv, files, stdinBytes) {
|
|
|
3006
3197
|
Alpha: ${meta.hasAlpha ? "True" : "False"}
|
|
3007
3198
|
Filesize: ${bytes.byteLength}B
|
|
3008
3199
|
Entropy: ${stats.entropy.toFixed(4)}
|
|
3009
|
-
`
|
|
3010
|
-
);
|
|
3200
|
+
`);
|
|
3011
3201
|
} else {
|
|
3012
|
-
outParts.push(
|
|
3013
|
-
|
|
3014
|
-
`
|
|
3015
|
-
);
|
|
3202
|
+
outParts.push(`${inPath} ${meta.format.toUpperCase()} ${meta.width}x${meta.height} ${meta.width}x${meta.height}+0+0 ${bitDepth}-bit ${spaceLabel} ${bytes.byteLength}B 0.000u 0:00.000
|
|
3203
|
+
`);
|
|
3016
3204
|
}
|
|
3017
3205
|
} catch (err) {
|
|
3018
3206
|
errParts.push(`identify: improper image header '${inPath}': ${err.message}
|
|
@@ -3026,6 +3214,17 @@ function runIdentifyCliSync(argv, files, stdinBytes) {
|
|
|
3026
3214
|
stderr: errParts.join("")
|
|
3027
3215
|
};
|
|
3028
3216
|
}
|
|
3217
|
+
async function runIdentifyCli(argv, files, stdinBytes, signal) {
|
|
3218
|
+
return drainSteps(runIdentifyCliSteps(argv, files, stdinBytes, signal), signal);
|
|
3219
|
+
}
|
|
3220
|
+
function runIdentifyCliSync(argv, files, stdinBytes, signal) {
|
|
3221
|
+
const steps = runIdentifyCliSteps(argv, files, stdinBytes, signal);
|
|
3222
|
+
let next = steps.next();
|
|
3223
|
+
while (!next.done) {
|
|
3224
|
+
next = steps.next();
|
|
3225
|
+
}
|
|
3226
|
+
return next.value;
|
|
3227
|
+
}
|
|
3029
3228
|
function parseMagickIndexSpec(spec, length) {
|
|
3030
3229
|
if (length <= 0) return [];
|
|
3031
3230
|
const resolve = (n) => n < 0 ? Math.max(0, length + n) : Math.min(Math.max(0, n), length - 1);
|
|
@@ -3052,23 +3251,29 @@ function parseMagickIndexSpec(spec, length) {
|
|
|
3052
3251
|
}
|
|
3053
3252
|
return out;
|
|
3054
3253
|
}
|
|
3055
|
-
function
|
|
3254
|
+
function* evaluatePipelineTokensSteps(tokens, files, state, parentStack = [], stdinBytes, signal) {
|
|
3255
|
+
let cooperativeWork = 63;
|
|
3056
3256
|
let stack = [];
|
|
3057
3257
|
let i = 0;
|
|
3058
3258
|
while (i < tokens.length) {
|
|
3259
|
+
yield;
|
|
3059
3260
|
const t = tokens[i];
|
|
3060
3261
|
if (t === "(") {
|
|
3061
3262
|
let depth = 1;
|
|
3062
3263
|
let j = i + 1;
|
|
3063
3264
|
while (j < tokens.length && depth > 0) {
|
|
3064
|
-
if (
|
|
3065
|
-
|
|
3265
|
+
if (++cooperativeWork % 65536 === 0)
|
|
3266
|
+
yield;
|
|
3267
|
+
if (tokens[j] === "(")
|
|
3268
|
+
depth++;
|
|
3269
|
+
else if (tokens[j] === ")")
|
|
3270
|
+
depth--;
|
|
3066
3271
|
j++;
|
|
3067
3272
|
}
|
|
3068
3273
|
const endIdx = depth === 0 ? j - 1 : j;
|
|
3069
3274
|
const subTokens = tokens.slice(i + 1, endIdx);
|
|
3070
3275
|
const subState = { ...state };
|
|
3071
|
-
const subResult =
|
|
3276
|
+
const subResult = yield* evaluatePipelineTokensSteps(subTokens, files, subState, stack, stdinBytes, signal);
|
|
3072
3277
|
stack.push(...subResult);
|
|
3073
3278
|
i = j;
|
|
3074
3279
|
continue;
|
|
@@ -3113,11 +3318,13 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3113
3318
|
} else if (t === "-define") {
|
|
3114
3319
|
const defStr = tokens[++i] ?? "";
|
|
3115
3320
|
const m = /^compose:args=(.*)$/i.exec(defStr);
|
|
3116
|
-
if (m)
|
|
3321
|
+
if (m)
|
|
3322
|
+
state.composeArgs = m[1];
|
|
3117
3323
|
} else if (t === "-set") {
|
|
3118
3324
|
const k = (tokens[++i] ?? "").toLowerCase();
|
|
3119
3325
|
const v = tokens[++i] ?? "";
|
|
3120
|
-
if (k === "option:compose:args")
|
|
3326
|
+
if (k === "option:compose:args")
|
|
3327
|
+
state.composeArgs = v;
|
|
3121
3328
|
} else if (t === "-write" || t === "+write") {
|
|
3122
3329
|
const writePath = tokens[++i] ?? "";
|
|
3123
3330
|
if (stack.length > 0 && writePath && writePath.toLowerCase() !== "null:") {
|
|
@@ -3125,6 +3332,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3125
3332
|
const { format, path } = inferOutputFormat(writePath, top.format);
|
|
3126
3333
|
if (stack.length > 1 && (/%0?\d*d/.test(path) || !state.adjoin)) {
|
|
3127
3334
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
3335
|
+
if (++cooperativeWork % 65536 === 0)
|
|
3336
|
+
yield;
|
|
3128
3337
|
const framePath = formatSceneOutputPath(path, idx);
|
|
3129
3338
|
const { data: frameBytes } = encodeImage(stack[idx], { format, quality: state.quality });
|
|
3130
3339
|
files.set(framePath, frameBytes);
|
|
@@ -3151,16 +3360,22 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3151
3360
|
} else if (t === "-coalesce" || t === "-deconstruct") {
|
|
3152
3361
|
} else if (t === "-splice") {
|
|
3153
3362
|
const geom = tokens[++i] ?? "0x0";
|
|
3154
|
-
stack = stack
|
|
3363
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3364
|
+
return yield* applyMagickSpliceSteps(im, geom, state.background, state.gravity, signal);
|
|
3365
|
+
});
|
|
3155
3366
|
} else if (t === "-chop") {
|
|
3156
3367
|
const geom = tokens[++i] ?? "0x0";
|
|
3157
|
-
stack = stack
|
|
3368
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3369
|
+
return yield* applyMagickChopSteps(im, geom, state.gravity, signal);
|
|
3370
|
+
});
|
|
3158
3371
|
} else if (t === "-roll") {
|
|
3159
3372
|
const geom = tokens[++i] ?? "+0+0";
|
|
3160
|
-
stack = stack
|
|
3373
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3374
|
+
return yield* applyMagickRollSteps(im, geom, signal);
|
|
3375
|
+
});
|
|
3161
3376
|
} else if (t === "-morph") {
|
|
3162
3377
|
const count = Number(tokens[++i] ?? 1);
|
|
3163
|
-
stack =
|
|
3378
|
+
stack = yield* applyMagickMorphSteps(stack, count, signal);
|
|
3164
3379
|
} else if (t === "-floodfill") {
|
|
3165
3380
|
const geom = tokens[++i] ?? "+0+0";
|
|
3166
3381
|
const nextTok = tokens[i + 1];
|
|
@@ -3172,25 +3387,35 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3172
3387
|
} catch {
|
|
3173
3388
|
}
|
|
3174
3389
|
}
|
|
3175
|
-
stack = stack
|
|
3390
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3391
|
+
return yield* applyMagickFloodfillSteps(im, geom, targetColor, state.fill, state.fuzz, signal);
|
|
3392
|
+
});
|
|
3176
3393
|
} else if (t === "-evaluate-sequence") {
|
|
3177
3394
|
const op = tokens[++i] ?? "Mean";
|
|
3178
3395
|
if (stack.length > 0) {
|
|
3179
|
-
stack = [
|
|
3396
|
+
stack = [yield* applyMagickEvaluateSequenceSteps(stack, op, signal)];
|
|
3180
3397
|
}
|
|
3181
3398
|
} else if (t === "-convolve") {
|
|
3182
3399
|
const kSpec = tokens[++i] ?? "1";
|
|
3183
|
-
stack = stack
|
|
3400
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3401
|
+
return yield* applyMagickCustomConvolveSteps(im, kSpec, signal);
|
|
3402
|
+
});
|
|
3184
3403
|
} else if (t === "-color-matrix" || t === "-recolor") {
|
|
3185
3404
|
const mSpec = tokens[++i] ?? "1,0,0 0,1,0 0,0,1";
|
|
3186
|
-
stack = stack
|
|
3405
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3406
|
+
return yield* applyMagickColorMatrixSteps(im, mSpec, signal);
|
|
3407
|
+
});
|
|
3187
3408
|
} else if (t === "-equalize") {
|
|
3188
|
-
stack = stack
|
|
3409
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3410
|
+
return yield* applyMagickEqualizeSteps(im, signal);
|
|
3411
|
+
});
|
|
3189
3412
|
} else if (t === "-remap") {
|
|
3190
3413
|
const palSpec = tokens[++i] ?? "";
|
|
3191
3414
|
const palImg = parseInputOperand(palSpec, files, state, stdinBytes);
|
|
3192
3415
|
if (palImg) {
|
|
3193
|
-
stack = stack
|
|
3416
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3417
|
+
return yield* applyMagickRemapSteps(im, palImg, state.dither, signal);
|
|
3418
|
+
});
|
|
3194
3419
|
}
|
|
3195
3420
|
} else if (t === "-channel") {
|
|
3196
3421
|
state.channels = parseChannelMask(tokens[++i] ?? "rgb");
|
|
@@ -3201,61 +3426,91 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3201
3426
|
} else if (t === "-opaque" || t === "+opaque") {
|
|
3202
3427
|
const targetColor = parseColor2(tokens[++i] ?? "#000000");
|
|
3203
3428
|
const invert = t === "+opaque";
|
|
3204
|
-
stack = stack
|
|
3429
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3430
|
+
return yield* applyMagickOpaqueSteps(im, targetColor, state.fill, state.fuzz, invert, signal);
|
|
3431
|
+
});
|
|
3205
3432
|
} else if (t === "-transparent" || t === "+transparent") {
|
|
3206
3433
|
const targetColor = parseColor2(tokens[++i] ?? "#ffffff");
|
|
3207
3434
|
const invert = t === "+transparent";
|
|
3208
|
-
stack = stack
|
|
3435
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3436
|
+
return yield* applyMagickTransparentSteps(im, targetColor, state.fuzz, invert, signal);
|
|
3437
|
+
});
|
|
3209
3438
|
} else if (t === "-evaluate") {
|
|
3210
3439
|
const op = tokens[++i] ?? "Add";
|
|
3211
3440
|
const val = tokens[++i] ?? "0";
|
|
3212
|
-
stack = stack
|
|
3441
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3442
|
+
return yield* applyMagickEvaluateSteps(im, op, val, state.channels, signal);
|
|
3443
|
+
});
|
|
3213
3444
|
} else if (t === "-function") {
|
|
3214
3445
|
const fn = tokens[++i] ?? "Polynomial";
|
|
3215
3446
|
const params = tokens[++i] ?? "1,0";
|
|
3216
|
-
stack = stack
|
|
3447
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3448
|
+
return yield* applyMagickFunctionSteps(im, fn, params, state.channels, signal);
|
|
3449
|
+
});
|
|
3217
3450
|
} else if (t === "-clut" || t === "-hald-clut") {
|
|
3218
3451
|
if (stack.length >= 2) {
|
|
3219
3452
|
const lut = stack[stack.length - 1];
|
|
3220
|
-
const mapped = stack.slice(0, -1)
|
|
3453
|
+
const mapped = yield* mapSteps(stack.slice(0, -1), function* (im) {
|
|
3454
|
+
return yield* applyMagickClutSteps(im, lut, state.channels, signal);
|
|
3455
|
+
});
|
|
3221
3456
|
stack = mapped;
|
|
3222
3457
|
}
|
|
3223
3458
|
} else if (t === "-fx") {
|
|
3224
3459
|
const expr = tokens[++i] ?? "u";
|
|
3225
3460
|
if (stack.length > 0) {
|
|
3226
|
-
stack = [
|
|
3461
|
+
stack = [yield* applyMagickFxSteps(stack, expr, state.channels, signal)];
|
|
3227
3462
|
}
|
|
3228
3463
|
} else if (t === "-shear") {
|
|
3229
3464
|
const geom = tokens[++i] ?? "0x0";
|
|
3230
|
-
stack = stack
|
|
3465
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3466
|
+
return yield* applyMagickShearSteps(im, geom, state.background, signal);
|
|
3467
|
+
});
|
|
3231
3468
|
} else if (t === "-distort" || t === "+distort") {
|
|
3232
3469
|
const method = tokens[++i] ?? "SRT";
|
|
3233
3470
|
const args = tokens[++i] ?? "0";
|
|
3234
|
-
stack = stack
|
|
3471
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3472
|
+
return yield* applyMagickDistortSteps(im, method, args, state.background, signal);
|
|
3473
|
+
});
|
|
3235
3474
|
} else if (t === "-swirl") {
|
|
3236
3475
|
const deg = Number(tokens[++i] ?? 0);
|
|
3237
|
-
stack = stack
|
|
3476
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3477
|
+
return yield* applyMagickSwirlSteps(im, deg, state.background, signal);
|
|
3478
|
+
});
|
|
3238
3479
|
} else if (t === "-implode") {
|
|
3239
3480
|
const amt = Number(tokens[++i] ?? 0);
|
|
3240
|
-
stack = stack
|
|
3481
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3482
|
+
return yield* applyMagickImplodeSteps(im, amt, state.background, signal);
|
|
3483
|
+
});
|
|
3241
3484
|
} else if (t === "-wave") {
|
|
3242
3485
|
const geom = tokens[++i] ?? "5x50";
|
|
3243
|
-
stack = stack
|
|
3486
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3487
|
+
return yield* applyMagickWaveSteps(im, geom, state.background, signal);
|
|
3488
|
+
});
|
|
3244
3489
|
} else if (t === "-shadow") {
|
|
3245
3490
|
const geom = tokens[++i] ?? "80x3+5+5";
|
|
3246
|
-
stack = stack
|
|
3491
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3492
|
+
return yield* applyMagickShadowSteps(im, geom, state.background, signal);
|
|
3493
|
+
});
|
|
3247
3494
|
} else if (t === "-vignette") {
|
|
3248
3495
|
const geom = tokens[++i] ?? "0x2";
|
|
3249
|
-
stack = stack
|
|
3496
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3497
|
+
return yield* applyMagickVignetteSteps(im, geom, state.background, signal);
|
|
3498
|
+
});
|
|
3250
3499
|
} else if (t === "-sepia-tone") {
|
|
3251
3500
|
const thresh = tokens[++i] ?? "80%";
|
|
3252
|
-
stack = stack
|
|
3501
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3502
|
+
return yield* applyMagickSepiaToneSteps(im, thresh, signal);
|
|
3503
|
+
});
|
|
3253
3504
|
} else if (t === "-solarize") {
|
|
3254
3505
|
const thresh = tokens[++i] ?? "50%";
|
|
3255
|
-
stack = stack
|
|
3506
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3507
|
+
return yield* applyMagickSolarizeSteps(im, thresh, signal);
|
|
3508
|
+
});
|
|
3256
3509
|
} else if (t === "-posterize" || t === "-colors") {
|
|
3257
3510
|
const lv = Number(tokens[++i] ?? 8);
|
|
3258
|
-
stack = stack
|
|
3511
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3512
|
+
return yield* applyMagickPosterizeSteps(im, lv, signal);
|
|
3513
|
+
});
|
|
3259
3514
|
} else if (t === "-dither" || t === "+dither") {
|
|
3260
3515
|
if (t === "+dither") {
|
|
3261
3516
|
state.dither = false;
|
|
@@ -3265,22 +3520,22 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3265
3520
|
}
|
|
3266
3521
|
} else if (t === "-edge" || t === "-canny") {
|
|
3267
3522
|
i++;
|
|
3268
|
-
stack = stack
|
|
3523
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3524
|
+
return yield* applyMagickConvolve3x3Steps(im, [-1, -1, -1, -1, 8, -1, -1, -1, -1], 0, signal);
|
|
3525
|
+
});
|
|
3269
3526
|
} else if (t === "-emboss") {
|
|
3270
3527
|
i++;
|
|
3271
|
-
stack = stack
|
|
3528
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3529
|
+
return yield* applyMagickConvolve3x3Steps(im, [-2, -1, 0, -1, 1, 1, 0, 1, 2], 128, signal);
|
|
3530
|
+
});
|
|
3272
3531
|
} else if (t === "-charcoal" || t === "-sketch") {
|
|
3273
3532
|
i++;
|
|
3274
|
-
stack = stack
|
|
3275
|
-
(im)
|
|
3276
|
-
|
|
3277
|
-
applyMagickConvolve3x3(blurImage(im, 1), [-1, -1, -1, -1, 8, -1, -1, -1, -1], 0),
|
|
3278
|
-
{ alpha: false }
|
|
3279
|
-
)
|
|
3280
|
-
)
|
|
3281
|
-
);
|
|
3533
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3534
|
+
return grayscaleImage(negateImage(yield* applyMagickConvolve3x3Steps(blurImage(im, 1), [-1, -1, -1, -1, 8, -1, -1, -1, -1], 0, signal), { alpha: false }));
|
|
3535
|
+
});
|
|
3282
3536
|
} else if (t === "+repage" || t === "-repage") {
|
|
3283
|
-
if (t === "-repage")
|
|
3537
|
+
if (t === "-repage")
|
|
3538
|
+
i++;
|
|
3284
3539
|
} else if (t === "-resize" || t === "-scale" || t === "-sample" || t === "-thumbnail") {
|
|
3285
3540
|
const geom = tokens[++i] ?? "100%";
|
|
3286
3541
|
const k = t === "-sample" ? "nearest" : state.kernel;
|
|
@@ -3289,26 +3544,28 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3289
3544
|
const geom = tokens[++i] ?? "100%";
|
|
3290
3545
|
const nextStack = [];
|
|
3291
3546
|
for (const im of stack) {
|
|
3547
|
+
if (++cooperativeWork % 65536 === 0)
|
|
3548
|
+
yield;
|
|
3292
3549
|
nextStack.push(...applyMagickCropToStack(im, geom, state.gravity));
|
|
3293
3550
|
}
|
|
3294
3551
|
stack = nextStack;
|
|
3295
3552
|
} else if (t === "-extent") {
|
|
3296
3553
|
const geom = tokens[++i] ?? "100%";
|
|
3297
|
-
stack = stack
|
|
3554
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3555
|
+
return yield* applyMagickExtentSteps(im, geom, state, signal);
|
|
3556
|
+
});
|
|
3298
3557
|
} else if (t === "-border") {
|
|
3299
3558
|
const g = parseMagickGeometry(tokens[++i] ?? "0x0");
|
|
3300
3559
|
const bw = Math.max(0, Math.round(g.width ?? 0));
|
|
3301
3560
|
const bh = Math.max(0, Math.round(g.height ?? bw));
|
|
3302
|
-
stack = stack.map(
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
})
|
|
3311
|
-
);
|
|
3561
|
+
stack = stack.map((im) => extendImage(im, {
|
|
3562
|
+
top: bh,
|
|
3563
|
+
bottom: bh,
|
|
3564
|
+
left: bw,
|
|
3565
|
+
right: bw,
|
|
3566
|
+
background: state.borderColor,
|
|
3567
|
+
extendWith: "background"
|
|
3568
|
+
}));
|
|
3312
3569
|
} else if (t === "-shave") {
|
|
3313
3570
|
const g = parseMagickGeometry(tokens[++i] ?? "0x0");
|
|
3314
3571
|
const sw = Math.max(0, Math.round(g.width ?? 0));
|
|
@@ -3347,11 +3604,16 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3347
3604
|
const r = out[idx];
|
|
3348
3605
|
const g = out[idx + 1];
|
|
3349
3606
|
const b = out[idx + 2];
|
|
3350
|
-
if (onlyGray && !(r === g && g === b))
|
|
3351
|
-
|
|
3352
|
-
if (ch.
|
|
3353
|
-
|
|
3354
|
-
if (ch.
|
|
3607
|
+
if (onlyGray && !(r === g && g === b))
|
|
3608
|
+
continue;
|
|
3609
|
+
if (ch.r)
|
|
3610
|
+
out[idx] = 255 - r;
|
|
3611
|
+
if (ch.g)
|
|
3612
|
+
out[idx + 1] = 255 - g;
|
|
3613
|
+
if (ch.b)
|
|
3614
|
+
out[idx + 2] = 255 - b;
|
|
3615
|
+
if (ch.a)
|
|
3616
|
+
out[idx + 3] = 255 - out[idx + 3];
|
|
3355
3617
|
}
|
|
3356
3618
|
return { ...im, data: out };
|
|
3357
3619
|
});
|
|
@@ -3388,8 +3650,10 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3388
3650
|
for (let idx = 0; idx < out.length; idx += 4) {
|
|
3389
3651
|
for (let c = 0; c < 4; c++) {
|
|
3390
3652
|
const v = out[idx + c];
|
|
3391
|
-
if (v < mins[c])
|
|
3392
|
-
|
|
3653
|
+
if (v < mins[c])
|
|
3654
|
+
mins[c] = v;
|
|
3655
|
+
if (v > maxs[c])
|
|
3656
|
+
maxs[c] = v;
|
|
3393
3657
|
}
|
|
3394
3658
|
}
|
|
3395
3659
|
if (!indep) {
|
|
@@ -3401,7 +3665,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3401
3665
|
const active = [ch.r, ch.g, ch.b, ch.a];
|
|
3402
3666
|
for (let idx = 0; idx < out.length; idx += 4) {
|
|
3403
3667
|
for (let c = 0; c < 4; c++) {
|
|
3404
|
-
if (!active[c])
|
|
3668
|
+
if (!active[c])
|
|
3669
|
+
continue;
|
|
3405
3670
|
const range = maxs[c] - mins[c];
|
|
3406
3671
|
if (range > 0) {
|
|
3407
3672
|
out[idx + c] = clampByteVal((out[idx + c] - mins[c]) / range * 255);
|
|
@@ -3423,7 +3688,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3423
3688
|
const highTarget = isPct ? (100 - wVal) / 100 * nPix : nPix - wVal;
|
|
3424
3689
|
for (let c = 0; c < 3; c++) {
|
|
3425
3690
|
const hist = new Uint32Array(256);
|
|
3426
|
-
for (let idx = c; idx < out.length; idx += 4)
|
|
3691
|
+
for (let idx = c; idx < out.length; idx += 4)
|
|
3692
|
+
hist[out[idx]]++;
|
|
3427
3693
|
let lowBin = 0;
|
|
3428
3694
|
let acc = 0;
|
|
3429
3695
|
for (let b = 0; b < 256; b++) {
|
|
@@ -3465,7 +3731,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3465
3731
|
for (let x = 0; x < im.width; x++) {
|
|
3466
3732
|
const topLeft = y < bw || x < bw;
|
|
3467
3733
|
const botRight = y >= im.height - bw || x >= im.width - bw;
|
|
3468
|
-
if (!topLeft && !botRight)
|
|
3734
|
+
if (!topLeft && !botRight)
|
|
3735
|
+
continue;
|
|
3469
3736
|
const lighten = raised ? topLeft : botRight;
|
|
3470
3737
|
const idx = (y * im.width + x) * 4;
|
|
3471
3738
|
for (let c = 0; c < 3; c++) {
|
|
@@ -3479,16 +3746,14 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3479
3746
|
const g = parseMagickGeometry(tokens[++i] ?? "4x4");
|
|
3480
3747
|
const fw = Math.max(0, Math.round(g.width ?? 4));
|
|
3481
3748
|
const fh = Math.max(0, Math.round(g.height ?? fw));
|
|
3482
|
-
stack = stack.map(
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
})
|
|
3491
|
-
);
|
|
3749
|
+
stack = stack.map((im) => extendImage(im, {
|
|
3750
|
+
top: fh,
|
|
3751
|
+
bottom: fh,
|
|
3752
|
+
left: fw,
|
|
3753
|
+
right: fw,
|
|
3754
|
+
background: state.borderColor,
|
|
3755
|
+
extendWith: "background"
|
|
3756
|
+
}));
|
|
3492
3757
|
} else if (t === "-deskew") {
|
|
3493
3758
|
i++;
|
|
3494
3759
|
} else if (t === "-auto-gamma") {
|
|
@@ -3497,7 +3762,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3497
3762
|
const numCh = im.hasAlpha ? 4 : 3;
|
|
3498
3763
|
let sum = 0;
|
|
3499
3764
|
for (let idx = 0; idx < out.length; idx += 4) {
|
|
3500
|
-
for (let c = 0; c < numCh; c++)
|
|
3765
|
+
for (let c = 0; c < numCh; c++)
|
|
3766
|
+
sum += out[idx + c];
|
|
3501
3767
|
}
|
|
3502
3768
|
const mean = sum / Math.max(1, im.width * im.height * numCh * 255);
|
|
3503
3769
|
if (mean > 0 && mean < 1) {
|
|
@@ -3535,7 +3801,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3535
3801
|
const parts = raw.split(",");
|
|
3536
3802
|
const anyPct = raw.includes("%");
|
|
3537
3803
|
const parsePt = (p, def) => {
|
|
3538
|
-
if (!p || p.length === 0)
|
|
3804
|
+
if (!p || p.length === 0)
|
|
3805
|
+
return def;
|
|
3539
3806
|
if (p.endsWith("%") || anyPct) {
|
|
3540
3807
|
return parseFloat(p) / 100 * 255;
|
|
3541
3808
|
}
|
|
@@ -3607,14 +3874,20 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3607
3874
|
kernelSpec = tokens[++i];
|
|
3608
3875
|
}
|
|
3609
3876
|
if (method.includes("convolve") || method.includes("correlate")) {
|
|
3610
|
-
stack = stack
|
|
3877
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3878
|
+
return yield* applyMagickCustomConvolveSteps(im, kernelSpec, signal);
|
|
3879
|
+
});
|
|
3611
3880
|
} else {
|
|
3612
|
-
stack = stack
|
|
3881
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3882
|
+
return yield* applyMagickMorphology4ChSteps(im, method, kernelSpec, signal);
|
|
3883
|
+
});
|
|
3613
3884
|
}
|
|
3614
3885
|
} else if (t === "-statistic") {
|
|
3615
3886
|
const statType = (tokens[++i] ?? "median").toLowerCase();
|
|
3616
3887
|
const geom = tokens[++i] ?? "3x3";
|
|
3617
|
-
stack = stack
|
|
3888
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3889
|
+
return yield* applyMagickMorphology4ChSteps(im, statType, geom, signal);
|
|
3890
|
+
});
|
|
3618
3891
|
} else if (t === "-alpha") {
|
|
3619
3892
|
const mode = (tokens[++i] ?? "on").toLowerCase();
|
|
3620
3893
|
if (mode === "remove") {
|
|
@@ -3622,22 +3895,22 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3622
3895
|
} else if (mode === "off" || mode === "deactivate" || mode === "opaque") {
|
|
3623
3896
|
stack = stack.map((im) => {
|
|
3624
3897
|
const out = new Uint8Array(im.data);
|
|
3625
|
-
for (let idx = 3; idx < out.length; idx += 4)
|
|
3898
|
+
for (let idx = 3; idx < out.length; idx += 4)
|
|
3899
|
+
out[idx] = 255;
|
|
3626
3900
|
return { ...im, data: out, hasAlpha: mode === "opaque" };
|
|
3627
3901
|
});
|
|
3628
3902
|
} else if (mode === "transparent") {
|
|
3629
3903
|
stack = stack.map((im) => {
|
|
3630
3904
|
const out = new Uint8Array(im.data);
|
|
3631
|
-
for (let idx = 3; idx < out.length; idx += 4)
|
|
3905
|
+
for (let idx = 3; idx < out.length; idx += 4)
|
|
3906
|
+
out[idx] = 0;
|
|
3632
3907
|
return { ...im, data: out, hasAlpha: true };
|
|
3633
3908
|
});
|
|
3634
3909
|
} else if (mode === "copy" || mode === "shape") {
|
|
3635
3910
|
stack = stack.map((im) => {
|
|
3636
3911
|
const out = new Uint8Array(im.data);
|
|
3637
3912
|
for (let idx = 0; idx < out.length; idx += 4) {
|
|
3638
|
-
const inten = clampByteVal(
|
|
3639
|
-
0.212656 * out[idx] + 0.715158 * out[idx + 1] + 0.072186 * out[idx + 2]
|
|
3640
|
-
);
|
|
3913
|
+
const inten = clampByteVal(0.212656 * out[idx] + 0.715158 * out[idx + 1] + 0.072186 * out[idx + 2]);
|
|
3641
3914
|
if (mode === "shape") {
|
|
3642
3915
|
out[idx] = state.background.r;
|
|
3643
3916
|
out[idx + 1] = state.background.g;
|
|
@@ -3655,17 +3928,19 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3655
3928
|
} else if (t === "-separate") {
|
|
3656
3929
|
const nextStack = [];
|
|
3657
3930
|
for (const im of stack) {
|
|
3931
|
+
if (++cooperativeWork % 65536 === 0)
|
|
3932
|
+
yield;
|
|
3658
3933
|
if (state.channelExplicit) {
|
|
3659
|
-
if (state.channels.r)
|
|
3660
|
-
|
|
3661
|
-
if (state.channels.
|
|
3662
|
-
|
|
3934
|
+
if (state.channels.r)
|
|
3935
|
+
nextStack.push(extractChannelImage(im, 0));
|
|
3936
|
+
if (state.channels.g)
|
|
3937
|
+
nextStack.push(extractChannelImage(im, 1));
|
|
3938
|
+
if (state.channels.b)
|
|
3939
|
+
nextStack.push(extractChannelImage(im, 2));
|
|
3940
|
+
if (state.channels.a)
|
|
3941
|
+
nextStack.push(extractChannelImage(ensureAlphaImage(im, 1), 3));
|
|
3663
3942
|
} else {
|
|
3664
|
-
nextStack.push(
|
|
3665
|
-
extractChannelImage(im, 0),
|
|
3666
|
-
extractChannelImage(im, 1),
|
|
3667
|
-
extractChannelImage(im, 2)
|
|
3668
|
-
);
|
|
3943
|
+
nextStack.push(extractChannelImage(im, 0), extractChannelImage(im, 1), extractChannelImage(im, 2));
|
|
3669
3944
|
if (im.hasAlpha) {
|
|
3670
3945
|
nextStack.push(extractChannelImage(ensureAlphaImage(im, 1), 3));
|
|
3671
3946
|
}
|
|
@@ -3680,6 +3955,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3680
3955
|
const aIm = stack[3];
|
|
3681
3956
|
const out = new Uint8Array(rIm.width * rIm.height * 4);
|
|
3682
3957
|
for (let p = 0; p < out.length; p += 4) {
|
|
3958
|
+
if (++cooperativeWork % 65536 === 0)
|
|
3959
|
+
yield;
|
|
3683
3960
|
out[p] = rIm.data[p];
|
|
3684
3961
|
out[p + 1] = gIm.data[p];
|
|
3685
3962
|
out[p + 2] = bIm.data[p];
|
|
@@ -3689,19 +3966,26 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3689
3966
|
}
|
|
3690
3967
|
} else if (t === "-draw") {
|
|
3691
3968
|
const drawSpec = tokens[++i] ?? "";
|
|
3692
|
-
stack = stack
|
|
3969
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3970
|
+
return yield* applyMagickDrawSteps(im, drawSpec, state, signal);
|
|
3971
|
+
});
|
|
3693
3972
|
} else if (t === "-annotate") {
|
|
3694
3973
|
const offsetOrText = tokens[++i] ?? "+0+0";
|
|
3695
3974
|
const hasExplicitOffset = /^[+-]\d/.test(offsetOrText) || /^\d+x\d+/.test(offsetOrText);
|
|
3696
3975
|
const offset = hasExplicitOffset ? offsetOrText : "+0+0";
|
|
3697
3976
|
const text = hasExplicitOffset ? tokens[++i] ?? "" : offsetOrText;
|
|
3698
|
-
stack = stack
|
|
3977
|
+
stack = yield* mapSteps(stack, function* (im) {
|
|
3978
|
+
return yield* applyMagickAnnotateSteps(im, offset, text, state, signal);
|
|
3979
|
+
});
|
|
3699
3980
|
} else if (t === "+clone" || t === "-clone") {
|
|
3700
3981
|
const sourcePool = stack.length > 0 ? stack : parentStack;
|
|
3701
3982
|
const spec = t === "+clone" ? "-1" : tokens[++i] ?? "-1";
|
|
3702
3983
|
for (const idx of parseMagickIndexSpec(spec, sourcePool.length)) {
|
|
3984
|
+
if (++cooperativeWork % 65536 === 0)
|
|
3985
|
+
yield;
|
|
3703
3986
|
const chosen = sourcePool[idx];
|
|
3704
|
-
if (chosen)
|
|
3987
|
+
if (chosen)
|
|
3988
|
+
stack.push({ ...chosen, data: new Uint8Array(chosen.data) });
|
|
3705
3989
|
}
|
|
3706
3990
|
} else if (t === "-duplicate" || t === "+duplicate") {
|
|
3707
3991
|
let count = 1;
|
|
@@ -3722,9 +4006,14 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3722
4006
|
const sourcePool = stack.length > 0 ? stack : parentStack;
|
|
3723
4007
|
const indices = parseMagickIndexSpec(idxSpec, sourcePool.length);
|
|
3724
4008
|
for (let k = 0; k < count; k++) {
|
|
4009
|
+
if (++cooperativeWork % 65536 === 0)
|
|
4010
|
+
yield;
|
|
3725
4011
|
for (const idx of indices) {
|
|
4012
|
+
if (++cooperativeWork % 65536 === 0)
|
|
4013
|
+
yield;
|
|
3726
4014
|
const chosen = sourcePool[idx];
|
|
3727
|
-
if (chosen)
|
|
4015
|
+
if (chosen)
|
|
4016
|
+
stack.push({ ...chosen, data: new Uint8Array(chosen.data) });
|
|
3728
4017
|
}
|
|
3729
4018
|
}
|
|
3730
4019
|
} else if (t === "+insert" || t === "-insert") {
|
|
@@ -3759,7 +4048,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3759
4048
|
} else if (t === "-append" || t === "+append") {
|
|
3760
4049
|
stack = [appendStackImages(stack, t === "-append", state)];
|
|
3761
4050
|
} else if (t === "-flatten" || t === "-mosaic" || t === "-layers" && ["flatten", "merge", "mosaic"].includes((tokens[i + 1] ?? "").toLowerCase())) {
|
|
3762
|
-
if (t === "-layers")
|
|
4051
|
+
if (t === "-layers")
|
|
4052
|
+
i++;
|
|
3763
4053
|
if (stack.length > 0) {
|
|
3764
4054
|
const maxW = Math.max(...stack.map((im) => im.width));
|
|
3765
4055
|
const maxH = Math.max(...stack.map((im) => im.height));
|
|
@@ -3782,14 +4072,7 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3782
4072
|
gy = g.y;
|
|
3783
4073
|
}
|
|
3784
4074
|
const grav = resolveGravityOffset(base.width - overlay.width, base.height - overlay.height, state.gravity);
|
|
3785
|
-
const composed =
|
|
3786
|
-
base,
|
|
3787
|
-
overlay,
|
|
3788
|
-
state.composeRaw,
|
|
3789
|
-
grav.left + gx,
|
|
3790
|
-
grav.top + gy,
|
|
3791
|
-
state.composeArgs
|
|
3792
|
-
);
|
|
4075
|
+
const composed = yield* applyMagickCompositeLayerSteps(base, overlay, state.composeRaw, grav.left + gx, grav.top + gy, state.composeArgs, signal);
|
|
3793
4076
|
stack = [composed, ...stack.slice(2)];
|
|
3794
4077
|
}
|
|
3795
4078
|
} else {
|
|
@@ -3802,10 +4085,8 @@ function evaluatePipelineTokens(tokens, files, state, parentStack = [], stdinByt
|
|
|
3802
4085
|
}
|
|
3803
4086
|
return stack;
|
|
3804
4087
|
}
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
}
|
|
3808
|
-
function runConvertCliSync(argv, files, stdinBytes) {
|
|
4088
|
+
function* runConvertCliSteps(argv, files, stdinBytes, signal) {
|
|
4089
|
+
let cooperativeWork = 63;
|
|
3809
4090
|
if (argv.length === 0 || argv.includes("--help") || argv.includes("-help") || argv.includes("-h")) {
|
|
3810
4091
|
return {
|
|
3811
4092
|
exitCode: 0,
|
|
@@ -3824,7 +4105,7 @@ function runConvertCliSync(argv, files, stdinBytes) {
|
|
|
3824
4105
|
const pipelineTokens = argv.slice(0, -1);
|
|
3825
4106
|
const state = createDefaultState();
|
|
3826
4107
|
try {
|
|
3827
|
-
const stack =
|
|
4108
|
+
const stack = yield* evaluatePipelineTokensSteps(pipelineTokens, files, state, [], stdinBytes, signal);
|
|
3828
4109
|
if (stack.length === 0) {
|
|
3829
4110
|
return {
|
|
3830
4111
|
exitCode: 1,
|
|
@@ -3860,6 +4141,8 @@ function runConvertCliSync(argv, files, stdinBytes) {
|
|
|
3860
4141
|
const { format, path: outPath } = inferOutputFormat(outSpec, "png");
|
|
3861
4142
|
if (stack.length > 1 && (/%0?\d*d/.test(outPath) || !state.adjoin)) {
|
|
3862
4143
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
4144
|
+
if (++cooperativeWork % 64 === 0)
|
|
4145
|
+
yield;
|
|
3863
4146
|
const framePath = formatSceneOutputPath(outPath, idx);
|
|
3864
4147
|
const { data: frameBytes } = encodeImage(stack[idx], { format, quality: state.quality });
|
|
3865
4148
|
files.set(framePath, frameBytes);
|
|
@@ -3873,6 +4156,8 @@ function runConvertCliSync(argv, files, stdinBytes) {
|
|
|
3873
4156
|
const fh = stack[0].height;
|
|
3874
4157
|
const combined = new Uint8Array(fw * fh * stack.length * 4);
|
|
3875
4158
|
for (let idx = 0; idx < stack.length; idx++) {
|
|
4159
|
+
if (++cooperativeWork % 64 === 0)
|
|
4160
|
+
yield;
|
|
3876
4161
|
const frame = stack[idx].width === fw && stack[idx].height === fh ? stack[idx] : applyMagickResize(stack[idx], `${fw}x${fh}!`, state.kernel);
|
|
3877
4162
|
combined.set(frame.data, idx * fw * fh * 4);
|
|
3878
4163
|
}
|
|
@@ -3910,10 +4195,19 @@ function runConvertCliSync(argv, files, stdinBytes) {
|
|
|
3910
4195
|
};
|
|
3911
4196
|
}
|
|
3912
4197
|
}
|
|
3913
|
-
async function
|
|
3914
|
-
return
|
|
4198
|
+
async function runConvertCli(argv, files, stdinBytes, signal) {
|
|
4199
|
+
return drainSteps(runConvertCliSteps(argv, files, stdinBytes, signal), signal);
|
|
4200
|
+
}
|
|
4201
|
+
function runConvertCliSync(argv, files, stdinBytes, signal) {
|
|
4202
|
+
const steps = runConvertCliSteps(argv, files, stdinBytes, signal);
|
|
4203
|
+
let next = steps.next();
|
|
4204
|
+
while (!next.done) {
|
|
4205
|
+
next = steps.next();
|
|
4206
|
+
}
|
|
4207
|
+
return next.value;
|
|
3915
4208
|
}
|
|
3916
|
-
function
|
|
4209
|
+
function* runMogrifyCliSteps(argv, files, _stdinBytes, signal) {
|
|
4210
|
+
let cooperativeWork = 63;
|
|
3917
4211
|
let outFormatExt;
|
|
3918
4212
|
let outDir;
|
|
3919
4213
|
const opTokens = [];
|
|
@@ -4004,6 +4298,8 @@ function runMogrifyCliSync(argv, files) {
|
|
|
4004
4298
|
"-sketch"
|
|
4005
4299
|
]);
|
|
4006
4300
|
for (let i = 0; i < argv.length; i++) {
|
|
4301
|
+
if (++cooperativeWork % 64 === 0)
|
|
4302
|
+
yield;
|
|
4007
4303
|
const t = argv[i];
|
|
4008
4304
|
if (t === "-format") {
|
|
4009
4305
|
outFormatExt = (argv[++i] ?? "png").replace(/^\./, "").toLowerCase();
|
|
@@ -4031,6 +4327,8 @@ function runMogrifyCliSync(argv, files) {
|
|
|
4031
4327
|
}
|
|
4032
4328
|
}
|
|
4033
4329
|
for (const target of targets) {
|
|
4330
|
+
if (++cooperativeWork % 64 === 0)
|
|
4331
|
+
yield;
|
|
4034
4332
|
if (!files.has(target)) {
|
|
4035
4333
|
return {
|
|
4036
4334
|
exitCode: 1,
|
|
@@ -4045,18 +4343,30 @@ function runMogrifyCliSync(argv, files) {
|
|
|
4045
4343
|
const targetExt = outFormatExt ?? origExt;
|
|
4046
4344
|
const destDir = outDir ? outDir.replace(/\/+$/, "") : target.slice(0, Math.max(0, target.lastIndexOf("/")));
|
|
4047
4345
|
const destPath = outFormatExt || outDir ? `${destDir ? destDir + "/" : ""}${stem}.${targetExt}` : target;
|
|
4048
|
-
const res =
|
|
4049
|
-
if (res.exitCode !== 0)
|
|
4346
|
+
const res = yield* runConvertCliSteps([...readSettings, target, ...opTokens, destPath], files, void 0, signal);
|
|
4347
|
+
if (res.exitCode !== 0)
|
|
4348
|
+
return res;
|
|
4050
4349
|
}
|
|
4051
4350
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
4052
4351
|
}
|
|
4053
|
-
async function
|
|
4054
|
-
return
|
|
4352
|
+
async function runMogrifyCli(argv, files, _stdinBytes, signal) {
|
|
4353
|
+
return drainSteps(runMogrifyCliSteps(argv, files, _stdinBytes, signal), signal);
|
|
4055
4354
|
}
|
|
4056
|
-
function
|
|
4355
|
+
function runMogrifyCliSync(argv, files, _stdinBytes, signal) {
|
|
4356
|
+
const steps = runMogrifyCliSteps(argv, files, _stdinBytes, signal);
|
|
4357
|
+
let next = steps.next();
|
|
4358
|
+
while (!next.done) {
|
|
4359
|
+
next = steps.next();
|
|
4360
|
+
}
|
|
4361
|
+
return next.value;
|
|
4362
|
+
}
|
|
4363
|
+
function* runCompositeCliSteps(argv, files, stdinBytes, signal) {
|
|
4364
|
+
let cooperativeWork = 63;
|
|
4057
4365
|
const options = [];
|
|
4058
4366
|
const operands = [];
|
|
4059
4367
|
for (let i = 0; i < argv.length; i++) {
|
|
4368
|
+
if (++cooperativeWork % 64 === 0)
|
|
4369
|
+
yield;
|
|
4060
4370
|
const t = argv[i];
|
|
4061
4371
|
if (t === "-gravity" || t === "-geometry" || t === "-compose" || t === "-background" || t === "-quality" || t === "-define") {
|
|
4062
4372
|
options.push(t, argv[++i] ?? "");
|
|
@@ -4080,7 +4390,18 @@ function runCompositeCliSync(argv, files, stdinBytes) {
|
|
|
4080
4390
|
const overlay = operands[0];
|
|
4081
4391
|
const base = operands[1];
|
|
4082
4392
|
const out = operands[operands.length - 1];
|
|
4083
|
-
return
|
|
4393
|
+
return yield* runConvertCliSteps([base, overlay, ...options, "-composite", out], files, stdinBytes, signal);
|
|
4394
|
+
}
|
|
4395
|
+
async function runCompositeCli(argv, files, stdinBytes, signal) {
|
|
4396
|
+
return drainSteps(runCompositeCliSteps(argv, files, stdinBytes, signal), signal);
|
|
4397
|
+
}
|
|
4398
|
+
function runCompositeCliSync(argv, files, stdinBytes, signal) {
|
|
4399
|
+
const steps = runCompositeCliSteps(argv, files, stdinBytes, signal);
|
|
4400
|
+
let next = steps.next();
|
|
4401
|
+
while (!next.done) {
|
|
4402
|
+
next = steps.next();
|
|
4403
|
+
}
|
|
4404
|
+
return next.value;
|
|
4084
4405
|
}
|
|
4085
4406
|
function formatMetricNum(n) {
|
|
4086
4407
|
if (!Number.isFinite(n)) return "inf";
|
|
@@ -4088,10 +4409,8 @@ function formatMetricNum(n) {
|
|
|
4088
4409
|
const fixed = n.toFixed(6).replace(/\.?0+$/, "");
|
|
4089
4410
|
return fixed === "-0" ? "0" : fixed;
|
|
4090
4411
|
}
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
}
|
|
4094
|
-
function runCompareCliSync(argv, files, stdinBytes) {
|
|
4412
|
+
function* runCompareCliSteps(argv, files, stdinBytes, signal) {
|
|
4413
|
+
let cooperativeWork = 63;
|
|
4095
4414
|
const state = createDefaultState();
|
|
4096
4415
|
state.fuzz = 0;
|
|
4097
4416
|
let metric = "rmse";
|
|
@@ -4101,6 +4420,8 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4101
4420
|
let dissimilarityThreshold;
|
|
4102
4421
|
const operands = [];
|
|
4103
4422
|
for (let i = 0; i < argv.length; i++) {
|
|
4423
|
+
if (++cooperativeWork % 64 === 0)
|
|
4424
|
+
yield;
|
|
4104
4425
|
const t = argv[i];
|
|
4105
4426
|
if (t === "--help" || t === "-help" || t === "-h") {
|
|
4106
4427
|
return {
|
|
@@ -4119,7 +4440,8 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4119
4440
|
lowlightColor = parseColor2(argv[++i] ?? "#ffffff");
|
|
4120
4441
|
} else if (t === "-compose") {
|
|
4121
4442
|
const cm = (argv[++i] ?? "over").toLowerCase();
|
|
4122
|
-
if (cm === "src" || cm === "source" || cm === "copy")
|
|
4443
|
+
if (cm === "src" || cm === "source" || cm === "copy")
|
|
4444
|
+
composeSrc = true;
|
|
4123
4445
|
} else if (t === "-dissimilarity-threshold") {
|
|
4124
4446
|
dissimilarityThreshold = Number(argv[++i] ?? 1);
|
|
4125
4447
|
} else if (t === "-density") {
|
|
@@ -4128,7 +4450,8 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4128
4450
|
} else if (t === "-quality") {
|
|
4129
4451
|
state.quality = Math.max(1, Math.min(100, Number(argv[++i] ?? 92)));
|
|
4130
4452
|
} else if (t.startsWith("-") && t.length > 1) {
|
|
4131
|
-
if (t === "-format" || t === "-alpha" || t === "-channel")
|
|
4453
|
+
if (t === "-format" || t === "-alpha" || t === "-channel")
|
|
4454
|
+
i++;
|
|
4132
4455
|
} else {
|
|
4133
4456
|
operands.push(t);
|
|
4134
4457
|
}
|
|
@@ -4185,7 +4508,11 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4185
4508
|
let sumLumA = 0;
|
|
4186
4509
|
let sumLumB = 0;
|
|
4187
4510
|
for (let y = 0; y < height; y++) {
|
|
4511
|
+
if (++cooperativeWork % 64 === 0)
|
|
4512
|
+
yield;
|
|
4188
4513
|
for (let x = 0; x < width; x++) {
|
|
4514
|
+
if (++cooperativeWork % 64 === 0)
|
|
4515
|
+
yield;
|
|
4189
4516
|
const pIdx = y * width + x;
|
|
4190
4517
|
const outOff = pIdx * 4;
|
|
4191
4518
|
const inBoundsA = x < imgA.width && y < imgA.height;
|
|
@@ -4240,7 +4567,8 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4240
4567
|
sumAbs += dr + dg + db;
|
|
4241
4568
|
sumSq += dr * dr + dg * dg + db * db;
|
|
4242
4569
|
}
|
|
4243
|
-
if (maxDelta > maxAbs)
|
|
4570
|
+
if (maxDelta > maxAbs)
|
|
4571
|
+
maxAbs = maxDelta;
|
|
4244
4572
|
const lA = (0.299 * rA + 0.587 * gA + 0.114 * bA) / 255;
|
|
4245
4573
|
const lB = (0.299 * rB + 0.587 * gB + 0.114 * bB) / 255;
|
|
4246
4574
|
lumA[pIdx] = lA;
|
|
@@ -4260,6 +4588,8 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4260
4588
|
let varB = 0;
|
|
4261
4589
|
let covAB = 0;
|
|
4262
4590
|
for (let i = 0; i < totalPixels; i++) {
|
|
4591
|
+
if (++cooperativeWork % 64 === 0)
|
|
4592
|
+
yield;
|
|
4263
4593
|
const dA = lumA[i] - muA;
|
|
4264
4594
|
const dB = lumB[i] - muB;
|
|
4265
4595
|
varA += dA * dA;
|
|
@@ -4337,10 +4667,19 @@ function runCompareCliSync(argv, files, stdinBytes) {
|
|
|
4337
4667
|
`
|
|
4338
4668
|
};
|
|
4339
4669
|
}
|
|
4340
|
-
async function
|
|
4341
|
-
return
|
|
4670
|
+
async function runCompareCli(argv, files, stdinBytes, signal) {
|
|
4671
|
+
return drainSteps(runCompareCliSteps(argv, files, stdinBytes, signal), signal);
|
|
4342
4672
|
}
|
|
4343
|
-
function
|
|
4673
|
+
function runCompareCliSync(argv, files, stdinBytes, signal) {
|
|
4674
|
+
const steps = runCompareCliSteps(argv, files, stdinBytes, signal);
|
|
4675
|
+
let next = steps.next();
|
|
4676
|
+
while (!next.done) {
|
|
4677
|
+
next = steps.next();
|
|
4678
|
+
}
|
|
4679
|
+
return next.value;
|
|
4680
|
+
}
|
|
4681
|
+
function* runMontageCliSteps(argv, files, stdinBytes, signal) {
|
|
4682
|
+
let cooperativeWork = 63;
|
|
4344
4683
|
const state = createDefaultState();
|
|
4345
4684
|
let tileCols;
|
|
4346
4685
|
let tileRows;
|
|
@@ -4351,6 +4690,8 @@ function runMontageCliSync(argv, files, stdinBytes) {
|
|
|
4351
4690
|
let borderW = 0;
|
|
4352
4691
|
const operands = [];
|
|
4353
4692
|
for (let i = 0; i < argv.length; i++) {
|
|
4693
|
+
if (++cooperativeWork % 64 === 0)
|
|
4694
|
+
yield;
|
|
4354
4695
|
const t = argv[i];
|
|
4355
4696
|
if (t === "-tile") {
|
|
4356
4697
|
const g = parseMagickGeometry(argv[++i] ?? "2x2");
|
|
@@ -4391,6 +4732,7 @@ function runMontageCliSync(argv, files, stdinBytes) {
|
|
|
4391
4732
|
const inPaths = operands.slice(0, -1);
|
|
4392
4733
|
const images = [];
|
|
4393
4734
|
for (const p of inPaths) {
|
|
4735
|
+
yield;
|
|
4394
4736
|
let loadedList;
|
|
4395
4737
|
try {
|
|
4396
4738
|
loadedList = parseInputOperands(p, files, state, stdinBytes);
|
|
@@ -4411,6 +4753,8 @@ function runMontageCliSync(argv, files, stdinBytes) {
|
|
|
4411
4753
|
};
|
|
4412
4754
|
}
|
|
4413
4755
|
for (const loaded of loadedList) {
|
|
4756
|
+
if (++cooperativeWork % 64 === 0)
|
|
4757
|
+
yield;
|
|
4414
4758
|
let thumb = loaded;
|
|
4415
4759
|
if (cellW !== void 0 || cellH !== void 0) {
|
|
4416
4760
|
const geomSpec = `${cellW ?? ""}${cellH !== void 0 ? "x" + cellH : ""}`;
|
|
@@ -4441,9 +4785,12 @@ function runMontageCliSync(argv, files, stdinBytes) {
|
|
|
4441
4785
|
const canvas = createSolidRgbaImage(canvasW, canvasH, state.background);
|
|
4442
4786
|
const layers = [];
|
|
4443
4787
|
for (let idx = 0; idx < images.length; idx++) {
|
|
4788
|
+
if (++cooperativeWork % 64 === 0)
|
|
4789
|
+
yield;
|
|
4444
4790
|
const col = idx % cols;
|
|
4445
4791
|
const row = Math.floor(idx / cols);
|
|
4446
|
-
if (row >= rows)
|
|
4792
|
+
if (row >= rows)
|
|
4793
|
+
break;
|
|
4447
4794
|
const im = images[idx];
|
|
4448
4795
|
const cellX = col * slotW + padX;
|
|
4449
4796
|
const cellY = row * slotH + padY;
|
|
@@ -4459,32 +4806,52 @@ function runMontageCliSync(argv, files, stdinBytes) {
|
|
|
4459
4806
|
files.set(outPath, encoded);
|
|
4460
4807
|
return { exitCode: 0, stdout: "", stderr: "" };
|
|
4461
4808
|
}
|
|
4462
|
-
async function
|
|
4463
|
-
return
|
|
4809
|
+
async function runMontageCli(argv, files, stdinBytes, signal) {
|
|
4810
|
+
return drainSteps(runMontageCliSteps(argv, files, stdinBytes, signal), signal);
|
|
4811
|
+
}
|
|
4812
|
+
function runMontageCliSync(argv, files, stdinBytes, signal) {
|
|
4813
|
+
const steps = runMontageCliSteps(argv, files, stdinBytes, signal);
|
|
4814
|
+
let next = steps.next();
|
|
4815
|
+
while (!next.done) {
|
|
4816
|
+
next = steps.next();
|
|
4817
|
+
}
|
|
4818
|
+
return next.value;
|
|
4464
4819
|
}
|
|
4465
|
-
function
|
|
4820
|
+
function* runMagickCliSteps(argv, files, stdinBytes, signal) {
|
|
4466
4821
|
const sub = argv[0];
|
|
4467
4822
|
if (sub === "identify") {
|
|
4468
|
-
return
|
|
4823
|
+
return yield* runIdentifyCliSteps(argv.slice(1), files, stdinBytes, signal);
|
|
4469
4824
|
}
|
|
4470
4825
|
if (sub === "mogrify") {
|
|
4471
|
-
return
|
|
4826
|
+
return yield* runMogrifyCliSteps(argv.slice(1), files, void 0, signal);
|
|
4472
4827
|
}
|
|
4473
4828
|
if (sub === "composite") {
|
|
4474
|
-
return
|
|
4829
|
+
return yield* runCompositeCliSteps(argv.slice(1), files, stdinBytes, signal);
|
|
4475
4830
|
}
|
|
4476
4831
|
if (sub === "montage") {
|
|
4477
|
-
return
|
|
4832
|
+
return yield* runMontageCliSteps(argv.slice(1), files, stdinBytes, signal);
|
|
4478
4833
|
}
|
|
4479
4834
|
if (sub === "compare") {
|
|
4480
|
-
return
|
|
4835
|
+
return yield* runCompareCliSteps(argv.slice(1), files, stdinBytes, signal);
|
|
4481
4836
|
}
|
|
4482
4837
|
if (sub === "convert") {
|
|
4483
|
-
return
|
|
4838
|
+
return yield* runConvertCliSteps(argv.slice(1), files, stdinBytes, signal);
|
|
4484
4839
|
}
|
|
4485
|
-
return
|
|
4840
|
+
return yield* runConvertCliSteps(argv, files, stdinBytes, signal);
|
|
4841
|
+
}
|
|
4842
|
+
async function runMagickCli(argv, files, stdinBytes, signal) {
|
|
4843
|
+
return drainSteps(runMagickCliSteps(argv, files, stdinBytes, signal), signal);
|
|
4844
|
+
}
|
|
4845
|
+
function runMagickCliSync(argv, files, stdinBytes, signal) {
|
|
4846
|
+
const steps = runMagickCliSteps(argv, files, stdinBytes, signal);
|
|
4847
|
+
let next = steps.next();
|
|
4848
|
+
while (!next.done) {
|
|
4849
|
+
next = steps.next();
|
|
4850
|
+
}
|
|
4851
|
+
return next.value;
|
|
4486
4852
|
}
|
|
4487
4853
|
async function executeVfsMagickTool(context, runner) {
|
|
4854
|
+
let cooperativeWork = 63;
|
|
4488
4855
|
const invocation = createOutputOperation(context, { write: async () => {
|
|
4489
4856
|
} });
|
|
4490
4857
|
try {
|
|
@@ -4495,6 +4862,7 @@ async function executeVfsMagickTool(context, runner) {
|
|
|
4495
4862
|
let needsStdin = false;
|
|
4496
4863
|
const hasOutputOperand = runner !== runIdentifyCli && !(runner === runMagickCli && argv[0] === "identify");
|
|
4497
4864
|
for (const [index, token] of argv.entries()) {
|
|
4865
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn(context.signal);
|
|
4498
4866
|
if (token === "-" || token.endsWith(":-")) {
|
|
4499
4867
|
if (!hasOutputOperand || index < argv.length - 1) needsStdin = true;
|
|
4500
4868
|
continue;
|
|
@@ -4522,18 +4890,21 @@ async function executeVfsMagickTool(context, runner) {
|
|
|
4522
4890
|
const chunks = [];
|
|
4523
4891
|
let total = 0;
|
|
4524
4892
|
for await (const chunk of readBytes(context.stdin, invocation.signal)) {
|
|
4893
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn(context.signal);
|
|
4525
4894
|
chunks.push(chunk);
|
|
4526
4895
|
total += chunk.byteLength;
|
|
4527
4896
|
}
|
|
4528
4897
|
stdinBytes = new Uint8Array(total);
|
|
4529
4898
|
let off = 0;
|
|
4530
4899
|
for (const chunk of chunks) {
|
|
4900
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn(context.signal);
|
|
4531
4901
|
stdinBytes.set(chunk, off);
|
|
4532
4902
|
off += chunk.byteLength;
|
|
4533
4903
|
}
|
|
4534
4904
|
}
|
|
4905
|
+
context.inputBudget?.check(0);
|
|
4535
4906
|
const existingSnap = new Map(vfsFiles);
|
|
4536
|
-
const res = await runner(argv, vfsFiles, stdinBytes);
|
|
4907
|
+
const res = await runner(argv, vfsFiles, stdinBytes, invocation.signal);
|
|
4537
4908
|
if (res.stderr) {
|
|
4538
4909
|
await writeBytes(context.stderr, new TextEncoder().encode(res.stderr), invocation.signal);
|
|
4539
4910
|
}
|
|
@@ -4545,6 +4916,7 @@ async function executeVfsMagickTool(context, runner) {
|
|
|
4545
4916
|
await writeBytes(stdout.output, new TextEncoder().encode(res.stdout), invocation.signal);
|
|
4546
4917
|
}
|
|
4547
4918
|
for (const [key, val] of vfsFiles.entries()) {
|
|
4919
|
+
if (++cooperativeWork % 64 === 0) await yieldTurn(context.signal);
|
|
4548
4920
|
if (existingSnap.get(key) !== val) {
|
|
4549
4921
|
const abs = resolveVfsPath(key);
|
|
4550
4922
|
const parentDir = abs.slice(0, abs.lastIndexOf("/")) || "/";
|
|
@@ -4560,79 +4932,100 @@ async function executeVfsMagickTool(context, runner) {
|
|
|
4560
4932
|
await invocation.close();
|
|
4561
4933
|
}
|
|
4562
4934
|
}
|
|
4563
|
-
function createMagickCommand(
|
|
4935
|
+
function createMagickCommand(options = {}) {
|
|
4936
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4564
4937
|
return Object.freeze({
|
|
4565
4938
|
name: "magick",
|
|
4566
4939
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4567
4940
|
description: "ImageMagick v7 image processor powered by @poe-code/image-ast",
|
|
4568
4941
|
execute(context) {
|
|
4569
|
-
return
|
|
4942
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
4943
|
+
return executeVfsMagickTool(context2, runMagickCli);
|
|
4944
|
+
});
|
|
4570
4945
|
}
|
|
4571
4946
|
});
|
|
4572
4947
|
}
|
|
4573
4948
|
var magickCommand = createMagickCommand();
|
|
4574
|
-
function createConvertCommand(
|
|
4949
|
+
function createConvertCommand(options = {}) {
|
|
4950
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4575
4951
|
return Object.freeze({
|
|
4576
4952
|
name: "convert",
|
|
4577
4953
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4578
4954
|
description: "ImageMagick convert pipeline powered by @poe-code/image-ast",
|
|
4579
4955
|
execute(context) {
|
|
4580
|
-
return
|
|
4956
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
4957
|
+
return executeVfsMagickTool(context2, runConvertCli);
|
|
4958
|
+
});
|
|
4581
4959
|
}
|
|
4582
4960
|
});
|
|
4583
4961
|
}
|
|
4584
4962
|
var convertCommand = createConvertCommand();
|
|
4585
|
-
function createMogrifyCommand(
|
|
4963
|
+
function createMogrifyCommand(options = {}) {
|
|
4964
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4586
4965
|
return Object.freeze({
|
|
4587
4966
|
name: "mogrify",
|
|
4588
4967
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4589
4968
|
description: "ImageMagick in-place batch image processor powered by @poe-code/image-ast",
|
|
4590
4969
|
execute(context) {
|
|
4591
|
-
return
|
|
4970
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
4971
|
+
return executeVfsMagickTool(context2, runMogrifyCli);
|
|
4972
|
+
});
|
|
4592
4973
|
}
|
|
4593
4974
|
});
|
|
4594
4975
|
}
|
|
4595
4976
|
var mogrifyCommand = createMogrifyCommand();
|
|
4596
|
-
function createCompositeCommand(
|
|
4977
|
+
function createCompositeCommand(options = {}) {
|
|
4978
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4597
4979
|
return Object.freeze({
|
|
4598
4980
|
name: "composite",
|
|
4599
4981
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4600
4982
|
description: "ImageMagick overlay composition tool powered by @poe-code/image-ast",
|
|
4601
4983
|
execute(context) {
|
|
4602
|
-
return
|
|
4984
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
4985
|
+
return executeVfsMagickTool(context2, runCompositeCli);
|
|
4986
|
+
});
|
|
4603
4987
|
}
|
|
4604
4988
|
});
|
|
4605
4989
|
}
|
|
4606
4990
|
var compositeCommand = createCompositeCommand();
|
|
4607
|
-
function createMontageCommand(
|
|
4991
|
+
function createMontageCommand(options = {}) {
|
|
4992
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4608
4993
|
return Object.freeze({
|
|
4609
4994
|
name: "montage",
|
|
4610
4995
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4611
4996
|
description: "ImageMagick contact-sheet grid generator powered by @poe-code/image-ast",
|
|
4612
4997
|
execute(context) {
|
|
4613
|
-
return
|
|
4998
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
4999
|
+
return executeVfsMagickTool(context2, runMontageCli);
|
|
5000
|
+
});
|
|
4614
5001
|
}
|
|
4615
5002
|
});
|
|
4616
5003
|
}
|
|
4617
5004
|
var montageCommand = createMontageCommand();
|
|
4618
|
-
function createIdentifyCommand(
|
|
5005
|
+
function createIdentifyCommand(options = {}) {
|
|
5006
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4619
5007
|
return Object.freeze({
|
|
4620
5008
|
name: "identify",
|
|
4621
5009
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4622
5010
|
description: "ImageMagick image metadata inspector powered by @poe-code/image-ast",
|
|
4623
5011
|
execute(context) {
|
|
4624
|
-
return
|
|
5012
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
5013
|
+
return executeVfsMagickTool(context2, runIdentifyCli);
|
|
5014
|
+
});
|
|
4625
5015
|
}
|
|
4626
5016
|
});
|
|
4627
5017
|
}
|
|
4628
5018
|
var identifyCommand = createIdentifyCommand();
|
|
4629
|
-
function createCompareCommand(
|
|
5019
|
+
function createCompareCommand(options = {}) {
|
|
5020
|
+
const maxInputBytes = InputByteBudget.limit(options.limits?.maxInputBytes);
|
|
4630
5021
|
return Object.freeze({
|
|
4631
5022
|
name: "compare",
|
|
4632
5023
|
runtimeIdentity: commandRuntimeIdentity,
|
|
4633
5024
|
description: "ImageMagick image comparison and diff generator powered by @poe-code/image-ast",
|
|
4634
5025
|
execute(context) {
|
|
4635
|
-
return
|
|
5026
|
+
return new InputByteBudget(maxInputBytes).run(context, async (context2) => {
|
|
5027
|
+
return executeVfsMagickTool(context2, runCompareCli);
|
|
5028
|
+
});
|
|
4636
5029
|
}
|
|
4637
5030
|
});
|
|
4638
5031
|
}
|
|
@@ -4663,6 +5056,11 @@ var imagemagickCommands = imagemagickPlugin;
|
|
|
4663
5056
|
function createImagemagickCommands(options = {}) {
|
|
4664
5057
|
return [createMagickCommand(options), createConvertCommand(options), createMogrifyCommand(options), createCompositeCommand(options), createMontageCommand(options), createIdentifyCommand(options), createCompareCommand(options)];
|
|
4665
5058
|
}
|
|
5059
|
+
function* mapSteps(values, mapper) {
|
|
5060
|
+
const result = [];
|
|
5061
|
+
for (const value of values) result.push(yield* mapper(value));
|
|
5062
|
+
return result;
|
|
5063
|
+
}
|
|
4666
5064
|
export {
|
|
4667
5065
|
compareCommand,
|
|
4668
5066
|
compositeCommand,
|