@pixerate/editor 0.92.0 → 0.94.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/THIRD_PARTY_NOTICES.md +2 -0
- package/dist/{chunk-PDCITYBT.cjs → chunk-4F3YDIWW.cjs} +367 -2
- package/dist/chunk-4F3YDIWW.cjs.map +1 -0
- package/dist/chunk-73L6TROJ.cjs +3685 -0
- package/dist/chunk-73L6TROJ.cjs.map +1 -0
- package/dist/chunk-747CGOT2.js +3685 -0
- package/dist/chunk-747CGOT2.js.map +1 -0
- package/dist/{chunk-YLB2WVNA.js → chunk-ISDCJHTO.js} +367 -2
- package/dist/chunk-ISDCJHTO.js.map +1 -0
- package/dist/image-editor/index.cjs +787 -302
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +84 -18
- package/dist/image-editor/index.d.ts +84 -18
- package/dist/image-editor/index.js +560 -75
- package/dist/image-editor/index.js.map +1 -1
- package/dist/paint/index.cjs +26 -2
- package/dist/paint/index.cjs.map +1 -1
- package/dist/paint/index.d.cts +96 -2
- package/dist/paint/index.d.ts +96 -2
- package/dist/paint/index.js +25 -1
- package/dist/raster/index.cjs +78 -2
- package/dist/raster/index.cjs.map +1 -1
- package/dist/raster/index.d.cts +99 -348
- package/dist/raster/index.d.ts +99 -348
- package/dist/raster/index.js +78 -2
- package/dist/{surface-fJhkmNQn.d.cts → surface-CuBg2c6k.d.cts} +1 -1
- package/dist/{surface-fJhkmNQn.d.ts → surface-CuBg2c6k.d.ts} +1 -1
- package/dist/zlib-BJ6U7LuB.d.cts +795 -0
- package/dist/zlib-BjQkpMFi.d.ts +795 -0
- package/package.json +3 -3
- package/skills/pixerate-image-editor/SKILL.md +63 -4
- package/dist/chunk-H543GD6T.cjs +0 -1696
- package/dist/chunk-H543GD6T.cjs.map +0 -1
- package/dist/chunk-P5TPUNBZ.js +0 -1696
- package/dist/chunk-P5TPUNBZ.js.map +0 -1
- package/dist/chunk-PDCITYBT.cjs.map +0 -1
- package/dist/chunk-YLB2WVNA.js.map +0 -1
|
@@ -5,17 +5,25 @@ import {
|
|
|
5
5
|
createCaptureTool
|
|
6
6
|
} from "../chunk-REOJJIY3.js";
|
|
7
7
|
import {
|
|
8
|
+
DEFAULT_GLOBAL_LIGHT,
|
|
8
9
|
DIRECT_GAUSSIAN_MAX_SIGMA,
|
|
10
|
+
LAYER_EFFECT_KINDS,
|
|
11
|
+
LayerEffectError,
|
|
9
12
|
RasterCompositor,
|
|
10
13
|
ZlibError,
|
|
11
14
|
adler32,
|
|
12
15
|
base64ToBytes,
|
|
13
16
|
blendTile,
|
|
17
|
+
builtinPattern,
|
|
18
|
+
builtinPatternIds,
|
|
14
19
|
bytesToBase64,
|
|
15
20
|
changedTiles,
|
|
21
|
+
curveLut,
|
|
16
22
|
decodePng,
|
|
23
|
+
defaultLayerEffect,
|
|
17
24
|
deflate,
|
|
18
25
|
deflateRaw,
|
|
26
|
+
effectsMargin,
|
|
19
27
|
encodePng,
|
|
20
28
|
findLayer,
|
|
21
29
|
flattenLayers,
|
|
@@ -23,30 +31,48 @@ import {
|
|
|
23
31
|
inflate,
|
|
24
32
|
inflateRaw,
|
|
25
33
|
insertLayer,
|
|
34
|
+
isLayerEffectKind,
|
|
26
35
|
isLayerLocked,
|
|
27
36
|
isPng,
|
|
37
|
+
layerEffectLabel,
|
|
28
38
|
mapLayer,
|
|
39
|
+
mergeLayerEffect,
|
|
40
|
+
newEffectId,
|
|
41
|
+
normalizeLayerEffects,
|
|
29
42
|
parseDataUrl,
|
|
30
|
-
pngDataUrl
|
|
31
|
-
|
|
43
|
+
pngDataUrl,
|
|
44
|
+
validateLayerEffects
|
|
45
|
+
} from "../chunk-747CGOT2.js";
|
|
32
46
|
import {
|
|
33
47
|
CoverageMap,
|
|
34
48
|
DEFAULT_BRUSH,
|
|
35
49
|
DabWalker,
|
|
36
50
|
MAX_BRUSH_SIZE,
|
|
51
|
+
PIGMENT_BANDS,
|
|
52
|
+
PIGMENT_LAMBDA_MIN,
|
|
53
|
+
PIGMENT_LAMBDA_STEP,
|
|
54
|
+
PIGMENT_WAVELENGTHS,
|
|
37
55
|
StrokeCoverage,
|
|
38
56
|
applyStrokeToTile,
|
|
39
57
|
coverageTileCoord,
|
|
58
|
+
createPigment,
|
|
59
|
+
createPigmentTools,
|
|
40
60
|
dabCoverage,
|
|
41
61
|
dabRect,
|
|
62
|
+
lerpPigment,
|
|
63
|
+
lerpPigmentInto,
|
|
64
|
+
mixPigments,
|
|
42
65
|
normalizeBrush,
|
|
43
66
|
rasterizeDab,
|
|
67
|
+
reflectanceToRgb,
|
|
68
|
+
rgbToReflectance,
|
|
69
|
+
setPigmentColor,
|
|
44
70
|
smoothPoints,
|
|
45
71
|
tipFalloff,
|
|
46
72
|
tipReach,
|
|
47
73
|
tipShape,
|
|
48
74
|
walkDabs
|
|
49
|
-
} from "../chunk-
|
|
75
|
+
} from "../chunk-ISDCJHTO.js";
|
|
50
76
|
import {
|
|
51
77
|
BLEND_MODES,
|
|
52
78
|
SurfaceDraft,
|
|
@@ -1484,59 +1510,6 @@ function normalizeAdjustmentLayers(raw) {
|
|
|
1484
1510
|
}
|
|
1485
1511
|
return out;
|
|
1486
1512
|
}
|
|
1487
|
-
function curveLut(points, size = ADJUSTMENT_LUT_SIZE) {
|
|
1488
|
-
const pts = points.filter((p) => Number.isFinite(p.input) && Number.isFinite(p.output)).map((p) => [p.input, p.output]).sort((a, b) => a[0] - b[0]);
|
|
1489
|
-
const dedup = [];
|
|
1490
|
-
for (const p of pts) {
|
|
1491
|
-
if (dedup.length && Math.abs(dedup[dedup.length - 1][0] - p[0]) < 1e-6) continue;
|
|
1492
|
-
dedup.push(p);
|
|
1493
|
-
}
|
|
1494
|
-
const out = new Float32Array(size);
|
|
1495
|
-
const n = dedup.length;
|
|
1496
|
-
if (n < 2) {
|
|
1497
|
-
for (let k = 0; k < size; k++) out[k] = k / (size - 1);
|
|
1498
|
-
return out;
|
|
1499
|
-
}
|
|
1500
|
-
const x = dedup.map((p) => p[0]);
|
|
1501
|
-
const y = dedup.map((p) => p[1]);
|
|
1502
|
-
const m2 = new Float64Array(n);
|
|
1503
|
-
if (n > 2) {
|
|
1504
|
-
const c = new Float64Array(n);
|
|
1505
|
-
const d = new Float64Array(n);
|
|
1506
|
-
for (let i = 1; i < n - 1; i++) {
|
|
1507
|
-
const h0 = x[i] - x[i - 1];
|
|
1508
|
-
const h1 = x[i + 1] - x[i];
|
|
1509
|
-
const a = h0 / 6;
|
|
1510
|
-
const b = (h0 + h1) / 3;
|
|
1511
|
-
const cc = h1 / 6;
|
|
1512
|
-
const r = (y[i + 1] - y[i]) / h1 - (y[i] - y[i - 1]) / h0;
|
|
1513
|
-
const denom = b - a * c[i - 1];
|
|
1514
|
-
c[i] = cc / denom;
|
|
1515
|
-
d[i] = (r - a * d[i - 1]) / denom;
|
|
1516
|
-
}
|
|
1517
|
-
for (let i = n - 2; i >= 1; i--) m2[i] = d[i] - c[i] * m2[i + 1];
|
|
1518
|
-
}
|
|
1519
|
-
let seg = 0;
|
|
1520
|
-
for (let k = 0; k < size; k++) {
|
|
1521
|
-
const xv = k / (size - 1);
|
|
1522
|
-
if (xv <= x[0]) {
|
|
1523
|
-
out[k] = clamp01(y[0]);
|
|
1524
|
-
continue;
|
|
1525
|
-
}
|
|
1526
|
-
if (xv >= x[n - 1]) {
|
|
1527
|
-
out[k] = clamp01(y[n - 1]);
|
|
1528
|
-
continue;
|
|
1529
|
-
}
|
|
1530
|
-
while (seg < n - 2 && xv > x[seg + 1]) seg++;
|
|
1531
|
-
const x0 = x[seg], x1 = x[seg + 1];
|
|
1532
|
-
const h = x1 - x0;
|
|
1533
|
-
const a = (x1 - xv) / h;
|
|
1534
|
-
const b = (xv - x0) / h;
|
|
1535
|
-
const v = a * y[seg] + b * y[seg + 1] + ((a * a * a - a) * m2[seg] + (b * b * b - b) * m2[seg + 1]) * (h * h) / 6;
|
|
1536
|
-
out[k] = clamp01(v);
|
|
1537
|
-
}
|
|
1538
|
-
return out;
|
|
1539
|
-
}
|
|
1540
1513
|
function curveLutFromLevels(points) {
|
|
1541
1514
|
return curveLut(points.map((p) => ({ input: p.input / 255, output: p.output / 255 })));
|
|
1542
1515
|
}
|
|
@@ -2688,7 +2661,7 @@ function developTarget(layers, activeLayerId) {
|
|
|
2688
2661
|
}
|
|
2689
2662
|
return pixels.find((l) => l.source === "document") ?? pixels.find((l) => l.id === BACKGROUND_LAYER_ID) ?? pixels[0] ?? null;
|
|
2690
2663
|
}
|
|
2691
|
-
var isPlain = (l) => l.visible && l.opacity === 1 && l.blend === "normal" && !l.clipped && !l.mask && !l.locks;
|
|
2664
|
+
var isPlain = (l) => l.visible && l.opacity === 1 && l.blend === "normal" && !l.clipped && !l.mask && !l.locks && !l.effects;
|
|
2692
2665
|
function legacyView(stack, width, height, activeLayerId = null) {
|
|
2693
2666
|
const { layers } = stack;
|
|
2694
2667
|
const target = developTarget(layers, activeLayerId);
|
|
@@ -2728,7 +2701,7 @@ function isLegacyShape(stack) {
|
|
|
2728
2701
|
const bg = layers[0];
|
|
2729
2702
|
if (!bg || bg.type !== "pixel" || bg.source !== "document") return false;
|
|
2730
2703
|
if (bg.id !== BACKGROUND_LAYER_ID || bg.name !== BACKGROUND_LAYER_NAME) return false;
|
|
2731
|
-
if (!bg.visible || bg.opacity !== 1 || bg.blend !== "normal" || bg.clipped || bg.locks) return false;
|
|
2704
|
+
if (!bg.visible || bg.opacity !== 1 || bg.blend !== "normal" || bg.clipped || bg.locks || bg.effects) return false;
|
|
2732
2705
|
if ((bg.fillOpacity ?? 1) !== 1 || bg.offset.x !== 0 || bg.offset.y !== 0) return false;
|
|
2733
2706
|
const filters = bg.filters ?? [];
|
|
2734
2707
|
if (filters.length < 1 || filters.length > 2) return false;
|
|
@@ -2744,7 +2717,7 @@ function isLegacyShape(stack) {
|
|
|
2744
2717
|
let adjustments = 0;
|
|
2745
2718
|
for (; i < layers.length && layers[i].type === "adjustment"; i++) {
|
|
2746
2719
|
const l = layers[i];
|
|
2747
|
-
if (l.clipped || l.locks || l.mask?.source) return false;
|
|
2720
|
+
if (l.clipped || l.locks || l.mask?.source || l.effects) return false;
|
|
2748
2721
|
adjustments++;
|
|
2749
2722
|
}
|
|
2750
2723
|
for (; i < layers.length; i++) {
|
|
@@ -3250,7 +3223,9 @@ var ImageEditorRenderer = class {
|
|
|
3250
3223
|
return this.depthMaps.get(`${source.maskSource}|${width}x${height}`) ?? null;
|
|
3251
3224
|
},
|
|
3252
3225
|
rasterizeAnnotation: (annotation, rect) => this.rasterizeAnnotation(annotation, rect),
|
|
3253
|
-
version: `${host?.version() ?? ""}:${this.assetVersion}
|
|
3226
|
+
version: `${host?.version() ?? ""}:${this.assetVersion}`,
|
|
3227
|
+
globalLight: host?.globalLight?.(),
|
|
3228
|
+
pattern: host?.pattern ? (id) => host.pattern(id) : void 0
|
|
3254
3229
|
};
|
|
3255
3230
|
}
|
|
3256
3231
|
/** Loads what the compositor reads synchronously: depth maps (at canvas size) and annotation images. */
|
|
@@ -4523,8 +4498,29 @@ function baseFields(layer, ctx) {
|
|
|
4523
4498
|
if (layer.clipped) out.clipped = true;
|
|
4524
4499
|
if (layer.mask) out.mask = serializeMask(layer.mask, `${layer.id}-mask`, ctx);
|
|
4525
4500
|
if (layer.locks && Object.values(layer.locks).some(Boolean)) out.locks = { ...layer.locks };
|
|
4501
|
+
if (layer.effects) out.effects = serializeEffects(layer.effects);
|
|
4502
|
+
return out;
|
|
4503
|
+
}
|
|
4504
|
+
function serializeEffects(effects) {
|
|
4505
|
+
const out = { enabled: effects.enabled, items: JSON.parse(JSON.stringify(effects.items)) };
|
|
4506
|
+
if (effects.scale !== void 0 && effects.scale !== 1) out.scale = effects.scale;
|
|
4507
|
+
if (effects.psd) out.psd = { key: effects.psd.key, data: bytesToBase64(effects.psd.data) };
|
|
4526
4508
|
return out;
|
|
4527
4509
|
}
|
|
4510
|
+
function deserializeEffects(raw) {
|
|
4511
|
+
if (!raw || typeof raw !== "object") return void 0;
|
|
4512
|
+
const r = raw;
|
|
4513
|
+
let psd;
|
|
4514
|
+
const p = r.psd;
|
|
4515
|
+
if (p && typeof p.key === "string" && typeof p.data === "string") {
|
|
4516
|
+
try {
|
|
4517
|
+
psd = { key: p.key, data: base64ToBytes(p.data) };
|
|
4518
|
+
} catch {
|
|
4519
|
+
psd = void 0;
|
|
4520
|
+
}
|
|
4521
|
+
}
|
|
4522
|
+
return normalizeLayerEffects({ ...r, psd });
|
|
4523
|
+
}
|
|
4528
4524
|
function serializeMask(mask, hint, ctx) {
|
|
4529
4525
|
const out = { defaultValue: mask.defaultValue };
|
|
4530
4526
|
if (!mask.source) {
|
|
@@ -4727,6 +4723,8 @@ function deserializeLayer(raw, ctx) {
|
|
|
4727
4723
|
for (const k of ["pixels", "transparency", "position", "all"]) if (r.locks[k] === true) locks[k] = true;
|
|
4728
4724
|
if (Object.keys(locks).length) base.locks = locks;
|
|
4729
4725
|
}
|
|
4726
|
+
const effects = deserializeEffects(r.effects);
|
|
4727
|
+
if (effects && r.type !== "adjustment") base.effects = effects;
|
|
4730
4728
|
switch (r.type) {
|
|
4731
4729
|
case "pixel": {
|
|
4732
4730
|
const layer = {
|
|
@@ -5009,6 +5007,77 @@ function removeLayerFilter(layers, id, filterId) {
|
|
|
5009
5007
|
else delete next.filters;
|
|
5010
5008
|
return mapLayer(layers, id, () => next);
|
|
5011
5009
|
}
|
|
5010
|
+
function requireEffectLayer(layers, id, action) {
|
|
5011
|
+
const layer = requireLayer(layers, id).layer;
|
|
5012
|
+
if (layer.type === "adjustment") fail(`Layer "${layer.name || id}" is an adjustment layer; effects go on pixel, annotation and group layers.`);
|
|
5013
|
+
requireUnlocked(layer, "all", action);
|
|
5014
|
+
return layer;
|
|
5015
|
+
}
|
|
5016
|
+
function layerEffectsOf(layer) {
|
|
5017
|
+
return layer.effects ?? { enabled: true, items: [] };
|
|
5018
|
+
}
|
|
5019
|
+
function guard(fn) {
|
|
5020
|
+
try {
|
|
5021
|
+
return fn();
|
|
5022
|
+
} catch (e) {
|
|
5023
|
+
if (e instanceof LayerEffectError) fail(e.message);
|
|
5024
|
+
throw e;
|
|
5025
|
+
}
|
|
5026
|
+
}
|
|
5027
|
+
function setLayerEffects(layers, id, effects) {
|
|
5028
|
+
const layer = requireEffectLayer(layers, id, "change its effects");
|
|
5029
|
+
const next = { ...layer };
|
|
5030
|
+
if (effects && (effects.items.length || effects.psd || effects.scale !== void 0 || !effects.enabled)) {
|
|
5031
|
+
guard(() => validateLayerEffects(effects));
|
|
5032
|
+
next.effects = effects;
|
|
5033
|
+
} else delete next.effects;
|
|
5034
|
+
return mapLayer(layers, id, () => next);
|
|
5035
|
+
}
|
|
5036
|
+
function addLayerEffect(layers, id, kind, params = {}, index) {
|
|
5037
|
+
if (!isLayerEffectKind(kind)) fail(`Unknown effect kind "${String(kind)}". Kinds: ${LAYER_EFFECT_KINDS.join(", ")}.`);
|
|
5038
|
+
const layer = requireEffectLayer(layers, id, "add effects");
|
|
5039
|
+
const current = layerEffectsOf(layer);
|
|
5040
|
+
const ids = new Set(current.items.map((e) => e.id));
|
|
5041
|
+
let effectId = newEffectId();
|
|
5042
|
+
while (ids.has(effectId)) effectId = newEffectId();
|
|
5043
|
+
const { id: _ignored, kind: _kind, ...rest } = params;
|
|
5044
|
+
const effect = guard(() => mergeLayerEffect(defaultLayerEffect(kind, effectId), rest));
|
|
5045
|
+
const items = [...current.items];
|
|
5046
|
+
const at = index === void 0 ? items.length : Math.max(0, Math.min(items.length, Math.floor(index)));
|
|
5047
|
+
items.splice(at, 0, effect);
|
|
5048
|
+
return { layers: setLayerEffects(layers, id, { ...current, items }), effect };
|
|
5049
|
+
}
|
|
5050
|
+
function requireEffect(layer, effectId) {
|
|
5051
|
+
const items = layer.effects?.items ?? [];
|
|
5052
|
+
const i = items.findIndex((e) => e.id === effectId);
|
|
5053
|
+
if (i === -1) fail(`Layer "${layer.name || layer.id}" has no effect "${effectId}". Effects: ${items.map((e) => `${e.id} (${e.kind})`).join(", ") || "none"}; call list_layer_effects.`);
|
|
5054
|
+
return i;
|
|
5055
|
+
}
|
|
5056
|
+
function updateLayerEffect(layers, id, effectId, changes) {
|
|
5057
|
+
const layer = requireEffectLayer(layers, id, "change its effects");
|
|
5058
|
+
const i = requireEffect(layer, effectId);
|
|
5059
|
+
const current = layer.effects;
|
|
5060
|
+
const items = [...current.items];
|
|
5061
|
+
items[i] = guard(() => mergeLayerEffect(items[i], changes));
|
|
5062
|
+
return setLayerEffects(layers, id, { ...current, items });
|
|
5063
|
+
}
|
|
5064
|
+
function removeLayerEffect(layers, id, effectId) {
|
|
5065
|
+
const layer = requireEffectLayer(layers, id, "change its effects");
|
|
5066
|
+
requireEffect(layer, effectId);
|
|
5067
|
+
const current = layer.effects;
|
|
5068
|
+
return setLayerEffects(layers, id, { ...current, items: current.items.filter((e) => e.id !== effectId) });
|
|
5069
|
+
}
|
|
5070
|
+
function setLayerEffectsEnabled(layers, id, enabled, scale) {
|
|
5071
|
+
const layer = requireEffectLayer(layers, id, "change its effects");
|
|
5072
|
+
if (scale !== void 0 && !(Number.isFinite(scale) && scale >= 0.01 && scale <= 10)) fail(`scale must be from 0.01 to 10 (1 = 100 %), got ${scale}.`);
|
|
5073
|
+
const current = layerEffectsOf(layer);
|
|
5074
|
+
const next = { ...current, enabled };
|
|
5075
|
+
if (scale !== void 0) {
|
|
5076
|
+
if (scale === 1) delete next.scale;
|
|
5077
|
+
else next.scale = scale;
|
|
5078
|
+
}
|
|
5079
|
+
return setLayerEffects(layers, id, next);
|
|
5080
|
+
}
|
|
5012
5081
|
function parseBlend(value, allowPassThrough = false) {
|
|
5013
5082
|
if (value === void 0) return void 0;
|
|
5014
5083
|
if (value === "pass-through" && allowPassThrough) return value;
|
|
@@ -7293,7 +7362,8 @@ var ImageEditorController = class {
|
|
|
7293
7362
|
this.renderer.layerSources = {
|
|
7294
7363
|
surfaceOf: (layer) => this.surfaceOf(layer),
|
|
7295
7364
|
sourceIsOpaque: () => this.sourceIsOpaque(),
|
|
7296
|
-
version: () => this.sourceVersion()
|
|
7365
|
+
version: () => this.sourceVersion(),
|
|
7366
|
+
globalLight: () => this.state.globalLight
|
|
7297
7367
|
};
|
|
7298
7368
|
this.state = {
|
|
7299
7369
|
sourceUrl: typeof options.image === "string" ? options.image : null,
|
|
@@ -7447,6 +7517,7 @@ var ImageEditorController = class {
|
|
|
7447
7517
|
}
|
|
7448
7518
|
};
|
|
7449
7519
|
if (s.legacyOutputBlur !== void 0) entry.legacyOutputBlur = s.legacyOutputBlur;
|
|
7520
|
+
if (s.globalLight) entry.globalLight = { ...s.globalLight };
|
|
7450
7521
|
return entry;
|
|
7451
7522
|
}
|
|
7452
7523
|
restoreHistoryEntry(entry) {
|
|
@@ -7459,6 +7530,8 @@ var ImageEditorController = class {
|
|
|
7459
7530
|
s.outputOpacity = entry.outputOpacity;
|
|
7460
7531
|
if (entry.legacyOutputBlur !== void 0) s.legacyOutputBlur = entry.legacyOutputBlur;
|
|
7461
7532
|
else delete s.legacyOutputBlur;
|
|
7533
|
+
if (entry.globalLight) s.globalLight = { ...entry.globalLight };
|
|
7534
|
+
else delete s.globalLight;
|
|
7462
7535
|
s.selection = entry.selection;
|
|
7463
7536
|
if (this.imageElement !== entry.source.element && !this.samplePixelsOverride) this.samplePixels = null;
|
|
7464
7537
|
this.imageElement = entry.source.element;
|
|
@@ -7680,7 +7753,7 @@ var ImageEditorController = class {
|
|
|
7680
7753
|
}
|
|
7681
7754
|
compositorSources() {
|
|
7682
7755
|
const { width, height } = this.naturalSize;
|
|
7683
|
-
return { width, height, surfaceOf: (l) => this.surfaceOf(l), version: this.sourceVersion() };
|
|
7756
|
+
return { width, height, surfaceOf: (l) => this.surfaceOf(l), version: this.sourceVersion(), globalLight: this.state.globalLight };
|
|
7684
7757
|
}
|
|
7685
7758
|
sourceIds = /* @__PURE__ */ new WeakMap();
|
|
7686
7759
|
nextSourceId = 1;
|
|
@@ -8092,6 +8165,55 @@ var ImageEditorController = class {
|
|
|
8092
8165
|
this.commitLayers(next);
|
|
8093
8166
|
return findLayer(next, id).layer.filters ?? [];
|
|
8094
8167
|
}
|
|
8168
|
+
// --- Layer effects ---
|
|
8169
|
+
/** A layer's effects (an empty, enabled list when it has none). */
|
|
8170
|
+
getLayerEffects(id) {
|
|
8171
|
+
return layerEffectsOf(requireLayer(this.state.layers, id).layer);
|
|
8172
|
+
}
|
|
8173
|
+
/**
|
|
8174
|
+
* Adds an effect of `kind` with Photoshop's defaults and `params` applied (one undo step), at
|
|
8175
|
+
* `index` in the layer's effect list (default the end). Returns the new effect and the effects.
|
|
8176
|
+
*/
|
|
8177
|
+
addLayerEffect(id, kind, params = {}, index) {
|
|
8178
|
+
const res = addLayerEffect(this.state.layers, id, kind, params, index);
|
|
8179
|
+
this.commitLayers(res.layers);
|
|
8180
|
+
return { effect: res.effect, effects: this.getLayerEffects(id) };
|
|
8181
|
+
}
|
|
8182
|
+
/** Changes one effect (one undo step, or none with `commitToHistory = false` during a drag). Returns the effects. */
|
|
8183
|
+
updateLayerEffect(id, effectId, changes, commitToHistory = true) {
|
|
8184
|
+
this.commitLayers(updateLayerEffect(this.state.layers, id, effectId, changes), void 0, commitToHistory);
|
|
8185
|
+
return this.getLayerEffects(id);
|
|
8186
|
+
}
|
|
8187
|
+
/** Removes one effect (one undo step). Returns the remaining effects. */
|
|
8188
|
+
removeLayerEffect(id, effectId) {
|
|
8189
|
+
this.commitLayers(removeLayerEffect(this.state.layers, id, effectId));
|
|
8190
|
+
return this.getLayerEffects(id);
|
|
8191
|
+
}
|
|
8192
|
+
/** Turns a layer's effects on or off as a whole and, when given, sets Scale Effects (one undo step). */
|
|
8193
|
+
setLayerEffectsEnabled(id, enabled, scale, commitToHistory = true) {
|
|
8194
|
+
this.commitLayers(setLayerEffectsEnabled(this.state.layers, id, enabled, scale), void 0, commitToHistory);
|
|
8195
|
+
return this.getLayerEffects(id);
|
|
8196
|
+
}
|
|
8197
|
+
/** Replaces a layer's effects (one undo step; `null` removes them). Returns the effects. */
|
|
8198
|
+
setLayerEffects(id, effects, commitToHistory = true) {
|
|
8199
|
+
this.commitLayers(setLayerEffects(this.state.layers, id, effects), void 0, commitToHistory);
|
|
8200
|
+
return this.getLayerEffects(id);
|
|
8201
|
+
}
|
|
8202
|
+
/** The light effects with "use global light" follow. */
|
|
8203
|
+
getGlobalLight() {
|
|
8204
|
+
return { ...this.state.globalLight ?? DEFAULT_GLOBAL_LIGHT };
|
|
8205
|
+
}
|
|
8206
|
+
/** Sets the global light (one undo step). `angle` -360..360°, `altitude` 0..90°. Returns it. */
|
|
8207
|
+
setGlobalLight(light, commitToHistory = true) {
|
|
8208
|
+
const next = { ...this.getGlobalLight(), ...light };
|
|
8209
|
+
if (!(Number.isFinite(next.angle) && next.angle >= -360 && next.angle <= 360)) throw new LayerOperationError(`angle must be from -360 to 360 degrees, got ${next.angle}.`);
|
|
8210
|
+
if (!(Number.isFinite(next.altitude) && next.altitude >= 0 && next.altitude <= 90)) throw new LayerOperationError(`altitude must be from 0 to 90 degrees, got ${next.altitude}.`);
|
|
8211
|
+
if (commitToHistory) this.recordHistory();
|
|
8212
|
+
if (next.angle === DEFAULT_GLOBAL_LIGHT.angle && next.altitude === DEFAULT_GLOBAL_LIGHT.altitude) delete this.state.globalLight;
|
|
8213
|
+
else this.state.globalLight = next;
|
|
8214
|
+
this.notify();
|
|
8215
|
+
return this.getGlobalLight();
|
|
8216
|
+
}
|
|
8095
8217
|
/** Composites `layers` (in isolation) over `rect` into a surface, loading depth maps first. */
|
|
8096
8218
|
async compositeToSurface(layers, rect) {
|
|
8097
8219
|
const { width, height } = this.naturalSize;
|
|
@@ -8121,7 +8243,8 @@ var ImageEditorController = class {
|
|
|
8121
8243
|
}
|
|
8122
8244
|
/**
|
|
8123
8245
|
* Merge Down: composites a layer onto the pixel layer directly below it (which keeps its name,
|
|
8124
|
-
* opacity and blend; masks, fill and
|
|
8246
|
+
* opacity and blend; masks, fill, filters and both layers' effects are baked), as one undo step.
|
|
8247
|
+
* Returns the merged id.
|
|
8125
8248
|
*/
|
|
8126
8249
|
async mergeDown(id) {
|
|
8127
8250
|
const loc = requireLayer(this.state.layers, id);
|
|
@@ -8133,7 +8256,9 @@ var ImageEditorController = class {
|
|
|
8133
8256
|
if (!upper.visible) throw new LayerOperationError(`Layer "${upper.name || id}" is hidden; show it or delete it instead of merging.`);
|
|
8134
8257
|
requireUnlocked(upper, "all", "merge it");
|
|
8135
8258
|
requireUnlocked(lower, "pixels", "merge into it");
|
|
8136
|
-
|
|
8259
|
+
let rect = unionRect(this.paintBounds(lower), upper.type === "adjustment" ? null : this.paintBounds(upper)) ?? { x: 0, y: 0, width: 1, height: 1 };
|
|
8260
|
+
const reach = Math.max(effectsMargin(lower.effects), upper.type === "adjustment" ? 0 : effectsMargin(upper.effects));
|
|
8261
|
+
if (reach) rect = { x: rect.x - reach, y: rect.y - reach, width: rect.width + 2 * reach, height: rect.height + 2 * reach };
|
|
8137
8262
|
const base = { ...lower, blend: "normal", opacity: 1 };
|
|
8138
8263
|
delete base.clipped;
|
|
8139
8264
|
const surface = await this.compositeToSurface([base, upper], rect);
|
|
@@ -8142,6 +8267,7 @@ var ImageEditorController = class {
|
|
|
8142
8267
|
delete merged.fillOpacity;
|
|
8143
8268
|
delete merged.filters;
|
|
8144
8269
|
delete merged.source;
|
|
8270
|
+
delete merged.effects;
|
|
8145
8271
|
let next = mapLayer(this.state.layers, id, () => null);
|
|
8146
8272
|
next = mapLayer(next, lower.id, () => merged);
|
|
8147
8273
|
this.commitLayers(next, () => {
|
|
@@ -9522,6 +9648,9 @@ var ImageEditorController = class {
|
|
|
9522
9648
|
if (typeof data.legacyOutputBlur === "number" && data.legacyOutputBlur >= 0) s.legacyOutputBlur = data.legacyOutputBlur;
|
|
9523
9649
|
else delete s.legacyOutputBlur;
|
|
9524
9650
|
s.activeLayerId = data.activeLayerId && findLayer(s.layers, data.activeLayerId) ? data.activeLayerId : null;
|
|
9651
|
+
const light = data.globalLight;
|
|
9652
|
+
if (light && Number.isFinite(light.angle) && Number.isFinite(light.altitude)) s.globalLight = { angle: light.angle, altitude: Math.min(90, Math.max(0, light.altitude)) };
|
|
9653
|
+
else delete s.globalLight;
|
|
9525
9654
|
if (!this.imageElement && typeof data.width === "number" && typeof data.height === "number" && data.width > 0 && data.height > 0) {
|
|
9526
9655
|
s.imageDimensions = { width: data.width, height: data.height };
|
|
9527
9656
|
}
|
|
@@ -9535,6 +9664,7 @@ var ImageEditorController = class {
|
|
|
9535
9664
|
s.crop = data.crop ? { ...data.crop } : null;
|
|
9536
9665
|
s.transform = { ...data.transform };
|
|
9537
9666
|
s.activeLayerId = null;
|
|
9667
|
+
delete s.globalLight;
|
|
9538
9668
|
}
|
|
9539
9669
|
s.activeTarget = "pixels";
|
|
9540
9670
|
this.viewKey = [];
|
|
@@ -9544,7 +9674,7 @@ var ImageEditorController = class {
|
|
|
9544
9674
|
serializeState() {
|
|
9545
9675
|
const { width, height } = this.naturalSize;
|
|
9546
9676
|
const view = legacyView(this.stack(), width, height, null);
|
|
9547
|
-
if (view.exact) {
|
|
9677
|
+
if (view.exact && !this.state.globalLight) {
|
|
9548
9678
|
return {
|
|
9549
9679
|
// States without adjustment layers keep schema 1, so they round-trip unchanged.
|
|
9550
9680
|
version: view.adjustments.layers?.length ? 2 : 1,
|
|
@@ -9571,6 +9701,7 @@ var ImageEditorController = class {
|
|
|
9571
9701
|
opacity: this.state.outputOpacity
|
|
9572
9702
|
};
|
|
9573
9703
|
if (this.state.legacyOutputBlur !== void 0) out.legacyOutputBlur = this.state.legacyOutputBlur;
|
|
9704
|
+
if (this.state.globalLight) out.globalLight = { ...this.state.globalLight };
|
|
9574
9705
|
return out;
|
|
9575
9706
|
}
|
|
9576
9707
|
};
|
|
@@ -10808,6 +10939,7 @@ function describeLayer(layer, activeId, boundsOf) {
|
|
|
10808
10939
|
clipped: Boolean(layer.clipped),
|
|
10809
10940
|
locks: layer.locks ? { ...layer.locks } : {},
|
|
10810
10941
|
mask: maskSummary(layer.mask),
|
|
10942
|
+
effects: layer.effects ? { enabled: layer.effects.enabled, scale: layer.effects.scale ?? 1, items: layer.effects.items.map((e) => ({ id: e.id, kind: e.kind, enabled: e.enabled })) } : null,
|
|
10811
10943
|
active: layer.id === activeId
|
|
10812
10944
|
};
|
|
10813
10945
|
switch (layer.type) {
|
|
@@ -10867,7 +10999,7 @@ function createImageLayerTools(controller) {
|
|
|
10867
10999
|
const listLayers = {
|
|
10868
11000
|
name: "list_layers",
|
|
10869
11001
|
title: "List image layers",
|
|
10870
|
-
description: "Returns the layer stack bottom to top as a tree: id, type (pixel, adjustment, group, annotation), name, document bounds (pixel layers), visible, opacity, fillOpacity, blend, clipped, locks, a mask summary, filters (pixel layers), kind and params (adjustment layers), children (groups) and which layer is active. Also returns the active layer id and target (pixels or mask) and the canvas size.",
|
|
11002
|
+
description: "Returns the layer stack bottom to top as a tree: id, type (pixel, adjustment, group, annotation), name, document bounds (pixel layers), visible, opacity, fillOpacity, blend, clipped, locks, a mask summary, an effects summary (master switch, scale, effect ids and kinds; details from list_layer_effects), filters (pixel layers), kind and params (adjustment layers), children (groups) and which layer is active. Also returns the active layer id and target (pixels or mask) and the canvas size.",
|
|
10871
11003
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
10872
11004
|
annotations: { title: "List image layers", ...READ2 },
|
|
10873
11005
|
handler: () => {
|
|
@@ -11303,9 +11435,338 @@ function createImageLayerTools(controller) {
|
|
|
11303
11435
|
];
|
|
11304
11436
|
}
|
|
11305
11437
|
|
|
11306
|
-
// src/image-editor/
|
|
11438
|
+
// src/image-editor/effect-tools.ts
|
|
11439
|
+
var READ3 = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
11307
11440
|
var WRITE3 = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
11441
|
+
var WRITE_IDEMPOTENT3 = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
11308
11442
|
var DESTRUCTIVE2 = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
|
|
11443
|
+
var LAYER_ID3 = { type: "string", description: "Layer id from list_layers (a pixel, annotation or group layer)." };
|
|
11444
|
+
var EFFECT_ID = { type: "string", description: "Effect id from list_layer_effects or add_layer_effect." };
|
|
11445
|
+
var BLEND_IDS = BLEND_MODES.map((m) => m.id);
|
|
11446
|
+
var DEFS = {
|
|
11447
|
+
color: { type: "string", pattern: "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$", description: "Colour as #rrggbb." },
|
|
11448
|
+
contour: {
|
|
11449
|
+
type: "object",
|
|
11450
|
+
description: "A transfer curve over the effect coverage: points { input, output } from 0 to 1 (at least 2), sorted by input. Linear is [{0,0},{1,1}].",
|
|
11451
|
+
properties: {
|
|
11452
|
+
name: { type: "string", description: 'Display name (e.g. "Cone", "Gaussian").' },
|
|
11453
|
+
points: {
|
|
11454
|
+
type: "array",
|
|
11455
|
+
minItems: 2,
|
|
11456
|
+
description: "Curve points.",
|
|
11457
|
+
items: {
|
|
11458
|
+
type: "object",
|
|
11459
|
+
properties: {
|
|
11460
|
+
input: { type: "number", minimum: 0, maximum: 1, description: "Coverage in (0..1)." },
|
|
11461
|
+
output: { type: "number", minimum: 0, maximum: 1, description: "Coverage out (0..1)." },
|
|
11462
|
+
corner: { type: "boolean", description: "Sharp corner instead of a smooth point (default false)." }
|
|
11463
|
+
},
|
|
11464
|
+
required: ["input", "output"],
|
|
11465
|
+
additionalProperties: false
|
|
11466
|
+
}
|
|
11467
|
+
}
|
|
11468
|
+
},
|
|
11469
|
+
required: ["name", "points"],
|
|
11470
|
+
additionalProperties: false
|
|
11471
|
+
},
|
|
11472
|
+
gradient: {
|
|
11473
|
+
type: "object",
|
|
11474
|
+
description: "A gradient: colour stops, optional opacity stops and its layout.",
|
|
11475
|
+
properties: {
|
|
11476
|
+
stops: {
|
|
11477
|
+
type: "array",
|
|
11478
|
+
minItems: 1,
|
|
11479
|
+
description: "Colour stops { position 0..1, color #rrggbb }.",
|
|
11480
|
+
items: {
|
|
11481
|
+
type: "object",
|
|
11482
|
+
properties: { position: { type: "number", minimum: 0, maximum: 1, description: "0..1 along the gradient." }, color: { $ref: "#/$defs/color" } },
|
|
11483
|
+
required: ["position", "color"],
|
|
11484
|
+
additionalProperties: false
|
|
11485
|
+
}
|
|
11486
|
+
},
|
|
11487
|
+
opacityStops: {
|
|
11488
|
+
type: "array",
|
|
11489
|
+
description: "Opacity stops { position 0..1, opacity 0..1 } (default opaque).",
|
|
11490
|
+
items: {
|
|
11491
|
+
type: "object",
|
|
11492
|
+
properties: {
|
|
11493
|
+
position: { type: "number", minimum: 0, maximum: 1, description: "0..1 along the gradient." },
|
|
11494
|
+
opacity: { type: "number", minimum: 0, maximum: 1, description: "0..1." }
|
|
11495
|
+
},
|
|
11496
|
+
required: ["position", "opacity"],
|
|
11497
|
+
additionalProperties: false
|
|
11498
|
+
}
|
|
11499
|
+
},
|
|
11500
|
+
style: { type: "string", enum: ["linear", "radial", "angle", "reflected", "diamond"], description: "Geometry." },
|
|
11501
|
+
angle: { type: "number", minimum: -360, maximum: 360, description: "Degrees, 90 = bottom to top." },
|
|
11502
|
+
scale: { type: "number", minimum: 0.1, maximum: 1.5, description: "1 = 100 %." },
|
|
11503
|
+
reverse: { type: "boolean", description: "Swap the ends." },
|
|
11504
|
+
align: { type: "boolean", description: "Lay out over the layer bounds (true) or the canvas." },
|
|
11505
|
+
offset: {
|
|
11506
|
+
type: "object",
|
|
11507
|
+
description: "Centre offset as fractions of the bounds.",
|
|
11508
|
+
properties: { x: { type: "number", minimum: -1, maximum: 1, description: "Fraction of the width." }, y: { type: "number", minimum: -1, maximum: 1, description: "Fraction of the height." } },
|
|
11509
|
+
required: ["x", "y"],
|
|
11510
|
+
additionalProperties: false
|
|
11511
|
+
}
|
|
11512
|
+
},
|
|
11513
|
+
required: ["stops", "style", "angle", "scale", "reverse", "align", "offset"],
|
|
11514
|
+
additionalProperties: false
|
|
11515
|
+
},
|
|
11516
|
+
phase: {
|
|
11517
|
+
type: "object",
|
|
11518
|
+
description: "Pattern origin offset in px.",
|
|
11519
|
+
properties: { x: { type: "number", description: "px." }, y: { type: "number", description: "px." } },
|
|
11520
|
+
required: ["x", "y"],
|
|
11521
|
+
additionalProperties: false
|
|
11522
|
+
},
|
|
11523
|
+
fill: {
|
|
11524
|
+
description: "What a stroke or glow paints with. Glows take color or gradient only.",
|
|
11525
|
+
anyOf: [
|
|
11526
|
+
{
|
|
11527
|
+
type: "object",
|
|
11528
|
+
properties: { type: { const: "color", description: "Solid colour." }, color: { $ref: "#/$defs/color" } },
|
|
11529
|
+
required: ["type", "color"],
|
|
11530
|
+
additionalProperties: false
|
|
11531
|
+
},
|
|
11532
|
+
{
|
|
11533
|
+
type: "object",
|
|
11534
|
+
properties: { type: { const: "gradient", description: "Gradient." }, gradient: { $ref: "#/$defs/gradient" } },
|
|
11535
|
+
required: ["type", "gradient"],
|
|
11536
|
+
additionalProperties: false
|
|
11537
|
+
},
|
|
11538
|
+
{
|
|
11539
|
+
type: "object",
|
|
11540
|
+
properties: {
|
|
11541
|
+
type: { const: "pattern", description: "Pattern (strokes only)." },
|
|
11542
|
+
patternId: { type: "string", description: "Pattern id from list_layer_effects.patterns." },
|
|
11543
|
+
name: { type: "string", description: "Display name." },
|
|
11544
|
+
scale: { type: "number", minimum: 0.01, maximum: 10, description: "1 = 100 %." },
|
|
11545
|
+
angle: { type: "number", minimum: -360, maximum: 360, description: "Rotation in degrees (default 0)." },
|
|
11546
|
+
link: { type: "boolean", description: "Tile from the layer (default true) or the canvas origin." },
|
|
11547
|
+
phase: { $ref: "#/$defs/phase" }
|
|
11548
|
+
},
|
|
11549
|
+
required: ["type", "patternId", "scale"],
|
|
11550
|
+
additionalProperties: false
|
|
11551
|
+
}
|
|
11552
|
+
]
|
|
11553
|
+
}
|
|
11554
|
+
};
|
|
11555
|
+
var nullable = (schema, description) => ({ anyOf: [schema, { type: "null" }], description });
|
|
11556
|
+
function settingsSchema(forUpdate) {
|
|
11557
|
+
const opt = (schema, description) => forUpdate ? nullable(schema, `${description} null removes it.`) : { ...schema, description };
|
|
11558
|
+
return {
|
|
11559
|
+
type: "object",
|
|
11560
|
+
description: forUpdate ? "Settings to change (only these; nested objects are replaced whole). Which settings a kind takes: see add_layer_effect." : "Settings to change from Photoshop's defaults (all optional). Unknown settings for the kind are refused with the list of its settings.",
|
|
11561
|
+
properties: {
|
|
11562
|
+
enabled: { type: "boolean", description: "All kinds: false keeps the effect but hides it (default true)." },
|
|
11563
|
+
blend: { type: "string", enum: BLEND_IDS, description: "All but bevel-emboss: blend mode (shadows multiply, glows screen, others normal)." },
|
|
11564
|
+
opacity: { type: "number", minimum: 0, maximum: 1, description: "All but bevel-emboss: 0..1 (shadows / glows 0.75, satin 0.5, others 1)." },
|
|
11565
|
+
color: { $ref: "#/$defs/color", description: "drop-shadow, inner-shadow, satin, color-overlay: #rrggbb." },
|
|
11566
|
+
angle: { type: "number", minimum: -360, maximum: 360, description: "Shadows, satin, bevel-emboss: light direction in degrees, counter-clockwise from 3 o'clock (default 120; satin 19)." },
|
|
11567
|
+
useGlobalLight: { type: "boolean", description: "Shadows, bevel-emboss: follow the document global light instead of angle (default true)." },
|
|
11568
|
+
distance: { type: "number", minimum: 0, maximum: 3e4, description: "Shadows, satin: offset in px (default 5; satin 11)." },
|
|
11569
|
+
spread: { type: "number", minimum: 0, maximum: 1, description: "drop-shadow, outer-glow: 0..1 of the size made solid (default 0)." },
|
|
11570
|
+
choke: { type: "number", minimum: 0, maximum: 1, description: "inner-shadow, inner-glow: 0..1 of the size made solid (default 0)." },
|
|
11571
|
+
size: { type: "number", minimum: 0, maximum: 250, description: "Shadows, glows, satin, bevel-emboss: blur / size in px (default 5; satin 14); stroke: width in px (default 3)." },
|
|
11572
|
+
contour: opt({ $ref: "#/$defs/contour" }, "Shadows, glows, satin: coverage contour (default linear)."),
|
|
11573
|
+
antiAlias: { type: "boolean", description: "Shadows, glows, satin: smooth the contour (default false; satin true)." },
|
|
11574
|
+
noise: { type: "number", minimum: 0, maximum: 1, description: "Shadows, glows: speckle 0..1 (default 0)." },
|
|
11575
|
+
knocksOut: { type: "boolean", description: "drop-shadow: the layer hides the shadow beneath its see-through fill (default true)." },
|
|
11576
|
+
fill: { $ref: "#/$defs/fill", description: "outer-glow, inner-glow (color or gradient), stroke (color, gradient or pattern)." },
|
|
11577
|
+
technique: { type: "string", enum: ["softer", "precise", "smooth", "chisel-hard", "chisel-soft"], description: "Glows: softer | precise (default softer); bevel-emboss: smooth | chisel-hard | chisel-soft (default smooth)." },
|
|
11578
|
+
range: { type: "number", minimum: 0.01, maximum: 1, description: "Glows: the part of the glow the contour spans (default 0.5)." },
|
|
11579
|
+
jitter: { type: "number", minimum: 0, maximum: 1, description: "Glows: gradient jitter 0..1 (stored, not rendered; default 0)." },
|
|
11580
|
+
source: { type: "string", enum: ["edge", "center"], description: "inner-glow: glow from the edge (default) or the centre." },
|
|
11581
|
+
style: { type: "string", enum: ["inner-bevel", "outer-bevel", "emboss", "pillow-emboss", "stroke-emboss"], description: "bevel-emboss: style (default inner-bevel)." },
|
|
11582
|
+
depth: { type: "number", minimum: 0, maximum: 10, description: "bevel-emboss: depth, 1 = 100 % (default 1)." },
|
|
11583
|
+
direction: { type: "string", enum: ["up", "down"], description: "bevel-emboss: raised (up, default) or sunk (down)." },
|
|
11584
|
+
soften: { type: "number", minimum: 0, maximum: 16, description: "bevel-emboss: blur of the height in px (default 0)." },
|
|
11585
|
+
altitude: { type: "number", minimum: 0, maximum: 90, description: "bevel-emboss: light altitude in degrees (default 30)." },
|
|
11586
|
+
glossContour: opt({ $ref: "#/$defs/contour" }, "bevel-emboss: gloss contour over the shading (default linear)."),
|
|
11587
|
+
highlightColor: { $ref: "#/$defs/color", description: "bevel-emboss: highlight colour (default #ffffff)." },
|
|
11588
|
+
highlightBlend: { type: "string", enum: BLEND_IDS, description: "bevel-emboss: highlight mode (default screen)." },
|
|
11589
|
+
highlightOpacity: { type: "number", minimum: 0, maximum: 1, description: "bevel-emboss: highlight opacity (default 0.75)." },
|
|
11590
|
+
shadowColor: { $ref: "#/$defs/color", description: "bevel-emboss: shadow colour (default #000000)." },
|
|
11591
|
+
shadowBlend: { type: "string", enum: BLEND_IDS, description: "bevel-emboss: shadow mode (default multiply)." },
|
|
11592
|
+
shadowOpacity: { type: "number", minimum: 0, maximum: 1, description: "bevel-emboss: shadow opacity (default 0.75)." },
|
|
11593
|
+
contourElement: opt(
|
|
11594
|
+
{
|
|
11595
|
+
type: "object",
|
|
11596
|
+
properties: {
|
|
11597
|
+
contour: { $ref: "#/$defs/contour" },
|
|
11598
|
+
range: { type: "number", minimum: 0, maximum: 1, description: "Stored range (default 0.5)." },
|
|
11599
|
+
antiAlias: { type: "boolean", description: "Smooth the contour." }
|
|
11600
|
+
},
|
|
11601
|
+
required: ["contour", "range", "antiAlias"],
|
|
11602
|
+
additionalProperties: false
|
|
11603
|
+
},
|
|
11604
|
+
"bevel-emboss: the Contour element, shaping the bevel's height profile (default off)."
|
|
11605
|
+
),
|
|
11606
|
+
texture: opt(
|
|
11607
|
+
{
|
|
11608
|
+
type: "object",
|
|
11609
|
+
properties: {
|
|
11610
|
+
patternId: { type: "string", description: "Pattern id from list_layer_effects.patterns." },
|
|
11611
|
+
name: { type: "string", description: "Display name." },
|
|
11612
|
+
scale: { type: "number", minimum: 0.01, maximum: 10, description: "1 = 100 %." },
|
|
11613
|
+
depth: { type: "number", minimum: -10, maximum: 10, description: "1 = +100 %; negative carves the pattern in." },
|
|
11614
|
+
invert: { type: "boolean", description: "Invert the pattern." },
|
|
11615
|
+
link: { type: "boolean", description: "Tile from the layer (default true)." },
|
|
11616
|
+
phase: { $ref: "#/$defs/phase" }
|
|
11617
|
+
},
|
|
11618
|
+
required: ["patternId", "scale", "depth", "invert"],
|
|
11619
|
+
additionalProperties: false
|
|
11620
|
+
},
|
|
11621
|
+
"bevel-emboss: the Texture element, a pattern's luminance as extra height (default off)."
|
|
11622
|
+
),
|
|
11623
|
+
invert: { type: "boolean", description: "satin: invert (default true)." },
|
|
11624
|
+
gradient: { $ref: "#/$defs/gradient", description: "gradient-overlay: the gradient (default black to white, 90\xB0)." },
|
|
11625
|
+
dither: { type: "boolean", description: "gradient-overlay: dither (stored; default false)." },
|
|
11626
|
+
patternId: { type: "string", description: "pattern-overlay: pattern id from list_layer_effects.patterns (default checker)." },
|
|
11627
|
+
name: { type: "string", description: "pattern-overlay: pattern display name." },
|
|
11628
|
+
scale: { type: "number", minimum: 0.01, maximum: 10, description: "pattern-overlay: 1 = 100 % (default 1)." },
|
|
11629
|
+
link: { type: "boolean", description: "pattern-overlay: tile from the layer (default true) or the canvas origin." },
|
|
11630
|
+
phase: { $ref: "#/$defs/phase", description: "pattern-overlay: origin offset in px (default 0, 0)." },
|
|
11631
|
+
position: { type: "string", enum: ["outside", "inside", "center"], description: "stroke: where the stroke sits on the edge (default outside)." }
|
|
11632
|
+
},
|
|
11633
|
+
additionalProperties: false
|
|
11634
|
+
};
|
|
11635
|
+
}
|
|
11636
|
+
function patternList() {
|
|
11637
|
+
return builtinPatternIds().map((id) => {
|
|
11638
|
+
const p = builtinPattern(id);
|
|
11639
|
+
return { id, name: p.name, width: p.width, height: p.height, builtin: true };
|
|
11640
|
+
});
|
|
11641
|
+
}
|
|
11642
|
+
function describeLayerEffects(effects) {
|
|
11643
|
+
return {
|
|
11644
|
+
enabled: effects.enabled,
|
|
11645
|
+
scale: effects.scale ?? 1,
|
|
11646
|
+
margin: effectsMargin(effects),
|
|
11647
|
+
fromPsd: Boolean(effects.psd),
|
|
11648
|
+
effects: effects.items.map((e) => ({ ...JSON.parse(JSON.stringify(e)), label: layerEffectLabel(e.kind) }))
|
|
11649
|
+
};
|
|
11650
|
+
}
|
|
11651
|
+
function createImageEffectTools(controller) {
|
|
11652
|
+
const layerArg = (id) => {
|
|
11653
|
+
if (typeof id !== "string" || !id) throw new LayerOperationError("layerId is required (a layer id from list_layers).");
|
|
11654
|
+
requireLayer(controller.getLayers(), id);
|
|
11655
|
+
return id;
|
|
11656
|
+
};
|
|
11657
|
+
const result = (layerId, extra = {}) => ({ layerId, ...extra, ...describeLayerEffects(controller.getLayerEffects(layerId)) });
|
|
11658
|
+
const list = {
|
|
11659
|
+
name: "list_layer_effects",
|
|
11660
|
+
title: "List layer effects",
|
|
11661
|
+
description: "Returns a layer's effects: the master switch (enabled), Scale Effects (scale, 1 = 100 %), margin (px the effects reach beyond the shape), whether they came from a PSD, and every effect with its id, kind, label and all settings. Also returns the document global light and the pattern ids pattern effects can use.",
|
|
11662
|
+
inputSchema: { type: "object", properties: { layerId: LAYER_ID3 }, required: ["layerId"], additionalProperties: false },
|
|
11663
|
+
annotations: { title: "List layer effects", ...READ3 },
|
|
11664
|
+
handler: ({ layerId }) => result(layerArg(layerId), { globalLight: controller.getGlobalLight(), patterns: patternList(), kinds: [...LAYER_EFFECT_KINDS] })
|
|
11665
|
+
};
|
|
11666
|
+
const add = {
|
|
11667
|
+
name: "add_layer_effect",
|
|
11668
|
+
title: "Add a layer effect",
|
|
11669
|
+
description: "Adds a live effect to a pixel, annotation or group layer with Photoshop's defaults, changed by settings: drop-shadow, inner-shadow, outer-glow, inner-glow, bevel-emboss, satin, color-overlay, gradient-overlay, pattern-overlay or stroke. Several of one kind are allowed (the first listed is on top). One undo step. Returns the new effect's id and the layer's effects.",
|
|
11670
|
+
inputSchema: {
|
|
11671
|
+
type: "object",
|
|
11672
|
+
$defs: DEFS,
|
|
11673
|
+
properties: {
|
|
11674
|
+
layerId: LAYER_ID3,
|
|
11675
|
+
kind: { type: "string", enum: [...LAYER_EFFECT_KINDS], description: "Effect kind." },
|
|
11676
|
+
settings: settingsSchema(false),
|
|
11677
|
+
index: { type: "integer", minimum: 0, description: "Position in the layer's effect list (default the end)." }
|
|
11678
|
+
},
|
|
11679
|
+
required: ["layerId", "kind"],
|
|
11680
|
+
additionalProperties: false
|
|
11681
|
+
},
|
|
11682
|
+
annotations: { title: "Add a layer effect", ...WRITE3 },
|
|
11683
|
+
handler: ({ layerId, kind, settings, index }) => {
|
|
11684
|
+
const id = layerArg(layerId);
|
|
11685
|
+
if (!isLayerEffectKind(kind)) throw new LayerOperationError(`kind must be one of ${LAYER_EFFECT_KINDS.join(", ")}.`);
|
|
11686
|
+
const { effect } = controller.addLayerEffect(id, kind, settings ?? {}, index);
|
|
11687
|
+
return result(id, { effectId: effect.id });
|
|
11688
|
+
}
|
|
11689
|
+
};
|
|
11690
|
+
const update = {
|
|
11691
|
+
name: "update_layer_effect",
|
|
11692
|
+
title: "Change a layer effect",
|
|
11693
|
+
description: "Changes settings of one effect (only the given ones; fill, gradient, contour and texture objects are replaced whole, null removes an optional contour or texture). The kind cannot change. Validates everything before changing anything. One undo step. Returns the layer's effects.",
|
|
11694
|
+
inputSchema: {
|
|
11695
|
+
type: "object",
|
|
11696
|
+
$defs: DEFS,
|
|
11697
|
+
properties: { layerId: LAYER_ID3, effectId: EFFECT_ID, settings: settingsSchema(true) },
|
|
11698
|
+
required: ["layerId", "effectId", "settings"],
|
|
11699
|
+
additionalProperties: false
|
|
11700
|
+
},
|
|
11701
|
+
annotations: { title: "Change a layer effect", ...WRITE_IDEMPOTENT3 },
|
|
11702
|
+
handler: ({ layerId, effectId, settings }) => {
|
|
11703
|
+
const id = layerArg(layerId);
|
|
11704
|
+
const changes = settings ?? {};
|
|
11705
|
+
if (!Object.keys(changes).length) throw new LayerOperationError("Give at least one setting to change.");
|
|
11706
|
+
controller.updateLayerEffect(id, effectId, changes);
|
|
11707
|
+
return result(id);
|
|
11708
|
+
}
|
|
11709
|
+
};
|
|
11710
|
+
const remove = {
|
|
11711
|
+
name: "remove_layer_effect",
|
|
11712
|
+
title: "Remove a layer effect",
|
|
11713
|
+
description: "Removes one effect from a layer (to hide it but keep its settings, set enabled false with update_layer_effect instead). One undo step. Returns the layer's remaining effects.",
|
|
11714
|
+
inputSchema: { type: "object", properties: { layerId: LAYER_ID3, effectId: EFFECT_ID }, required: ["layerId", "effectId"], additionalProperties: false },
|
|
11715
|
+
annotations: { title: "Remove a layer effect", ...DESTRUCTIVE2 },
|
|
11716
|
+
handler: ({ layerId, effectId }) => {
|
|
11717
|
+
const id = layerArg(layerId);
|
|
11718
|
+
controller.removeLayerEffect(id, effectId);
|
|
11719
|
+
return result(id);
|
|
11720
|
+
}
|
|
11721
|
+
};
|
|
11722
|
+
const setEnabled = {
|
|
11723
|
+
name: "set_layer_effects_enabled",
|
|
11724
|
+
title: "Switch layer effects on or off",
|
|
11725
|
+
description: "Turns all of a layer's effects on or off at once (the master switch; each effect keeps its own enabled flag) and optionally sets Scale Effects, which multiplies every size, distance and pattern scale. One undo step. Returns the layer's effects.",
|
|
11726
|
+
inputSchema: {
|
|
11727
|
+
type: "object",
|
|
11728
|
+
properties: {
|
|
11729
|
+
layerId: LAYER_ID3,
|
|
11730
|
+
enabled: { type: "boolean", description: "true renders the enabled effects; false hides them all." },
|
|
11731
|
+
scale: { type: "number", minimum: 0.01, maximum: 10, description: "Scale Effects, 1 = 100 % (unchanged when left out)." }
|
|
11732
|
+
},
|
|
11733
|
+
required: ["layerId", "enabled"],
|
|
11734
|
+
additionalProperties: false
|
|
11735
|
+
},
|
|
11736
|
+
annotations: { title: "Switch layer effects on or off", ...WRITE_IDEMPOTENT3 },
|
|
11737
|
+
handler: ({ layerId, enabled, scale }) => {
|
|
11738
|
+
const id = layerArg(layerId);
|
|
11739
|
+
controller.setLayerEffectsEnabled(id, enabled, scale);
|
|
11740
|
+
return result(id);
|
|
11741
|
+
}
|
|
11742
|
+
};
|
|
11743
|
+
const light = {
|
|
11744
|
+
name: "set_global_light",
|
|
11745
|
+
title: "Set the global light",
|
|
11746
|
+
description: "Sets the document global light that shadows and bevels with useGlobalLight follow (Photoshop default: angle 120\xB0, altitude 30\xB0). One undo step. Returns the light.",
|
|
11747
|
+
inputSchema: {
|
|
11748
|
+
type: "object",
|
|
11749
|
+
properties: {
|
|
11750
|
+
angle: { type: "number", minimum: -360, maximum: 360, description: "Degrees, counter-clockwise from 3 o'clock: where the light comes from (unchanged when left out)." },
|
|
11751
|
+
altitude: { type: "number", minimum: 0, maximum: 90, description: "Degrees above the canvas, for bevels (unchanged when left out)." }
|
|
11752
|
+
},
|
|
11753
|
+
additionalProperties: false
|
|
11754
|
+
},
|
|
11755
|
+
annotations: { title: "Set the global light", ...WRITE_IDEMPOTENT3 },
|
|
11756
|
+
handler: ({ angle, altitude }) => {
|
|
11757
|
+
if (angle === void 0 && altitude === void 0) throw new LayerOperationError("Give angle, altitude or both.");
|
|
11758
|
+
const next = {};
|
|
11759
|
+
if (angle !== void 0) next.angle = angle;
|
|
11760
|
+
if (altitude !== void 0) next.altitude = altitude;
|
|
11761
|
+
return { globalLight: controller.setGlobalLight(next) };
|
|
11762
|
+
}
|
|
11763
|
+
};
|
|
11764
|
+
return [list, add, update, remove, setEnabled, light];
|
|
11765
|
+
}
|
|
11766
|
+
|
|
11767
|
+
// src/image-editor/paint-tools.ts
|
|
11768
|
+
var WRITE4 = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
11769
|
+
var DESTRUCTIVE3 = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
|
|
11309
11770
|
var TARGET = {
|
|
11310
11771
|
layerId: { type: "string", description: "Layer to paint (default the active layer; see list_layers)." },
|
|
11311
11772
|
channel: { type: "string", enum: ["pixels", "mask"], description: "pixels (default for a pixel layer) or the layer's mask: black hides, white reveals." }
|
|
@@ -11363,7 +11824,7 @@ function createImagePaintTools(controller) {
|
|
|
11363
11824
|
required: ["points"],
|
|
11364
11825
|
additionalProperties: false
|
|
11365
11826
|
},
|
|
11366
|
-
annotations: { title: "Paint a brush stroke", ...
|
|
11827
|
+
annotations: { title: "Paint a brush stroke", ...WRITE4 },
|
|
11367
11828
|
handler: (args) => controller.paintStroke({
|
|
11368
11829
|
tool: args.tool,
|
|
11369
11830
|
points: args.points,
|
|
@@ -11387,7 +11848,7 @@ function createImagePaintTools(controller) {
|
|
|
11387
11848
|
},
|
|
11388
11849
|
additionalProperties: false
|
|
11389
11850
|
},
|
|
11390
|
-
annotations: { title: "Fill pixels", ...
|
|
11851
|
+
annotations: { title: "Fill pixels", ...WRITE4 },
|
|
11391
11852
|
handler: (args) => controller.fillPixels({
|
|
11392
11853
|
color: args.color,
|
|
11393
11854
|
opacity: args.opacity,
|
|
@@ -11409,15 +11870,15 @@ function createImagePaintTools(controller) {
|
|
|
11409
11870
|
},
|
|
11410
11871
|
additionalProperties: false
|
|
11411
11872
|
},
|
|
11412
|
-
annotations: { title: "Clear pixels", ...
|
|
11873
|
+
annotations: { title: "Clear pixels", ...DESTRUCTIVE3 },
|
|
11413
11874
|
handler: (args) => controller.clearPixels({ opacity: args.opacity, useSelection: args.useSelection, ...readTarget(args) })
|
|
11414
11875
|
};
|
|
11415
11876
|
return [paintStroke, fill, clear];
|
|
11416
11877
|
}
|
|
11417
11878
|
|
|
11418
11879
|
// src/image-editor/psd-tools.ts
|
|
11419
|
-
var
|
|
11420
|
-
var
|
|
11880
|
+
var READ4 = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
11881
|
+
var DESTRUCTIVE4 = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
|
|
11421
11882
|
var DATA = {
|
|
11422
11883
|
type: "string",
|
|
11423
11884
|
minLength: 1,
|
|
@@ -11437,7 +11898,7 @@ function createImagePsdTools(controller) {
|
|
|
11437
11898
|
title: "Inspect a PSD",
|
|
11438
11899
|
description: "Reads a PSD / PSB without opening it: size, bit depth, colour mode, resolution, and every layer (bottom first, a group before its children) with its PSD kind, the layer type it would become and its status (mapped, approximated or dropped, with notes), plus the import warnings. Changes nothing. Call before import_psd to see what would be lost.",
|
|
11439
11900
|
inputSchema: { type: "object", properties: { data: DATA }, required: ["data"], additionalProperties: false },
|
|
11440
|
-
annotations: { title: "Inspect a PSD", ...
|
|
11901
|
+
annotations: { title: "Inspect a PSD", ...READ4 },
|
|
11441
11902
|
handler: ({ data }) => {
|
|
11442
11903
|
const res = importPsd(psdBytesFromBase64(data), { skipPixels: true });
|
|
11443
11904
|
return {
|
|
@@ -11455,7 +11916,7 @@ function createImagePsdTools(controller) {
|
|
|
11455
11916
|
title: "Open a PSD as the document",
|
|
11456
11917
|
description: "Opens a PSD / PSB as the document, replacing the current layers, crop and rotation (one undo step; undo brings the previous document back). Pixel, group and adjustment layers, masks, blend modes, opacity, fill, clipping, visibility and locks map directly; type, smart-object, fill and shape layers come in as their pixels; unsupported adjustments are left out. Returns the new layer tree with ids, the size and the warnings (each names the affected layers).",
|
|
11457
11918
|
inputSchema: { type: "object", properties: { data: DATA }, required: ["data"], additionalProperties: false },
|
|
11458
|
-
annotations: { title: "Open a PSD as the document", ...
|
|
11919
|
+
annotations: { title: "Open a PSD as the document", ...DESTRUCTIVE4 },
|
|
11459
11920
|
handler: ({ data }) => {
|
|
11460
11921
|
const res = controller.loadPsd(psdBytesFromBase64(data));
|
|
11461
11922
|
const s = controller.getState();
|
|
@@ -11474,7 +11935,7 @@ function createImagePsdTools(controller) {
|
|
|
11474
11935
|
title: "Export the document as a PSD",
|
|
11475
11936
|
description: "Writes the document as an 8-bit RGB PSD (a PSB above 30000 px) with real layers, groups, adjustment layers and masks, in the source frame (crop and rotation are not applied). Layer filters and depth masks are baked, annotation layers are rasterized (in a browser; elsewhere left out), and the merged image is the editor's composite. Changes nothing. Returns the file as base64, its size in bytes, whether it is a PSB, and warnings for everything that was changed or left out.",
|
|
11476
11937
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
11477
|
-
annotations: { title: "Export the document as a PSD", ...
|
|
11938
|
+
annotations: { title: "Export the document as a PSD", ...READ4 },
|
|
11478
11939
|
handler: async () => {
|
|
11479
11940
|
const res = await controller.toPsd();
|
|
11480
11941
|
return {
|
|
@@ -11728,7 +12189,9 @@ function createImageEditorToolProvider(controller, options = {}) {
|
|
|
11728
12189
|
...createImageSelectionTools(controller),
|
|
11729
12190
|
...createImageEditTools(controller),
|
|
11730
12191
|
...createImageLayerTools(controller),
|
|
12192
|
+
...createImageEffectTools(controller),
|
|
11731
12193
|
...createImagePaintTools(controller),
|
|
12194
|
+
...createPigmentTools(),
|
|
11732
12195
|
...createImagePsdTools(controller)
|
|
11733
12196
|
]
|
|
11734
12197
|
};
|
|
@@ -12386,6 +12849,10 @@ export {
|
|
|
12386
12849
|
MIN_KELVIN,
|
|
12387
12850
|
MIRED_PER_TEMPERATURE_UNIT,
|
|
12388
12851
|
PAINT_TOOLS,
|
|
12852
|
+
PIGMENT_BANDS,
|
|
12853
|
+
PIGMENT_LAMBDA_MIN,
|
|
12854
|
+
PIGMENT_LAMBDA_STEP,
|
|
12855
|
+
PIGMENT_WAVELENGTHS,
|
|
12389
12856
|
PSD_BLEND_KEYS,
|
|
12390
12857
|
PSD_FILE_ACCEPT,
|
|
12391
12858
|
PaintGesture,
|
|
@@ -12410,6 +12877,7 @@ export {
|
|
|
12410
12877
|
XYZ_D50_TO_SRGB,
|
|
12411
12878
|
ZlibError,
|
|
12412
12879
|
activeAdjustmentLayers,
|
|
12880
|
+
addLayerEffect,
|
|
12413
12881
|
addLayerFilter,
|
|
12414
12882
|
addToHistogram,
|
|
12415
12883
|
adjustmentKindLabel,
|
|
@@ -12473,10 +12941,13 @@ export {
|
|
|
12473
12941
|
createImageCaptureSurface,
|
|
12474
12942
|
createImageEditTools,
|
|
12475
12943
|
createImageEditorToolProvider,
|
|
12944
|
+
createImageEffectTools,
|
|
12476
12945
|
createImageLayerTools,
|
|
12477
12946
|
createImagePaintTools,
|
|
12478
12947
|
createImagePsdTools,
|
|
12479
12948
|
createImageSelectionTools,
|
|
12949
|
+
createPigment,
|
|
12950
|
+
createPigmentTools,
|
|
12480
12951
|
createSelectionMask,
|
|
12481
12952
|
curveLut,
|
|
12482
12953
|
curveLutFromLevels,
|
|
@@ -12497,7 +12968,9 @@ export {
|
|
|
12497
12968
|
depthMaskAlpha,
|
|
12498
12969
|
depthRasterMask,
|
|
12499
12970
|
describeLayer,
|
|
12971
|
+
describeLayerEffects,
|
|
12500
12972
|
describeSelection,
|
|
12973
|
+
deserializeEffects,
|
|
12501
12974
|
deserializeLayer,
|
|
12502
12975
|
deserializeLayers,
|
|
12503
12976
|
deserializeSelection,
|
|
@@ -12582,6 +13055,7 @@ export {
|
|
|
12582
13055
|
isSpatialFilter,
|
|
12583
13056
|
kelvinToTemperature,
|
|
12584
13057
|
layerBadge,
|
|
13058
|
+
layerEffectsOf,
|
|
12585
13059
|
layerLabel,
|
|
12586
13060
|
layerMaskCoverage,
|
|
12587
13061
|
layerMaskFromSelection,
|
|
@@ -12595,6 +13069,8 @@ export {
|
|
|
12595
13069
|
legacyAdjustmentLayer,
|
|
12596
13070
|
legacyMaskOf,
|
|
12597
13071
|
legacyView,
|
|
13072
|
+
lerpPigment,
|
|
13073
|
+
lerpPigmentInto,
|
|
12598
13074
|
levelsValue,
|
|
12599
13075
|
linearSrgbToXy,
|
|
12600
13076
|
linearToSrgb,
|
|
@@ -12605,6 +13081,7 @@ export {
|
|
|
12605
13081
|
maskSummary,
|
|
12606
13082
|
migrateSerializedImageEditorState,
|
|
12607
13083
|
migrateToLayeredState,
|
|
13084
|
+
mixPigments,
|
|
12608
13085
|
modifySelection,
|
|
12609
13086
|
moveCurvePoint,
|
|
12610
13087
|
moveLayer,
|
|
@@ -12660,9 +13137,11 @@ export {
|
|
|
12660
13137
|
refineCoverage,
|
|
12661
13138
|
refineEdgeHalo,
|
|
12662
13139
|
refineSelection,
|
|
13140
|
+
reflectanceToRgb,
|
|
12663
13141
|
removeAlpha,
|
|
12664
13142
|
removeCurvePoint,
|
|
12665
13143
|
removeLayer,
|
|
13144
|
+
removeLayerEffect,
|
|
12666
13145
|
removeLayerFilter,
|
|
12667
13146
|
renderLayeredBase,
|
|
12668
13147
|
requireLayer,
|
|
@@ -12673,6 +13152,7 @@ export {
|
|
|
12673
13152
|
resolveMosaicRegionBounds,
|
|
12674
13153
|
rgbToGray,
|
|
12675
13154
|
rgbToHsl,
|
|
13155
|
+
rgbToReflectance,
|
|
12676
13156
|
runLayerMenuAction,
|
|
12677
13157
|
sampleLut,
|
|
12678
13158
|
sampleToneLut,
|
|
@@ -12684,14 +13164,18 @@ export {
|
|
|
12684
13164
|
selectionToCoverage,
|
|
12685
13165
|
selectionToPixels,
|
|
12686
13166
|
selectionValueAt,
|
|
13167
|
+
serializeEffects,
|
|
12687
13168
|
serializeLayer,
|
|
12688
13169
|
serializeLayers,
|
|
12689
13170
|
serializeLayersExternal,
|
|
12690
13171
|
serializeSelection,
|
|
12691
13172
|
setControlPath,
|
|
13173
|
+
setLayerEffects,
|
|
13174
|
+
setLayerEffectsEnabled,
|
|
12692
13175
|
setLayerMask,
|
|
12693
13176
|
setLayerProperties,
|
|
12694
13177
|
setLum,
|
|
13178
|
+
setPigmentColor,
|
|
12695
13179
|
shiftCoverage,
|
|
12696
13180
|
smoothCoverage,
|
|
12697
13181
|
smoothPoints,
|
|
@@ -12721,6 +13205,7 @@ export {
|
|
|
12721
13205
|
uniformTile,
|
|
12722
13206
|
unionRect,
|
|
12723
13207
|
unprojectCanvasPoint,
|
|
13208
|
+
updateLayerEffect,
|
|
12724
13209
|
updateLayerFilter,
|
|
12725
13210
|
updateLayerMaskProps,
|
|
12726
13211
|
uvToXy,
|