@pixerate/editor 0.130.0 → 0.133.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-editor/index.cjs +55 -55
- package/dist/animation-editor/index.d.cts +4 -4
- package/dist/animation-editor/index.d.ts +4 -4
- package/dist/animation-editor/index.js +2 -2
- package/dist/{bezier-CigmusV_.d.ts → bezier-BAGdL89w.d.ts} +1 -1
- package/dist/{bezier-CdoGygwG.d.cts → bezier-DL2wPsFf.d.cts} +1 -1
- package/dist/canvas/index.d.cts +7 -7
- package/dist/canvas/index.d.ts +7 -7
- package/dist/{chunk-MZXQTKUM.cjs → chunk-24ATT2PE.cjs} +10 -6
- package/dist/chunk-24ATT2PE.cjs.map +1 -0
- package/dist/{chunk-AHUYMDYW.js → chunk-2HC4DRF4.js} +10 -6
- package/dist/chunk-2HC4DRF4.js.map +1 -0
- package/dist/{chunk-2PXRKMOH.cjs → chunk-2QKUD3E2.cjs} +36 -36
- package/dist/{chunk-2PXRKMOH.cjs.map → chunk-2QKUD3E2.cjs.map} +1 -1
- package/dist/{chunk-PMHPXCJC.cjs → chunk-65GNHOD4.cjs} +268 -199
- package/dist/chunk-65GNHOD4.cjs.map +1 -0
- package/dist/{chunk-YRZ6NVE3.js → chunk-6CTZAGZ2.js} +235 -4
- package/dist/chunk-6CTZAGZ2.js.map +1 -0
- package/dist/{chunk-ERYGCA72.js → chunk-AOCFL7L7.js} +88 -19
- package/dist/chunk-AOCFL7L7.js.map +1 -0
- package/dist/{chunk-LXGOYRPE.cjs → chunk-F7GGEAO2.cjs} +322 -75
- package/dist/chunk-F7GGEAO2.cjs.map +1 -0
- package/dist/{chunk-PRYMC442.js → chunk-FOBB6AIO.js} +257 -10
- package/dist/chunk-FOBB6AIO.js.map +1 -0
- package/dist/{chunk-W6M7C7R3.cjs → chunk-NVTHUPJ6.cjs} +236 -5
- package/dist/chunk-NVTHUPJ6.cjs.map +1 -0
- package/dist/{chunk-L5OTIYOO.js → chunk-VGZSIXX3.js} +2 -2
- package/dist/effects/index.d.cts +4 -4
- package/dist/effects/index.d.ts +4 -4
- package/dist/{export-CejjC2iI.d.cts → export-BICOEM9d.d.cts} +33 -11
- package/dist/{export-5WDKJqTy.d.cts → export-CeFplzAW.d.cts} +1 -1
- package/dist/{export-B4r8b9Ft.d.ts → export-XnuX8FZ2.d.ts} +33 -11
- package/dist/{export-CU_ARP3A.d.ts → export-zB4HITwP.d.ts} +1 -1
- package/dist/{helpers-CzZu51eI.d.cts → helpers-BuKdqUlM.d.cts} +56 -1
- package/dist/{helpers-X_rycLNJ.d.ts → helpers-cssRNUzH.d.ts} +56 -1
- package/dist/image-editor/index.cjs +1064 -903
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +32 -13
- package/dist/image-editor/index.d.ts +32 -13
- package/dist/image-editor/index.js +180 -19
- package/dist/image-editor/index.js.map +1 -1
- package/dist/index.cjs +11 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/{opentype-DlRMYcCW.d.cts → opentype-C3iyIFRx.d.cts} +1 -1
- package/dist/{opentype-CrHAsKh3.d.ts → opentype-DG5Lkwul.d.ts} +1 -1
- package/dist/paint/index.cjs +8 -2
- package/dist/paint/index.cjs.map +1 -1
- package/dist/paint/index.d.cts +14 -3
- package/dist/paint/index.d.ts +14 -3
- package/dist/paint/index.js +7 -1
- package/dist/paint-editor/index.cjs +78 -78
- package/dist/paint-editor/index.d.cts +7 -7
- package/dist/paint-editor/index.d.ts +7 -7
- package/dist/paint-editor/index.js +3 -3
- package/dist/{pathfinder-CKfKOVP4.d.cts → pathfinder-8vXik95z.d.cts} +1 -1
- package/dist/{pathfinder-Dlss70hL.d.ts → pathfinder-DKLt4UDG.d.ts} +1 -1
- package/dist/{pool-DDOo0xJH.d.ts → pool-C69pkWRz.d.ts} +1 -1
- package/dist/{pool-DKic69LD.d.cts → pool-VAWcYUbs.d.cts} +1 -1
- package/dist/{rand-pQQ2sJTk.d.ts → rand-BaqEOs1Y.d.ts} +17 -4
- package/dist/{rand-DTXAssW1.d.cts → rand-DdpFzCo6.d.cts} +17 -4
- package/dist/raster/index.cjs +2 -2
- package/dist/raster/index.d.cts +4 -4
- package/dist/raster/index.d.ts +4 -4
- package/dist/raster/index.js +1 -1
- package/dist/{svg-BRaii3pI.d.cts → svg-BThlZmja.d.cts} +2 -2
- package/dist/{svg-BYVZeVo0.d.ts → svg-CEYpvsgH.d.ts} +2 -2
- package/dist/{tools-CtheDLDr.d.cts → tools-CRnZJXXr.d.cts} +1 -1
- package/dist/{tools-D8bZ-7YG.d.ts → tools-CVGqEpO8.d.ts} +1 -1
- package/dist/vector/index.cjs +1493 -1032
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +155 -12
- package/dist/vector/index.d.ts +155 -12
- package/dist/vector/index.js +469 -8
- package/dist/vector/index.js.map +1 -1
- package/dist/video-editor/index.d.cts +4 -4
- package/dist/video-editor/index.d.ts +4 -4
- package/dist/{warp-BFoYxy_s.d.cts → warp-ChcFDdlT.d.cts} +1 -1
- package/dist/{warp-CZVC8pB5.d.ts → warp-mKylbLiF.d.ts} +1 -1
- package/package.json +2 -2
- package/skills/pixerate-image-editor/SKILL.md +7 -3
- package/skills/pixerate-image-editor/references/color-management.md +1 -1
- package/skills/pixerate-image-editor/references/photoshop-files.md +2 -2
- package/skills/pixerate-image-editor/references/retouching.md +12 -3
- package/skills/pixerate-vector/SKILL.md +17 -0
- package/skills/pixerate-vector/references/commands.md +19 -0
- package/dist/chunk-AHUYMDYW.js.map +0 -1
- package/dist/chunk-ERYGCA72.js.map +0 -1
- package/dist/chunk-LXGOYRPE.cjs.map +0 -1
- package/dist/chunk-MZXQTKUM.cjs.map +0 -1
- package/dist/chunk-PMHPXCJC.cjs.map +0 -1
- package/dist/chunk-PRYMC442.js.map +0 -1
- package/dist/chunk-W6M7C7R3.cjs.map +0 -1
- package/dist/chunk-YRZ6NVE3.js.map +0 -1
- /package/dist/{chunk-L5OTIYOO.js.map → chunk-VGZSIXX3.js.map} +0 -0
|
@@ -75,6 +75,7 @@ import {
|
|
|
75
75
|
applyDepthMask,
|
|
76
76
|
applyImageProjectionToContext,
|
|
77
77
|
applyLegacyAdjustments,
|
|
78
|
+
applyLegacyFloat,
|
|
78
79
|
applyMatrix3,
|
|
79
80
|
applyParams,
|
|
80
81
|
applyProcess2Adjustments,
|
|
@@ -362,7 +363,7 @@ import {
|
|
|
362
363
|
writePsd,
|
|
363
364
|
xyToTempTint,
|
|
364
365
|
xyToUv
|
|
365
|
-
} from "../chunk-
|
|
366
|
+
} from "../chunk-AOCFL7L7.js";
|
|
366
367
|
import {
|
|
367
368
|
parseCssColor
|
|
368
369
|
} from "../chunk-CTTF4KYV.js";
|
|
@@ -426,7 +427,7 @@ import {
|
|
|
426
427
|
validateLayerEffects,
|
|
427
428
|
warpSurface,
|
|
428
429
|
workingToSamples
|
|
429
|
-
} from "../chunk-
|
|
430
|
+
} from "../chunk-2HC4DRF4.js";
|
|
430
431
|
import {
|
|
431
432
|
applyHomography,
|
|
432
433
|
boxQuad,
|
|
@@ -447,6 +448,8 @@ import {
|
|
|
447
448
|
applyRetouchToTile,
|
|
448
449
|
applyToneToDeepTile,
|
|
449
450
|
bestOffset,
|
|
451
|
+
boxBlurPixels,
|
|
452
|
+
contentAwareFill,
|
|
450
453
|
dilateMask,
|
|
451
454
|
dodgeBurn,
|
|
452
455
|
dodgeBurnCurve,
|
|
@@ -457,6 +460,7 @@ import {
|
|
|
457
460
|
normalizeRetouch,
|
|
458
461
|
perDabStrength,
|
|
459
462
|
readSourceRegion,
|
|
463
|
+
retouchFilter,
|
|
460
464
|
rgbaViewOfGrey,
|
|
461
465
|
saturationOf,
|
|
462
466
|
seamlessClone,
|
|
@@ -467,7 +471,7 @@ import {
|
|
|
467
471
|
spotHealPixels,
|
|
468
472
|
spotHealWindow,
|
|
469
473
|
toneOf
|
|
470
|
-
} from "../chunk-
|
|
474
|
+
} from "../chunk-6CTZAGZ2.js";
|
|
471
475
|
import {
|
|
472
476
|
BrushstrokeCache,
|
|
473
477
|
brushstrokeDataUrl,
|
|
@@ -802,7 +806,7 @@ import {
|
|
|
802
806
|
warpMeshParamAt,
|
|
803
807
|
warpMeshRows,
|
|
804
808
|
warpPresetMesh
|
|
805
|
-
} from "../chunk-
|
|
809
|
+
} from "../chunk-FOBB6AIO.js";
|
|
806
810
|
import "../chunk-YGJIER2R.js";
|
|
807
811
|
import "../chunk-KHNZ6MOU.js";
|
|
808
812
|
import {
|
|
@@ -1332,6 +1336,27 @@ var ImageEditorRenderer = class {
|
|
|
1332
1336
|
}
|
|
1333
1337
|
ctx.restore();
|
|
1334
1338
|
}
|
|
1339
|
+
if (options.cloneSourceMarker) {
|
|
1340
|
+
const m = projectImagePoint(options.cloneSourceMarker, projection);
|
|
1341
|
+
ctx.save();
|
|
1342
|
+
try {
|
|
1343
|
+
const r = 7;
|
|
1344
|
+
ctx.beginPath();
|
|
1345
|
+
ctx.arc(m.x, m.y, r, 0, Math.PI * 2);
|
|
1346
|
+
ctx.moveTo(m.x - r - 4, m.y);
|
|
1347
|
+
ctx.lineTo(m.x + r + 4, m.y);
|
|
1348
|
+
ctx.moveTo(m.x, m.y - r - 4);
|
|
1349
|
+
ctx.lineTo(m.x, m.y + r + 4);
|
|
1350
|
+
ctx.lineWidth = 3;
|
|
1351
|
+
ctx.strokeStyle = "rgba(0,0,0,0.6)";
|
|
1352
|
+
ctx.stroke();
|
|
1353
|
+
ctx.lineWidth = 1;
|
|
1354
|
+
ctx.strokeStyle = "#ffffff";
|
|
1355
|
+
ctx.stroke();
|
|
1356
|
+
} catch {
|
|
1357
|
+
}
|
|
1358
|
+
ctx.restore();
|
|
1359
|
+
}
|
|
1335
1360
|
if (options.textEdit) {
|
|
1336
1361
|
const t = options.textEdit;
|
|
1337
1362
|
ctx.save();
|
|
@@ -3492,6 +3517,19 @@ function colorModePlanes(doc, mode) {
|
|
|
3492
3517
|
return planes;
|
|
3493
3518
|
};
|
|
3494
3519
|
}
|
|
3520
|
+
function colorModePlanes16(doc, mode) {
|
|
3521
|
+
const src = resolveProfile(doc);
|
|
3522
|
+
const cmyk = mode.mode === "cmyk";
|
|
3523
|
+
const t = cmyk ? Transform.create(src, resolveProfile(mode.profile), { intent: mode.intent, bpc: true }) : Transform.create(src, builtinProfile("lab-d50"), { intent: "relative", bpc: false });
|
|
3524
|
+
const k = cmyk ? 4 : 3;
|
|
3525
|
+
return (rgba, n) => {
|
|
3526
|
+
const out = new Uint16Array(n * 4);
|
|
3527
|
+
t.convert16(rgba, 4, out, 4, false);
|
|
3528
|
+
const planes = Array.from({ length: k }, () => new Uint16Array(n));
|
|
3529
|
+
for (let i = 0; i < n; i++) for (let c = 0; c < k; c++) planes[c][i] = cmyk ? 65535 - out[i * 4 + c] : out[i * 4 + c];
|
|
3530
|
+
return planes;
|
|
3531
|
+
};
|
|
3532
|
+
}
|
|
3495
3533
|
var resolved = /* @__PURE__ */ new WeakMap();
|
|
3496
3534
|
var fromBytes = /* @__PURE__ */ new Map();
|
|
3497
3535
|
function resolveProfile(doc) {
|
|
@@ -3651,7 +3689,7 @@ function convertSurfaceColors(surface, t) {
|
|
|
3651
3689
|
|
|
3652
3690
|
// src/image-editor/controller.ts
|
|
3653
3691
|
var IMAGE_EDITOR_SCHEMA_VERSION = LAYERED_SCHEMA_VERSION;
|
|
3654
|
-
var RETOUCH_TOOLS = ["clone", "heal", "spot-heal", "smudge", "dodge", "burn", "sponge"];
|
|
3692
|
+
var RETOUCH_TOOLS = ["clone", "heal", "spot-heal", "smudge", "dodge", "burn", "sponge", "blur", "sharpen", "history"];
|
|
3655
3693
|
var isRetouchTool = (tool) => RETOUCH_TOOLS.includes(tool);
|
|
3656
3694
|
var STROKE_TOOLS = ["brush", "eraser", "mixer", ...RETOUCH_TOOLS];
|
|
3657
3695
|
function paintCoverageInto(base, coverage, apply, rects, depth = null) {
|
|
@@ -3925,6 +3963,18 @@ var PaintStrokeSession = class {
|
|
|
3925
3963
|
this.controller._strokeCommit(this.before, this.target.id, this.target.channel, null);
|
|
3926
3964
|
}
|
|
3927
3965
|
};
|
|
3966
|
+
function workRegionOf(surface, rect, depth) {
|
|
3967
|
+
if (!depth) return Float32Array.from(readRegion(surface, rect));
|
|
3968
|
+
const d = readDeepRegion(surface, rect, depth);
|
|
3969
|
+
const out = new Float32Array(d.length);
|
|
3970
|
+
if (d instanceof Uint16Array) {
|
|
3971
|
+
for (let i = 0; i < d.length; i++) out[i] = d[i] / 257;
|
|
3972
|
+
return out;
|
|
3973
|
+
}
|
|
3974
|
+
const ch = surface.channels;
|
|
3975
|
+
for (let i = 0; i < d.length; i++) out[i] = (ch === 4 && (i & 3) !== 3 ? srgbEncode(d[i]) : d[i]) * 255;
|
|
3976
|
+
return out;
|
|
3977
|
+
}
|
|
3928
3978
|
function workTileOf(tile) {
|
|
3929
3979
|
if (!tile) return null;
|
|
3930
3980
|
const d = tile.deep;
|
|
@@ -6124,7 +6174,7 @@ var ImageEditorController = class {
|
|
|
6124
6174
|
if (tool === "smudge") return { kind: "dabs", create: (pixels) => new RetouchDabStroke(brush, pixels, smudgeEffect(brush, settings.strength)) };
|
|
6125
6175
|
if (tool === "sponge") return { kind: "dabs", create: (pixels) => new RetouchDabStroke(brush, pixels, spongeEffect(brush, settings.spongeMode === "saturate", settings.vibrance)) };
|
|
6126
6176
|
const retouchApply = {
|
|
6127
|
-
opacity: tool === "clone" || tool === "heal" ? brush.opacity : 1,
|
|
6177
|
+
opacity: tool === "clone" || tool === "heal" || tool === "history" ? brush.opacity : tool === "blur" || tool === "sharpen" ? brush.opacity * settings.strength : 1,
|
|
6128
6178
|
blend: tool === "clone" && !mask ? brush.blend : "normal",
|
|
6129
6179
|
lockTransparency: target.lockTransparency,
|
|
6130
6180
|
selection: apply.selection,
|
|
@@ -6136,6 +6186,41 @@ var ImageEditorController = class {
|
|
|
6136
6186
|
return { kind: "coverage", coverage, apply: retouchApply, start: () => {
|
|
6137
6187
|
}, paint: () => paint2 };
|
|
6138
6188
|
}
|
|
6189
|
+
if (tool === "blur" || tool === "sharpen") {
|
|
6190
|
+
const n = target.surface.channels;
|
|
6191
|
+
const depth = !mask && this.bitDepth !== 8 ? this.bitDepth : null;
|
|
6192
|
+
const m = 6;
|
|
6193
|
+
const filtered = new TilePixelSource(
|
|
6194
|
+
(tx, ty) => {
|
|
6195
|
+
const r = { x: tx * TILE - m, y: ty * TILE - m, width: TILE + 2 * m, height: TILE + 2 * m };
|
|
6196
|
+
const d = workRegionOf(target.surface, r, depth);
|
|
6197
|
+
retouchFilter(d, r.width, r.height, n, tool, 2, 1.2);
|
|
6198
|
+
const out = new Float32Array(TILE * TILE * n);
|
|
6199
|
+
for (let y = 0; y < TILE; y++) out.set(d.subarray(((y + m) * r.width + m) * n, ((y + m) * r.width + m + TILE) * n), y * TILE * n);
|
|
6200
|
+
return out;
|
|
6201
|
+
},
|
|
6202
|
+
n,
|
|
6203
|
+
target.offset
|
|
6204
|
+
);
|
|
6205
|
+
const paint2 = { kind: "source", source: filtered, dx: 0, dy: 0 };
|
|
6206
|
+
return { kind: "coverage", coverage, apply: retouchApply, start: () => {
|
|
6207
|
+
}, paint: () => paint2 };
|
|
6208
|
+
}
|
|
6209
|
+
if (tool === "history") {
|
|
6210
|
+
const steps = settings.historySteps;
|
|
6211
|
+
const entry = steps > 0 ? this.undoStack[this.undoStack.length - steps] ?? this.undoStack[0] : this.undoStack[0];
|
|
6212
|
+
if (!entry) throw new LayerOperationError("There is no earlier state to paint from yet: the History Brush paints a layer as it was some undo steps back. Make a change first.");
|
|
6213
|
+
const then = findLayer(entry.layers, target.id)?.layer;
|
|
6214
|
+
if (!then) throw new LayerOperationError(`Layer "${target.id}" did not exist ${steps > 0 ? `${steps} steps back` : "in the oldest state"}; choose fewer history steps (historySteps).`);
|
|
6215
|
+
const surface = target.channel === "mask" ? then.mask?.surface : then.type === "pixel" ? then.surface : void 0;
|
|
6216
|
+
if (!surface) throw new LayerOperationError(`Layer "${target.id}" had no ${target.channel === "mask" ? "mask" : "pixels"} in that state.`);
|
|
6217
|
+
const offset2 = then.type === "pixel" ? then.offset : { x: 0, y: 0 };
|
|
6218
|
+
const depth = !mask && this.bitDepth !== 8 ? this.bitDepth : null;
|
|
6219
|
+
const source2 = depth ? new TilePixelSource((tx, ty) => workTileOf(surface.tiles.get(tileKey(tx, ty))), 4, offset2) : this.surfaceSource(surface, offset2);
|
|
6220
|
+
const paint2 = { kind: "source", source: source2, dx: 0, dy: 0 };
|
|
6221
|
+
return { kind: "coverage", coverage, apply: retouchApply, start: () => {
|
|
6222
|
+
}, paint: () => paint2 };
|
|
6223
|
+
}
|
|
6139
6224
|
const sample = mask ? "current" : settings.sample;
|
|
6140
6225
|
const deep = !mask && this.bitDepth !== 8 ? this.bitDepth : null;
|
|
6141
6226
|
const own = deep ? new TilePixelSource((tx, ty) => workTileOf(target.surface.tiles.get(tileKey(tx, ty))), 4, target.offset) : this.surfaceSource(target.surface, target.offset);
|
|
@@ -6992,6 +7077,20 @@ var ImageEditorController = class {
|
|
|
6992
7077
|
}
|
|
6993
7078
|
return this.blankSource;
|
|
6994
7079
|
}
|
|
7080
|
+
/**
|
|
7081
|
+
* Where the Clone Stamp or Healing Brush samples for a brush at `cursor` (document pixels), or
|
|
7082
|
+
* `null` when neither tool is active or no source is set: the cursor plus the aligned offset
|
|
7083
|
+
* once a stroke has fixed it, else the source point itself (where the next stroke starts
|
|
7084
|
+
* sampling). The editors draw it as the clone source marker.
|
|
7085
|
+
*/
|
|
7086
|
+
cloneSourceMarker(cursor = null) {
|
|
7087
|
+
const s = this.state;
|
|
7088
|
+
if (s.activeTool !== "clone" && s.activeTool !== "heal") return null;
|
|
7089
|
+
const cs = s.paint.cloneSource;
|
|
7090
|
+
if (!cs) return null;
|
|
7091
|
+
if (cursor && cs.offset && s.paint.retouch.aligned) return { x: cursor.x + cs.offset.x, y: cursor.y + cs.offset.y };
|
|
7092
|
+
return { x: cs.x, y: cs.y };
|
|
7093
|
+
}
|
|
6995
7094
|
async render(targetCanvas, options) {
|
|
6996
7095
|
const source = this.drawSource();
|
|
6997
7096
|
if (!source) return;
|
|
@@ -7001,6 +7100,8 @@ var ImageEditorController = class {
|
|
|
7001
7100
|
try {
|
|
7002
7101
|
await this.renderer.renderToCanvas(targetCanvas, source, this.state, {
|
|
7003
7102
|
...options,
|
|
7103
|
+
// The clone source follows the brush cursor (both editors pass it).
|
|
7104
|
+
cloneSourceMarker: options?.cloneSourceMarker !== void 0 ? options.cloneSourceMarker : options?.brushCursor ? this.cloneSourceMarker(options.brushCursor) : null,
|
|
7004
7105
|
dirty: dirty === "all" ? void 0 : dirty,
|
|
7005
7106
|
checkpointLayerId: this.state.activeLayerId
|
|
7006
7107
|
});
|
|
@@ -7841,7 +7942,8 @@ var ImageEditorController = class {
|
|
|
7841
7942
|
warnings.push(`Adjustment layers were written with their RGB settings; in a ${m.mode.toUpperCase()} file Photoshop applies them to its own channels, so they may look different there.`);
|
|
7842
7943
|
}
|
|
7843
7944
|
const planes = colorModePlanes(this.state.colorProfile, m);
|
|
7844
|
-
|
|
7945
|
+
const planes16 = this.bitDepth === 8 ? void 0 : colorModePlanes16(this.state.colorProfile, m);
|
|
7946
|
+
return m.mode === "cmyk" ? { colorMode: "cmyk", colorPlanes: planes, colorPlanes16: planes16, iccProfile: profileBytes(m.profile) } : { colorMode: "lab", colorPlanes: planes, colorPlanes16: planes16 };
|
|
7845
7947
|
}
|
|
7846
7948
|
/** Pixels per inch of the last opened PSD (written back by `toPsd`). */
|
|
7847
7949
|
psdResolution;
|
|
@@ -8054,8 +8156,8 @@ var ImageEditorController = class {
|
|
|
8054
8156
|
for (const [msg, names] of note) warnings.push(`${msg} (${names.length === 1 ? "layer" : "layers"} ${names.map((n) => `"${n}"`).join(", ")}).`);
|
|
8055
8157
|
const merged = compositor.composite(prepared, canvas, { ...sources, version: `psd:${Date.now()}` });
|
|
8056
8158
|
const color = this.psdColorOptions(warnings);
|
|
8057
|
-
if (color.colorMode && this.bitDepth
|
|
8058
|
-
const depth = color.colorMode ?
|
|
8159
|
+
if (color.colorMode && this.bitDepth === 32) warnings.push(`${color.colorMode.toUpperCase()} files are written at 16 bits per channel at most; the 32-bit samples were converted (colour above 1 clipped).`);
|
|
8160
|
+
const depth = color.colorMode && this.bitDepth === 32 ? 16 : this.bitDepth;
|
|
8059
8161
|
const mergedDeep = depth === 8 ? void 0 : workingToSamples(compositeDeep(prepared, canvas, sources, depth), depth);
|
|
8060
8162
|
const result = exportPsd({ width, height, layers: prepared, merged, mergedDeep, resolution: this.psdResolution, patterns: this.state.patterns, globalLight: this.state.globalLight, depth, ...color });
|
|
8061
8163
|
warnings.push(...result.warnings);
|
|
@@ -10605,13 +10707,17 @@ var PAINT_TOOLS = [
|
|
|
10605
10707
|
{ id: "smudge", label: "Smudge", shortcut: "" },
|
|
10606
10708
|
{ id: "dodge", label: "Dodge", shortcut: "O" },
|
|
10607
10709
|
{ id: "burn", label: "Burn", shortcut: "Shift+O" },
|
|
10608
|
-
{ id: "sponge", label: "Sponge", shortcut: "Shift+O" }
|
|
10710
|
+
{ id: "sponge", label: "Sponge", shortcut: "Shift+O" },
|
|
10711
|
+
{ id: "blur", label: "Blur", shortcut: "" },
|
|
10712
|
+
{ id: "sharpen", label: "Sharpen", shortcut: "" },
|
|
10713
|
+
{ id: "history", label: "History", shortcut: "Y" }
|
|
10609
10714
|
];
|
|
10610
10715
|
var isPaintTool = (tool) => PAINT_TOOLS.some((t) => t.id === tool);
|
|
10611
|
-
var isRetouchPaintTool = (tool) => tool === "clone" || tool === "heal" || tool === "spot-heal" || tool === "smudge" || tool === "dodge" || tool === "burn" || tool === "sponge";
|
|
10716
|
+
var isRetouchPaintTool = (tool) => tool === "clone" || tool === "heal" || tool === "spot-heal" || tool === "smudge" || tool === "dodge" || tool === "burn" || tool === "sponge" || tool === "blur" || tool === "sharpen" || tool === "history";
|
|
10612
10717
|
var RETOUCH_OPTION_CONTROLS = [
|
|
10613
10718
|
{ id: "exposure", label: "Exposure", section: "layer", min: 0, max: 1, step: 0.01, default: 0.5, decimals: 0, track: plain2, displayScale: 100, unit: "%", tools: ["dodge", "burn"] },
|
|
10614
|
-
{ id: "strength", label: "Strength", section: "layer", min: 0, max: 1, step: 0.01, default: 0.5, decimals: 0, track: plain2, displayScale: 100, unit: "%", tools: ["smudge"] }
|
|
10719
|
+
{ id: "strength", label: "Strength", section: "layer", min: 0, max: 1, step: 0.01, default: 0.5, decimals: 0, track: plain2, displayScale: 100, unit: "%", tools: ["smudge", "blur", "sharpen"] },
|
|
10720
|
+
{ id: "historySteps", label: "Steps back", section: "layer", min: 0, max: 50, step: 1, default: 0, decimals: 0, track: plain2, unit: "", tools: ["history"] }
|
|
10615
10721
|
];
|
|
10616
10722
|
var RETOUCH_CHOICES = [
|
|
10617
10723
|
{
|
|
@@ -10630,6 +10736,7 @@ var RETOUCH_CHOICES = [
|
|
|
10630
10736
|
tools: ["spot-heal"],
|
|
10631
10737
|
options: [
|
|
10632
10738
|
{ id: "proximity-match", label: "Proximity Match", title: "Copy the best matching patch nearby" },
|
|
10739
|
+
{ id: "content-aware", label: "Content-Aware", title: "Synthesise texture and edges from patches around the spot" },
|
|
10633
10740
|
{ id: "smooth", label: "Smooth", title: "Fill smoothly from the edges" }
|
|
10634
10741
|
]
|
|
10635
10742
|
},
|
|
@@ -10702,6 +10809,9 @@ function handlePaintShortcut(controller, e) {
|
|
|
10702
10809
|
controller.setTool(next);
|
|
10703
10810
|
return true;
|
|
10704
10811
|
}
|
|
10812
|
+
case "y":
|
|
10813
|
+
controller.setTool("history");
|
|
10814
|
+
return true;
|
|
10705
10815
|
case "d":
|
|
10706
10816
|
controller.resetPaintColors();
|
|
10707
10817
|
return true;
|
|
@@ -11145,7 +11255,7 @@ function createImageColorTools(controller) {
|
|
|
11145
11255
|
const setMode = {
|
|
11146
11256
|
name: "set_color_mode",
|
|
11147
11257
|
title: "Set the colour mode",
|
|
11148
|
-
description: "Image \u203A Mode: rgb, cmyk (for print: give the press `profile`, default coated-cmyk, and the `intent` RGB is separated with) or lab. The document is still edited as RGB in its working space; a CMYK document is soft-proofed through its profile in the viewport (unless set_proof_setup says otherwise), and export_psd writes CMYK or Lab channels with the profile. Changes no pixels. One undo step. Returns the profile summary with mode and cmykProfile.",
|
|
11258
|
+
description: "Image \u203A Mode: rgb, cmyk (for print: give the press `profile`, default coated-cmyk, and the `intent` RGB is separated with) or lab. The document is still edited as RGB in its working space; a CMYK document is soft-proofed through its profile in the viewport (unless set_proof_setup says otherwise), and export_psd writes CMYK or Lab channels with the profile, at 8 or 16 bits (a 32-bit document is written at 16). Changes no pixels. One undo step. Returns the profile summary with mode and cmykProfile.",
|
|
11149
11259
|
inputSchema: {
|
|
11150
11260
|
type: "object",
|
|
11151
11261
|
properties: {
|
|
@@ -11286,12 +11396,12 @@ function createImageRetouchTools(controller) {
|
|
|
11286
11396
|
const spotHeal = {
|
|
11287
11397
|
name: "spot_heal",
|
|
11288
11398
|
title: "Spot Healing stroke",
|
|
11289
|
-
description: "Removes what a stroke covers without a source point (Photoshop's Spot Healing Brush): proximity-match copies the best matching patch nearby and blends it in; smooth fills from the edges inwards (for spots on smooth areas). Paint just over the spot with a brush a little larger than it. One undo step. Returns the layerId, channel, changed bounds, dab count and spotHeal {offset} (the patch offset copied, or null for a smooth fill).",
|
|
11399
|
+
description: "Removes what a stroke covers without a source point (Photoshop's Spot Healing Brush): proximity-match copies the best matching patch nearby and blends it in; content-aware synthesises texture and continues edges from patches all around (best across lines, on patterns and for larger spots, a little slower); smooth fills from the edges inwards (for spots on smooth areas). Paint just over the spot with a brush a little larger than it. One undo step. Returns the layerId, channel, changed bounds, dab count and spotHeal {offset} (the patch offset copied, or null for a smooth fill).",
|
|
11290
11400
|
inputSchema: {
|
|
11291
11401
|
type: "object",
|
|
11292
11402
|
properties: {
|
|
11293
11403
|
points: POINTS,
|
|
11294
|
-
type: { type: "string", enum: [...SPOT_HEAL_TYPES], description: "proximity-match (default) or smooth." },
|
|
11404
|
+
type: { type: "string", enum: [...SPOT_HEAL_TYPES], description: "proximity-match (default the current option), content-aware or smooth." },
|
|
11295
11405
|
sample: SAMPLE,
|
|
11296
11406
|
brush: BRUSH2,
|
|
11297
11407
|
...TARGET2
|
|
@@ -11368,10 +11478,55 @@ function createImageRetouchTools(controller) {
|
|
|
11368
11478
|
annotations: { title: "Sponge stroke", ...WRITE5 },
|
|
11369
11479
|
handler: (args) => stroke("sponge", { ...args, channel: "pixels" }, { ...pick(args, ["vibrance"]), ...args.mode !== void 0 ? { spongeMode: args.mode } : {} })
|
|
11370
11480
|
};
|
|
11481
|
+
const filterSchema = (verb) => ({
|
|
11482
|
+
type: "object",
|
|
11483
|
+
properties: {
|
|
11484
|
+
points: POINTS,
|
|
11485
|
+
strength: { type: "number", minimum: 0, maximum: 1, description: `How strongly to ${verb}, 0..1 (default the current option, 0.5); multiplies the brush opacity.` },
|
|
11486
|
+
brush: BRUSH2,
|
|
11487
|
+
...TARGET2
|
|
11488
|
+
},
|
|
11489
|
+
required: ["points"],
|
|
11490
|
+
additionalProperties: false
|
|
11491
|
+
});
|
|
11492
|
+
const blurTool = {
|
|
11493
|
+
name: "blur_stroke",
|
|
11494
|
+
title: "Blur stroke",
|
|
11495
|
+
description: "Softens the pixels a stroke covers (Photoshop's Blur tool): a soft blur of the layer laid through the brush at `strength`. Overlapping dabs in one stroke do not compound; another stroke blurs further. Works on pixels and masks, at any bit depth. One undo step. Returns the layerId, channel, changed bounds and dab count.",
|
|
11496
|
+
inputSchema: filterSchema("blur"),
|
|
11497
|
+
annotations: { title: "Blur stroke", ...WRITE5 },
|
|
11498
|
+
handler: (args) => stroke("blur", args, pick(args, ["strength"]))
|
|
11499
|
+
};
|
|
11500
|
+
const sharpenTool = {
|
|
11501
|
+
name: "sharpen_stroke",
|
|
11502
|
+
title: "Sharpen stroke",
|
|
11503
|
+
description: "Crisps the pixels a stroke covers (Photoshop's Sharpen tool): an unsharp mask of the layer laid through the brush at `strength`. Keep strength low (0.2..0.5) and inspect with capture_view; strong sharpening shows halos and noise. One undo step. Returns the layerId, channel, changed bounds and dab count.",
|
|
11504
|
+
inputSchema: filterSchema("sharpen"),
|
|
11505
|
+
annotations: { title: "Sharpen stroke", ...WRITE5 },
|
|
11506
|
+
handler: (args) => stroke("sharpen", args, pick(args, ["strength"]))
|
|
11507
|
+
};
|
|
11508
|
+
const historyBrush = {
|
|
11509
|
+
name: "history_brush",
|
|
11510
|
+
title: "History Brush stroke",
|
|
11511
|
+
description: "Paints the layer back as it was earlier (Photoshop's History Brush): the same layer's pixels (or mask) from `historySteps` undo steps back, or from the oldest state history keeps (0, the default, usually the document as opened), laid through the brush. Use it to undo part of a filter, paint or retouch in one area. Fails if the layer did not exist then or there is no history yet. One undo step. Returns the layerId, channel, changed bounds and dab count.",
|
|
11512
|
+
inputSchema: {
|
|
11513
|
+
type: "object",
|
|
11514
|
+
properties: {
|
|
11515
|
+
points: POINTS,
|
|
11516
|
+
historySteps: { type: "integer", minimum: 0, maximum: 1e3, description: "Undo steps back to paint from; 0 (default the current option) is the oldest state history keeps." },
|
|
11517
|
+
brush: BRUSH2,
|
|
11518
|
+
...TARGET2
|
|
11519
|
+
},
|
|
11520
|
+
required: ["points"],
|
|
11521
|
+
additionalProperties: false
|
|
11522
|
+
},
|
|
11523
|
+
annotations: { title: "History Brush stroke", ...WRITE5 },
|
|
11524
|
+
handler: (args) => stroke("history", args, pick(args, ["historySteps"]))
|
|
11525
|
+
};
|
|
11371
11526
|
const getOptions = {
|
|
11372
11527
|
name: "get_retouch_options",
|
|
11373
11528
|
title: "Get retouch options",
|
|
11374
|
-
description: "Reads the retouching tools' options (aligned, sample, spotType, range, exposure, protectTones, spongeMode, vibrance, strength) and the clone source ({x, y, offset} or null; offset is the aligned offset the last clone or heal stroke fixed). Call it before clone_stamp or heal_brush without a source to see where they will sample.",
|
|
11529
|
+
description: "Reads the retouching tools' options (aligned, sample, spotType, range, exposure, protectTones, spongeMode, vibrance, strength, historySteps) and the clone source ({x, y, offset} or null; offset is the aligned offset the last clone or heal stroke fixed: an aligned stroke samples at the brush plus offset, which the editors show as a crosshair). Call it before clone_stamp or heal_brush without a source to see where they will sample.",
|
|
11375
11530
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
11376
11531
|
annotations: { title: "Get retouch options", ...READ6 },
|
|
11377
11532
|
handler: () => {
|
|
@@ -11388,13 +11543,14 @@ function createImageRetouchTools(controller) {
|
|
|
11388
11543
|
properties: {
|
|
11389
11544
|
aligned: { type: "boolean", description: "Clone / heal: keep the offset from stroke to stroke (default true)." },
|
|
11390
11545
|
sample: SAMPLE,
|
|
11391
|
-
spotType: { type: "string", enum: [...SPOT_HEAL_TYPES], description: "Spot heal: proximity-match (default) or smooth." },
|
|
11546
|
+
spotType: { type: "string", enum: [...SPOT_HEAL_TYPES], description: "Spot heal: proximity-match (default), content-aware or smooth." },
|
|
11392
11547
|
range: { type: "string", enum: [...TONE_RANGES], description: "Dodge / burn: shadows, midtones (default) or highlights." },
|
|
11393
11548
|
exposure: { type: "number", minimum: 0, maximum: 1, description: "Dodge / burn strength 0..1 (default 0.5)." },
|
|
11394
11549
|
protectTones: { type: "boolean", description: "Dodge / burn: keep hue and saturation (default true)." },
|
|
11395
11550
|
spongeMode: { type: "string", enum: ["desaturate", "saturate"], description: "Sponge: desaturate (default) or saturate." },
|
|
11396
11551
|
vibrance: { type: "boolean", description: "Sponge: damp clipping (default true)." },
|
|
11397
|
-
strength: { type: "number", minimum: 0, maximum: 1, description: "Smudge strength 0..1 (default 0.5)." }
|
|
11552
|
+
strength: { type: "number", minimum: 0, maximum: 1, description: "Smudge, blur and sharpen strength 0..1 (default 0.5)." },
|
|
11553
|
+
historySteps: { type: "integer", minimum: 0, maximum: 1e3, description: "History Brush: undo steps back it paints from; 0 is the oldest state (default 0)." }
|
|
11398
11554
|
},
|
|
11399
11555
|
additionalProperties: false
|
|
11400
11556
|
},
|
|
@@ -11424,7 +11580,7 @@ function createImageRetouchTools(controller) {
|
|
|
11424
11580
|
return controller.setCloneSource(checkSource(controller, { x: args.x, y: args.y }));
|
|
11425
11581
|
}
|
|
11426
11582
|
};
|
|
11427
|
-
return [cloneStamp, healBrush, spotHeal, smudge, dodge, burn, spongeTool, getOptions, setOptions, setSource];
|
|
11583
|
+
return [cloneStamp, healBrush, spotHeal, smudge, dodge, burn, spongeTool, blurTool, sharpenTool, historyBrush, getOptions, setOptions, setSource];
|
|
11428
11584
|
}
|
|
11429
11585
|
function pick(args, keys) {
|
|
11430
11586
|
const out = {};
|
|
@@ -15085,6 +15241,7 @@ export {
|
|
|
15085
15241
|
applyHomography,
|
|
15086
15242
|
applyImageProjectionToContext,
|
|
15087
15243
|
applyLegacyAdjustments,
|
|
15244
|
+
applyLegacyFloat,
|
|
15088
15245
|
applyMatrix3,
|
|
15089
15246
|
applyOutputStage,
|
|
15090
15247
|
applyParams,
|
|
@@ -15113,6 +15270,7 @@ export {
|
|
|
15113
15270
|
blenderDab,
|
|
15114
15271
|
blurFilter,
|
|
15115
15272
|
borderCoverage,
|
|
15273
|
+
boxBlurPixels,
|
|
15116
15274
|
boxMean,
|
|
15117
15275
|
boxPointOf,
|
|
15118
15276
|
boxQuad,
|
|
@@ -15143,6 +15301,7 @@ export {
|
|
|
15143
15301
|
collectTiles,
|
|
15144
15302
|
colorBalanceChannel,
|
|
15145
15303
|
colorModePlanes,
|
|
15304
|
+
colorModePlanes16,
|
|
15146
15305
|
colorPanelView,
|
|
15147
15306
|
colorRange,
|
|
15148
15307
|
combineSelections,
|
|
@@ -15152,6 +15311,7 @@ export {
|
|
|
15152
15311
|
compositeSurfaceOver,
|
|
15153
15312
|
computeHistogram,
|
|
15154
15313
|
computeSelectionBounds,
|
|
15314
|
+
contentAwareFill,
|
|
15155
15315
|
contentBounds,
|
|
15156
15316
|
contentsBox,
|
|
15157
15317
|
contentsSurface,
|
|
@@ -15592,6 +15752,7 @@ export {
|
|
|
15592
15752
|
resolvePaintGradient,
|
|
15593
15753
|
resolveProfile,
|
|
15594
15754
|
restyleRange,
|
|
15755
|
+
retouchFilter,
|
|
15595
15756
|
reversePaintGradient,
|
|
15596
15757
|
rgbToGray,
|
|
15597
15758
|
rgbToHsl,
|