@pixerate/editor 0.89.0 → 0.90.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/image-editor/index.cjs +2770 -176
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +439 -8
- package/dist/image-editor/index.d.ts +439 -8
- package/dist/image-editor/index.js +2653 -59
- package/dist/image-editor/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7;
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9;
|
|
2
2
|
|
|
3
3
|
var _chunkD6FH2YAXcjs = require('../chunk-D6FH2YAX.cjs');
|
|
4
4
|
|
|
@@ -271,8 +271,8 @@ function whiteBalanceFromSample(rgb) {
|
|
|
271
271
|
if (lin[0] + lin[1] + lin[2] <= 1e-6) return { temperature: 0, tint: 0 };
|
|
272
272
|
const src = linearSrgbToXy(applyMatrix3(AS_SHOT_WB_INV, lin));
|
|
273
273
|
const { kelvin, tint } = xyToTempTint(src);
|
|
274
|
-
const
|
|
275
|
-
return { temperature:
|
|
274
|
+
const clamp3 = (v) => Math.max(-100, Math.min(100, v));
|
|
275
|
+
return { temperature: clamp3(kelvinToTemperature(kelvin)), tint: clamp3(tint) };
|
|
276
276
|
}
|
|
277
277
|
var TONE_LUT_SIZE = 4096;
|
|
278
278
|
var GREY = 0.18;
|
|
@@ -1001,20 +1001,20 @@ function distanceTransform(inside, width, height) {
|
|
|
1001
1001
|
for (let y = 0; y < height; y++) {
|
|
1002
1002
|
const row = y * width;
|
|
1003
1003
|
let count = 0;
|
|
1004
|
-
for (let
|
|
1005
|
-
const dq = vertical[row +
|
|
1004
|
+
for (let q2 = 0; q2 < width; q2++) {
|
|
1005
|
+
const dq = vertical[row + q2];
|
|
1006
1006
|
if (dq === NONE) continue;
|
|
1007
1007
|
const fq = dq * dq;
|
|
1008
1008
|
let start = -Infinity;
|
|
1009
1009
|
while (count > 0) {
|
|
1010
1010
|
const p = sites[count - 1];
|
|
1011
1011
|
const dp = vertical[row + p];
|
|
1012
|
-
start = (fq - dp * dp) / (2 * (
|
|
1012
|
+
start = (fq - dp * dp) / (2 * (q2 - p)) + (q2 + p) * 0.5;
|
|
1013
1013
|
if (start > starts[count - 1]) break;
|
|
1014
1014
|
count--;
|
|
1015
1015
|
}
|
|
1016
1016
|
if (count === 0) start = -Infinity;
|
|
1017
|
-
sites[count] =
|
|
1017
|
+
sites[count] = q2;
|
|
1018
1018
|
starts[count] = start;
|
|
1019
1019
|
count++;
|
|
1020
1020
|
}
|
|
@@ -1551,9 +1551,9 @@ function levelsValue(ch, v, quantum) {
|
|
|
1551
1551
|
const range = Math.max(1e-6, ch.inWhite - ch.inBlack);
|
|
1552
1552
|
let u;
|
|
1553
1553
|
if (quantum !== void 0 && Number.isFinite(quantum) && quantum >= 1) {
|
|
1554
|
-
const
|
|
1555
|
-
const vq = Math.round(v *
|
|
1556
|
-
u = Math.floor(clamp01((vq - ch.inBlack) / range) *
|
|
1554
|
+
const q2 = quantum;
|
|
1555
|
+
const vq = Math.round(v * q2) / q2;
|
|
1556
|
+
u = Math.floor(clamp01((vq - ch.inBlack) / range) * q2 + 0.5 + 1e-3) / q2;
|
|
1557
1557
|
} else {
|
|
1558
1558
|
u = clamp01((v - ch.inBlack) / range);
|
|
1559
1559
|
}
|
|
@@ -1587,13 +1587,13 @@ function rgbToHsl(c) {
|
|
|
1587
1587
|
}
|
|
1588
1588
|
function hslToRgb(h, s, l) {
|
|
1589
1589
|
if (s <= 0) return [l, l, l];
|
|
1590
|
-
const
|
|
1591
|
-
const p = 2 * l -
|
|
1590
|
+
const q2 = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
1591
|
+
const p = 2 * l - q2;
|
|
1592
1592
|
const f = (t) => {
|
|
1593
1593
|
t = remEuclid(t, 1);
|
|
1594
|
-
if (t < 1 / 6) return p + (
|
|
1595
|
-
if (t < 0.5) return
|
|
1596
|
-
if (t < 2 / 3) return p + (
|
|
1594
|
+
if (t < 1 / 6) return p + (q2 - p) * 6 * t;
|
|
1595
|
+
if (t < 0.5) return q2;
|
|
1596
|
+
if (t < 2 / 3) return p + (q2 - p) * (2 / 3 - t) * 6;
|
|
1597
1597
|
return p;
|
|
1598
1598
|
};
|
|
1599
1599
|
return [f(h + 1 / 3), f(h), f(h - 1 / 3)];
|
|
@@ -1671,10 +1671,10 @@ function vibranceLinear(c, v) {
|
|
|
1671
1671
|
t2 = t * (1 - a / 4) * (1 - a + a * t * (1 + t) / 2);
|
|
1672
1672
|
v2 = mx - a * shape;
|
|
1673
1673
|
} else {
|
|
1674
|
-
const [c0, c1, p,
|
|
1674
|
+
const [c0, c1, p, q2, r0, ra, rt] = VIBRANCE_BOOST;
|
|
1675
1675
|
const w = vibranceSkin(hsvHue(c, mx, mn));
|
|
1676
1676
|
const a = v * (1 - w) + 0.64 * Math.pow(v, 1.6) * w;
|
|
1677
|
-
const boost = (c0 * a + c1 * a * a) * Math.pow(t, p) * Math.pow(1 - t,
|
|
1677
|
+
const boost = (c0 * a + c1 * a * a) * Math.pow(t, p) * Math.pow(1 - t, q2) * Math.exp((r0 + ra * a + rt * (1 - t)) * Math.max(0, 1 - mx));
|
|
1678
1678
|
t2 = Math.min(1, t * (1 + boost));
|
|
1679
1679
|
v2 = mx + v / 4 * shape;
|
|
1680
1680
|
}
|
|
@@ -3961,7 +3961,7 @@ function polygonCoverage(points, width, height, antiAlias = true) {
|
|
|
3961
3961
|
if (a.y < b.y) edges.push({ top: a.y, bottom: b.y, ax: a.x, ay: a.y, bx: b.x, by: b.y });
|
|
3962
3962
|
else if (b.y < a.y) edges.push({ top: b.y, bottom: a.y, ax: a.x, ay: a.y, bx: b.x, by: b.y });
|
|
3963
3963
|
}
|
|
3964
|
-
edges.sort((p,
|
|
3964
|
+
edges.sort((p, q2) => p.top - q2.top);
|
|
3965
3965
|
let next = 0;
|
|
3966
3966
|
let active = [];
|
|
3967
3967
|
const xs = [];
|
|
@@ -4425,13 +4425,13 @@ function refineCoverage(guide, m, w, h, params = {}) {
|
|
|
4425
4425
|
if (any) {
|
|
4426
4426
|
const dist = distanceTransform(boundary, w, h);
|
|
4427
4427
|
const r = gfRadius(p);
|
|
4428
|
-
const
|
|
4428
|
+
const q2 = guidedFilterColor(guide, m, w, h, r);
|
|
4429
4429
|
const widths = p.smartRadius ? edgeWidth(guide, w, h, r) : null;
|
|
4430
4430
|
for (let i = 0; i < n; i++) {
|
|
4431
4431
|
const reff = widths ? Math.min(Math.max(p.radius, 1.5), Math.max(1.5, widths[i])) : p.radius;
|
|
4432
4432
|
const wgt = Math.min(1, Math.max(0, reff + 1 - dist[i]));
|
|
4433
4433
|
if (wgt > 0) {
|
|
4434
|
-
const qi = Math.min(1, Math.max(0,
|
|
4434
|
+
const qi = Math.min(1, Math.max(0, q2[i]));
|
|
4435
4435
|
a[i] = m[i] + (qi - m[i]) * wgt;
|
|
4436
4436
|
}
|
|
4437
4437
|
}
|
|
@@ -4583,6 +4583,53 @@ function serializeLayers(layers) {
|
|
|
4583
4583
|
};
|
|
4584
4584
|
return { layers: layers.map((l) => serializeLayer(l, ctx)), assets };
|
|
4585
4585
|
}
|
|
4586
|
+
var externalRefs = /* @__PURE__ */ new WeakMap();
|
|
4587
|
+
async function serializeLayersExternal(layers, store) {
|
|
4588
|
+
const inline = serializeLayers(layers);
|
|
4589
|
+
let refs = externalRefs.get(store);
|
|
4590
|
+
if (!refs) {
|
|
4591
|
+
refs = /* @__PURE__ */ new Map();
|
|
4592
|
+
externalRefs.set(store, refs);
|
|
4593
|
+
}
|
|
4594
|
+
const assets = {};
|
|
4595
|
+
for (const [id, url] of Object.entries(inline.assets)) {
|
|
4596
|
+
let ref = refs.get(url);
|
|
4597
|
+
if (!ref) {
|
|
4598
|
+
const parsed = _chunkH543GD6Tcjs.parseDataUrl.call(void 0, url);
|
|
4599
|
+
const png = decodePngHeader(parsed.bytes);
|
|
4600
|
+
ref = await store.put(new Blob([parsed.bytes], { type: "image/png" }), { id, width: png.width, height: png.height });
|
|
4601
|
+
if (typeof ref !== "string" || !ref) throw new Error(`The asset store returned no reference for "${id}".`);
|
|
4602
|
+
refs.set(url, ref);
|
|
4603
|
+
}
|
|
4604
|
+
assets[id] = ref;
|
|
4605
|
+
}
|
|
4606
|
+
return { layers: inline.layers, assets };
|
|
4607
|
+
}
|
|
4608
|
+
function decodePngHeader(bytes) {
|
|
4609
|
+
const u32 = (o) => (bytes[o] << 24 | bytes[o + 1] << 16 | bytes[o + 2] << 8 | bytes[o + 3]) >>> 0;
|
|
4610
|
+
return { width: u32(16), height: u32(20) };
|
|
4611
|
+
}
|
|
4612
|
+
async function resolveExternalAssets(assets, store, problems) {
|
|
4613
|
+
const out = {};
|
|
4614
|
+
for (const [id, ref] of Object.entries(assets)) {
|
|
4615
|
+
if (ref.startsWith("data:")) {
|
|
4616
|
+
out[id] = ref;
|
|
4617
|
+
continue;
|
|
4618
|
+
}
|
|
4619
|
+
if (!store) {
|
|
4620
|
+
problems.push(`Asset "${id}" is external (${ref}) and no asset store was given.`);
|
|
4621
|
+
continue;
|
|
4622
|
+
}
|
|
4623
|
+
try {
|
|
4624
|
+
const blob = await store.get(ref);
|
|
4625
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
4626
|
+
out[id] = `data:image/png;base64,${_chunkH543GD6Tcjs.bytesToBase64.call(void 0, bytes)}`;
|
|
4627
|
+
} catch (err) {
|
|
4628
|
+
problems.push(`Asset "${id}" (${ref}) could not be fetched: ${err.message}`);
|
|
4629
|
+
}
|
|
4630
|
+
}
|
|
4631
|
+
return out;
|
|
4632
|
+
}
|
|
4586
4633
|
function decodePngDataUrl(url, channels) {
|
|
4587
4634
|
const parsed = _chunkH543GD6Tcjs.parseDataUrl.call(void 0, url);
|
|
4588
4635
|
if (!parsed) throw new Error("Asset is not a data URL.");
|
|
@@ -4976,6 +5023,2070 @@ function unionRect(a, b) {
|
|
|
4976
5023
|
return { x, y, width: Math.max(a.x + a.width, b.x + b.width) - x, height: Math.max(a.y + a.height, b.y + b.height) - y };
|
|
4977
5024
|
}
|
|
4978
5025
|
|
|
5026
|
+
// src/image-editor/psd/binary.ts
|
|
5027
|
+
var PsdError = class extends Error {
|
|
5028
|
+
constructor(message) {
|
|
5029
|
+
super(message);
|
|
5030
|
+
this.name = "PsdError";
|
|
5031
|
+
}
|
|
5032
|
+
};
|
|
5033
|
+
var PsdReader = class _PsdReader {
|
|
5034
|
+
constructor(data, start = 0, end = data.length) {
|
|
5035
|
+
this.data = data;
|
|
5036
|
+
this.start = start;
|
|
5037
|
+
this.end = end;
|
|
5038
|
+
this.pos = start;
|
|
5039
|
+
}
|
|
5040
|
+
|
|
5041
|
+
|
|
5042
|
+
|
|
5043
|
+
|
|
5044
|
+
get remaining() {
|
|
5045
|
+
return this.end - this.pos;
|
|
5046
|
+
}
|
|
5047
|
+
get offset() {
|
|
5048
|
+
return this.pos - this.start;
|
|
5049
|
+
}
|
|
5050
|
+
need(n, what) {
|
|
5051
|
+
if (n < 0 || this.pos + n > this.end) throw new PsdError(`Unexpected end of data reading ${what} at byte ${this.pos}.`);
|
|
5052
|
+
}
|
|
5053
|
+
u8() {
|
|
5054
|
+
this.need(1, "a byte");
|
|
5055
|
+
return this.data[this.pos++];
|
|
5056
|
+
}
|
|
5057
|
+
i8() {
|
|
5058
|
+
const v = this.u8();
|
|
5059
|
+
return v > 127 ? v - 256 : v;
|
|
5060
|
+
}
|
|
5061
|
+
u16() {
|
|
5062
|
+
this.need(2, "a 16-bit value");
|
|
5063
|
+
const v = this.data[this.pos] << 8 | this.data[this.pos + 1];
|
|
5064
|
+
this.pos += 2;
|
|
5065
|
+
return v;
|
|
5066
|
+
}
|
|
5067
|
+
i16() {
|
|
5068
|
+
const v = this.u16();
|
|
5069
|
+
return v > 32767 ? v - 65536 : v;
|
|
5070
|
+
}
|
|
5071
|
+
u32() {
|
|
5072
|
+
this.need(4, "a 32-bit value");
|
|
5073
|
+
const d = this.data;
|
|
5074
|
+
const p = this.pos;
|
|
5075
|
+
this.pos += 4;
|
|
5076
|
+
return (d[p] << 24 | d[p + 1] << 16 | d[p + 2] << 8 | d[p + 3]) >>> 0;
|
|
5077
|
+
}
|
|
5078
|
+
i32() {
|
|
5079
|
+
return this.u32() | 0;
|
|
5080
|
+
}
|
|
5081
|
+
u64() {
|
|
5082
|
+
const hi = this.u32();
|
|
5083
|
+
const lo = this.u32();
|
|
5084
|
+
const v = hi * 2 ** 32 + lo;
|
|
5085
|
+
if (!Number.isSafeInteger(v)) throw new PsdError("A 64-bit length is too large.");
|
|
5086
|
+
return v;
|
|
5087
|
+
}
|
|
5088
|
+
i64() {
|
|
5089
|
+
const hi = this.i32();
|
|
5090
|
+
const lo = this.u32();
|
|
5091
|
+
return hi * 2 ** 32 + lo;
|
|
5092
|
+
}
|
|
5093
|
+
f32() {
|
|
5094
|
+
this.need(4, "a float");
|
|
5095
|
+
const v = new DataView(this.data.buffer, this.data.byteOffset + this.pos, 4).getFloat32(0, false);
|
|
5096
|
+
this.pos += 4;
|
|
5097
|
+
return v;
|
|
5098
|
+
}
|
|
5099
|
+
f64() {
|
|
5100
|
+
this.need(8, "a double");
|
|
5101
|
+
const v = new DataView(this.data.buffer, this.data.byteOffset + this.pos, 8).getFloat64(0, false);
|
|
5102
|
+
this.pos += 8;
|
|
5103
|
+
return v;
|
|
5104
|
+
}
|
|
5105
|
+
/** A length field: 8 bytes in PSB where the format says so, else 4. */
|
|
5106
|
+
len(long2) {
|
|
5107
|
+
return long2 ? this.u64() : this.u32();
|
|
5108
|
+
}
|
|
5109
|
+
bytes(n) {
|
|
5110
|
+
this.need(n, `${n} bytes`);
|
|
5111
|
+
const out = this.data.subarray(this.pos, this.pos + n);
|
|
5112
|
+
this.pos += n;
|
|
5113
|
+
return out;
|
|
5114
|
+
}
|
|
5115
|
+
ascii(n) {
|
|
5116
|
+
return String.fromCharCode(...this.bytes(n));
|
|
5117
|
+
}
|
|
5118
|
+
skip(n) {
|
|
5119
|
+
this.need(n, `${n} bytes`);
|
|
5120
|
+
this.pos += n;
|
|
5121
|
+
}
|
|
5122
|
+
/** A reader over the next `n` bytes (and skips them here). */
|
|
5123
|
+
sub(n) {
|
|
5124
|
+
this.need(n, `a ${n}-byte section`);
|
|
5125
|
+
const r = new _PsdReader(this.data, this.pos, this.pos + n);
|
|
5126
|
+
this.pos += n;
|
|
5127
|
+
return r;
|
|
5128
|
+
}
|
|
5129
|
+
peek(n) {
|
|
5130
|
+
return this.data.subarray(this.pos, Math.min(this.end, this.pos + n));
|
|
5131
|
+
}
|
|
5132
|
+
rest() {
|
|
5133
|
+
const out = this.data.subarray(this.pos, this.end);
|
|
5134
|
+
this.pos = this.end;
|
|
5135
|
+
return out;
|
|
5136
|
+
}
|
|
5137
|
+
/** Refuses counts that could not fit in what is left (each item at least `size` bytes). */
|
|
5138
|
+
checkCount(n, size, what) {
|
|
5139
|
+
if (n * size > this.remaining) throw new PsdError(`${what}: count ${n} does not fit in the remaining ${this.remaining} bytes.`);
|
|
5140
|
+
}
|
|
5141
|
+
/** Pascal string padded to a multiple of `align` (length byte included). */
|
|
5142
|
+
pascal(align) {
|
|
5143
|
+
const n = this.u8();
|
|
5144
|
+
const s = this.bytes(n);
|
|
5145
|
+
const pad = (align - (1 + n) % align) % align;
|
|
5146
|
+
this.skip(Math.min(pad, this.remaining));
|
|
5147
|
+
return s;
|
|
5148
|
+
}
|
|
5149
|
+
/** Photoshop Unicode string: u32 code-unit count, UTF-16BE units (trailing NULs dropped). */
|
|
5150
|
+
unicode() {
|
|
5151
|
+
const n = this.u32();
|
|
5152
|
+
this.checkCount(n, 2, "Unicode string");
|
|
5153
|
+
let s = "";
|
|
5154
|
+
for (let i = 0; i < n; i++) s += String.fromCharCode(this.u16());
|
|
5155
|
+
return s.replace(/\u0000+$/, "");
|
|
5156
|
+
}
|
|
5157
|
+
};
|
|
5158
|
+
var PsdWriter = (_class4 = class {constructor() { _class4.prototype.__init24.call(this);_class4.prototype.__init25.call(this); }
|
|
5159
|
+
__init24() {this.buf = new Uint8Array(1 << 16)}
|
|
5160
|
+
__init25() {this.length = 0}
|
|
5161
|
+
ensure(n) {
|
|
5162
|
+
if (this.length + n <= this.buf.length) return;
|
|
5163
|
+
let size = this.buf.length * 2;
|
|
5164
|
+
while (size < this.length + n) size *= 2;
|
|
5165
|
+
const next = new Uint8Array(size);
|
|
5166
|
+
next.set(this.buf.subarray(0, this.length));
|
|
5167
|
+
this.buf = next;
|
|
5168
|
+
}
|
|
5169
|
+
u8(v) {
|
|
5170
|
+
this.ensure(1);
|
|
5171
|
+
this.buf[this.length++] = v & 255;
|
|
5172
|
+
}
|
|
5173
|
+
u16(v) {
|
|
5174
|
+
this.ensure(2);
|
|
5175
|
+
this.buf[this.length++] = v >>> 8 & 255;
|
|
5176
|
+
this.buf[this.length++] = v & 255;
|
|
5177
|
+
}
|
|
5178
|
+
i16(v) {
|
|
5179
|
+
this.u16(v < 0 ? v + 65536 : v);
|
|
5180
|
+
}
|
|
5181
|
+
u32(v) {
|
|
5182
|
+
this.ensure(4);
|
|
5183
|
+
this.buf[this.length++] = v >>> 24 & 255;
|
|
5184
|
+
this.buf[this.length++] = v >>> 16 & 255;
|
|
5185
|
+
this.buf[this.length++] = v >>> 8 & 255;
|
|
5186
|
+
this.buf[this.length++] = v & 255;
|
|
5187
|
+
}
|
|
5188
|
+
i32(v) {
|
|
5189
|
+
this.u32(v >>> 0);
|
|
5190
|
+
}
|
|
5191
|
+
u64(v) {
|
|
5192
|
+
this.u32(Math.floor(v / 2 ** 32));
|
|
5193
|
+
this.u32(v >>> 0);
|
|
5194
|
+
}
|
|
5195
|
+
f64(v) {
|
|
5196
|
+
this.ensure(8);
|
|
5197
|
+
new DataView(this.buf.buffer, this.length, 8).setFloat64(0, v, false);
|
|
5198
|
+
this.length += 8;
|
|
5199
|
+
}
|
|
5200
|
+
bytes(b) {
|
|
5201
|
+
this.ensure(b.length);
|
|
5202
|
+
this.buf.set(b, this.length);
|
|
5203
|
+
this.length += b.length;
|
|
5204
|
+
}
|
|
5205
|
+
ascii(s) {
|
|
5206
|
+
for (let i = 0; i < s.length; i++) this.u8(s.charCodeAt(i));
|
|
5207
|
+
}
|
|
5208
|
+
zeros(n) {
|
|
5209
|
+
this.ensure(n);
|
|
5210
|
+
this.buf.fill(0, this.length, this.length + n);
|
|
5211
|
+
this.length += n;
|
|
5212
|
+
}
|
|
5213
|
+
/** Reserves a length field; `endLen` fills it with the bytes written since. */
|
|
5214
|
+
beginLen(long2) {
|
|
5215
|
+
const at = this.length;
|
|
5216
|
+
if (long2) this.u64(0);
|
|
5217
|
+
else this.u32(0);
|
|
5218
|
+
return { at, long: long2 };
|
|
5219
|
+
}
|
|
5220
|
+
endLen(mark) {
|
|
5221
|
+
const n = this.length - mark.at - (mark.long ? 8 : 4);
|
|
5222
|
+
const save = this.length;
|
|
5223
|
+
this.length = mark.at;
|
|
5224
|
+
if (mark.long) this.u64(n);
|
|
5225
|
+
else this.u32(n);
|
|
5226
|
+
this.length = save;
|
|
5227
|
+
return n;
|
|
5228
|
+
}
|
|
5229
|
+
/** Pascal string padded to a multiple of `align`. */
|
|
5230
|
+
pascal(s, align) {
|
|
5231
|
+
const n = Math.min(255, s.length);
|
|
5232
|
+
this.u8(n);
|
|
5233
|
+
this.bytes(s.subarray(0, n));
|
|
5234
|
+
this.zeros((align - (1 + n) % align) % align);
|
|
5235
|
+
}
|
|
5236
|
+
unicode(s, nul = false) {
|
|
5237
|
+
const n = s.length + (nul ? 1 : 0);
|
|
5238
|
+
this.u32(n);
|
|
5239
|
+
for (let i = 0; i < s.length; i++) this.u16(s.charCodeAt(i));
|
|
5240
|
+
if (nul) this.u16(0);
|
|
5241
|
+
}
|
|
5242
|
+
result() {
|
|
5243
|
+
return this.buf.slice(0, this.length);
|
|
5244
|
+
}
|
|
5245
|
+
}, _class4);
|
|
5246
|
+
function decodeLegacyName(b) {
|
|
5247
|
+
try {
|
|
5248
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(b);
|
|
5249
|
+
} catch (e12) {
|
|
5250
|
+
return String.fromCharCode(...b);
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
5253
|
+
function encodeLegacyName(s) {
|
|
5254
|
+
const out = [];
|
|
5255
|
+
for (const ch of s) {
|
|
5256
|
+
const c = ch.codePointAt(0);
|
|
5257
|
+
out.push(c >= 32 && c < 127 ? c : 63);
|
|
5258
|
+
if (out.length >= 255) break;
|
|
5259
|
+
}
|
|
5260
|
+
return Uint8Array.from(out);
|
|
5261
|
+
}
|
|
5262
|
+
|
|
5263
|
+
// src/image-editor/psd/descriptor.ts
|
|
5264
|
+
var MAX_DEPTH = 64;
|
|
5265
|
+
var STRING_IDS = /* @__PURE__ */ new Set(["warp", "list", "time"]);
|
|
5266
|
+
function descriptor(classId, items = []) {
|
|
5267
|
+
return { name: "", classId, items };
|
|
5268
|
+
}
|
|
5269
|
+
function descGet(d, key) {
|
|
5270
|
+
return _optionalChain([d, 'access', _93 => _93.items, 'access', _94 => _94.find, 'call', _95 => _95(([k]) => k === key), 'optionalAccess', _96 => _96[1]]);
|
|
5271
|
+
}
|
|
5272
|
+
function descNumber(d, key) {
|
|
5273
|
+
const v = descGet(d, key);
|
|
5274
|
+
if (!v) return void 0;
|
|
5275
|
+
if (v.type === "long" || v.type === "doub" || v.type === "UntF" || v.type === "comp") return v.value;
|
|
5276
|
+
return void 0;
|
|
5277
|
+
}
|
|
5278
|
+
function descBool(d, key) {
|
|
5279
|
+
const v = descGet(d, key);
|
|
5280
|
+
return _optionalChain([v, 'optionalAccess', _97 => _97.type]) === "bool" ? v.value : void 0;
|
|
5281
|
+
}
|
|
5282
|
+
function descObject(d, key) {
|
|
5283
|
+
const v = descGet(d, key);
|
|
5284
|
+
return v && (v.type === "Objc" || v.type === "GlbO") ? v.value : void 0;
|
|
5285
|
+
}
|
|
5286
|
+
function readId(r) {
|
|
5287
|
+
const n = r.u32();
|
|
5288
|
+
return n === 0 ? r.ascii(4) : r.ascii(n);
|
|
5289
|
+
}
|
|
5290
|
+
function writeId(w, id) {
|
|
5291
|
+
if (id.length === 4 && !STRING_IDS.has(id)) {
|
|
5292
|
+
w.u32(0);
|
|
5293
|
+
w.ascii(id);
|
|
5294
|
+
} else {
|
|
5295
|
+
w.u32(id.length);
|
|
5296
|
+
w.ascii(id);
|
|
5297
|
+
}
|
|
5298
|
+
}
|
|
5299
|
+
function readClass(r) {
|
|
5300
|
+
return { name: r.unicode(), classId: readId(r) };
|
|
5301
|
+
}
|
|
5302
|
+
function writeClass(w, c) {
|
|
5303
|
+
w.unicode(c.name);
|
|
5304
|
+
writeId(w, c.classId);
|
|
5305
|
+
}
|
|
5306
|
+
function readReferenceItem(r) {
|
|
5307
|
+
const type = r.ascii(4);
|
|
5308
|
+
switch (type) {
|
|
5309
|
+
case "prop":
|
|
5310
|
+
return { type, class: readClass(r), key: readId(r) };
|
|
5311
|
+
case "Clss":
|
|
5312
|
+
return { type, class: readClass(r) };
|
|
5313
|
+
case "Enmr":
|
|
5314
|
+
return { type, class: readClass(r), typeId: readId(r), value: readId(r) };
|
|
5315
|
+
case "rele":
|
|
5316
|
+
return { type, class: readClass(r), offset: r.i32() };
|
|
5317
|
+
case "Idnt":
|
|
5318
|
+
return { type, class: readClass(r), id: r.u32() };
|
|
5319
|
+
case "indx":
|
|
5320
|
+
return { type, class: readClass(r), index: r.u32() };
|
|
5321
|
+
case "name":
|
|
5322
|
+
return { type, class: readClass(r), name: r.unicode() };
|
|
5323
|
+
default:
|
|
5324
|
+
throw new PsdError(`Unsupported descriptor reference item "${type}".`);
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
function writeReferenceItem(w, it) {
|
|
5328
|
+
w.ascii(it.type);
|
|
5329
|
+
writeClass(w, it.class);
|
|
5330
|
+
switch (it.type) {
|
|
5331
|
+
case "prop":
|
|
5332
|
+
writeId(w, it.key);
|
|
5333
|
+
break;
|
|
5334
|
+
case "Enmr":
|
|
5335
|
+
writeId(w, it.typeId);
|
|
5336
|
+
writeId(w, it.value);
|
|
5337
|
+
break;
|
|
5338
|
+
case "rele":
|
|
5339
|
+
w.i32(it.offset);
|
|
5340
|
+
break;
|
|
5341
|
+
case "Idnt":
|
|
5342
|
+
w.u32(it.id);
|
|
5343
|
+
break;
|
|
5344
|
+
case "indx":
|
|
5345
|
+
w.u32(it.index);
|
|
5346
|
+
break;
|
|
5347
|
+
case "name":
|
|
5348
|
+
w.unicode(it.name);
|
|
5349
|
+
break;
|
|
5350
|
+
}
|
|
5351
|
+
}
|
|
5352
|
+
function readValue(r, depth) {
|
|
5353
|
+
if (depth > MAX_DEPTH) throw new PsdError("Descriptor nesting is too deep.");
|
|
5354
|
+
const type = r.ascii(4);
|
|
5355
|
+
switch (type) {
|
|
5356
|
+
case "obj ": {
|
|
5357
|
+
const n = r.u32();
|
|
5358
|
+
r.checkCount(n, 8, "Descriptor reference");
|
|
5359
|
+
const items = [];
|
|
5360
|
+
for (let i = 0; i < n; i++) items.push(readReferenceItem(r));
|
|
5361
|
+
return { type, items };
|
|
5362
|
+
}
|
|
5363
|
+
case "Objc":
|
|
5364
|
+
case "GlbO":
|
|
5365
|
+
return { type, value: readDescriptorBody(r, depth + 1) };
|
|
5366
|
+
case "VlLs": {
|
|
5367
|
+
const n = r.u32();
|
|
5368
|
+
r.checkCount(n, 4, "Descriptor list");
|
|
5369
|
+
const items = [];
|
|
5370
|
+
for (let i = 0; i < n; i++) items.push(readValue(r, depth + 1));
|
|
5371
|
+
return { type, items };
|
|
5372
|
+
}
|
|
5373
|
+
case "doub":
|
|
5374
|
+
return { type, value: r.f64() };
|
|
5375
|
+
case "UntF":
|
|
5376
|
+
return { type, unit: r.ascii(4), value: r.f64() };
|
|
5377
|
+
case "UnFl": {
|
|
5378
|
+
const unit = r.ascii(4);
|
|
5379
|
+
const n = r.u32();
|
|
5380
|
+
r.checkCount(n, 8, "Unit float list");
|
|
5381
|
+
const values = [];
|
|
5382
|
+
for (let i = 0; i < n; i++) values.push(r.f64());
|
|
5383
|
+
return { type, unit, values };
|
|
5384
|
+
}
|
|
5385
|
+
case "TEXT":
|
|
5386
|
+
return { type, value: r.unicode() };
|
|
5387
|
+
case "enum":
|
|
5388
|
+
return { type, typeId: readId(r), value: readId(r) };
|
|
5389
|
+
case "long":
|
|
5390
|
+
return { type, value: r.i32() };
|
|
5391
|
+
case "comp":
|
|
5392
|
+
return { type, value: r.i64() };
|
|
5393
|
+
case "bool":
|
|
5394
|
+
return { type, value: r.u8() !== 0 };
|
|
5395
|
+
case "type":
|
|
5396
|
+
case "GlbC":
|
|
5397
|
+
return { type, class: readClass(r) };
|
|
5398
|
+
case "alis":
|
|
5399
|
+
case "Pth ":
|
|
5400
|
+
case "tdta":
|
|
5401
|
+
return { type, data: r.bytes(r.u32()) };
|
|
5402
|
+
case "ObAr":
|
|
5403
|
+
return { type, prefix: r.u32(), body: readDescriptorBody(r, depth + 1) };
|
|
5404
|
+
default:
|
|
5405
|
+
throw new PsdError(`Unsupported descriptor value type "${type}".`);
|
|
5406
|
+
}
|
|
5407
|
+
}
|
|
5408
|
+
function writeValue(w, v) {
|
|
5409
|
+
w.ascii(v.type);
|
|
5410
|
+
switch (v.type) {
|
|
5411
|
+
case "obj ":
|
|
5412
|
+
w.u32(v.items.length);
|
|
5413
|
+
for (const it of v.items) writeReferenceItem(w, it);
|
|
5414
|
+
break;
|
|
5415
|
+
case "Objc":
|
|
5416
|
+
case "GlbO":
|
|
5417
|
+
writeDescriptorBody(w, v.value);
|
|
5418
|
+
break;
|
|
5419
|
+
case "VlLs":
|
|
5420
|
+
w.u32(v.items.length);
|
|
5421
|
+
for (const it of v.items) writeValue(w, it);
|
|
5422
|
+
break;
|
|
5423
|
+
case "doub":
|
|
5424
|
+
w.f64(v.value);
|
|
5425
|
+
break;
|
|
5426
|
+
case "UntF":
|
|
5427
|
+
w.ascii(v.unit);
|
|
5428
|
+
w.f64(v.value);
|
|
5429
|
+
break;
|
|
5430
|
+
case "UnFl":
|
|
5431
|
+
w.ascii(v.unit);
|
|
5432
|
+
w.u32(v.values.length);
|
|
5433
|
+
for (const x of v.values) w.f64(x);
|
|
5434
|
+
break;
|
|
5435
|
+
case "TEXT":
|
|
5436
|
+
w.unicode(v.value, true);
|
|
5437
|
+
break;
|
|
5438
|
+
case "enum":
|
|
5439
|
+
writeId(w, v.typeId);
|
|
5440
|
+
writeId(w, v.value);
|
|
5441
|
+
break;
|
|
5442
|
+
case "long":
|
|
5443
|
+
w.i32(v.value);
|
|
5444
|
+
break;
|
|
5445
|
+
case "comp":
|
|
5446
|
+
w.u32(Math.floor(v.value / 2 ** 32) >>> 0);
|
|
5447
|
+
w.u32(v.value >>> 0);
|
|
5448
|
+
break;
|
|
5449
|
+
case "bool":
|
|
5450
|
+
w.u8(v.value ? 1 : 0);
|
|
5451
|
+
break;
|
|
5452
|
+
case "type":
|
|
5453
|
+
case "GlbC":
|
|
5454
|
+
writeClass(w, v.class);
|
|
5455
|
+
break;
|
|
5456
|
+
case "alis":
|
|
5457
|
+
case "Pth ":
|
|
5458
|
+
case "tdta":
|
|
5459
|
+
w.u32(v.data.length);
|
|
5460
|
+
w.bytes(v.data);
|
|
5461
|
+
break;
|
|
5462
|
+
case "ObAr":
|
|
5463
|
+
w.u32(v.prefix);
|
|
5464
|
+
writeDescriptorBody(w, v.body);
|
|
5465
|
+
break;
|
|
5466
|
+
}
|
|
5467
|
+
}
|
|
5468
|
+
function readDescriptorBody(r, depth) {
|
|
5469
|
+
if (depth > MAX_DEPTH) throw new PsdError("Descriptor nesting is too deep.");
|
|
5470
|
+
const name = r.unicode();
|
|
5471
|
+
const classId = readId(r);
|
|
5472
|
+
const n = r.u32();
|
|
5473
|
+
r.checkCount(n, 10, "Descriptor items");
|
|
5474
|
+
const items = [];
|
|
5475
|
+
for (let i = 0; i < n; i++) {
|
|
5476
|
+
const key = readId(r);
|
|
5477
|
+
items.push([key, readValue(r, depth + 1)]);
|
|
5478
|
+
}
|
|
5479
|
+
return { name, classId, items };
|
|
5480
|
+
}
|
|
5481
|
+
function writeDescriptorBody(w, d) {
|
|
5482
|
+
w.unicode(d.name, true);
|
|
5483
|
+
writeId(w, d.classId);
|
|
5484
|
+
w.u32(d.items.length);
|
|
5485
|
+
for (const [k, v] of d.items) {
|
|
5486
|
+
writeId(w, k);
|
|
5487
|
+
writeValue(w, v);
|
|
5488
|
+
}
|
|
5489
|
+
}
|
|
5490
|
+
function readVersionedDescriptor(r) {
|
|
5491
|
+
const version = r.u32();
|
|
5492
|
+
if (version !== 16) throw new PsdError(`Descriptor version ${version}, expected 16.`);
|
|
5493
|
+
return readDescriptorBody(r, 0);
|
|
5494
|
+
}
|
|
5495
|
+
function writeVersionedDescriptor(w, d) {
|
|
5496
|
+
w.u32(16);
|
|
5497
|
+
writeDescriptorBody(w, d);
|
|
5498
|
+
}
|
|
5499
|
+
function parseVersionedDescriptor(bytes) {
|
|
5500
|
+
return readVersionedDescriptor(new PsdReader(bytes));
|
|
5501
|
+
}
|
|
5502
|
+
function versionedDescriptorBytes(d) {
|
|
5503
|
+
const w = new PsdWriter();
|
|
5504
|
+
writeVersionedDescriptor(w, d);
|
|
5505
|
+
return w.result();
|
|
5506
|
+
}
|
|
5507
|
+
|
|
5508
|
+
// src/image-editor/psd/adjust.ts
|
|
5509
|
+
var ADJUSTMENT_KEYS = ["levl", "curv", "hue2", "brit", "nvrt", "thrs", "post", "expA", "vibA", "blnc", "mixr", "grdm", "phfl", "selc", "blwh", "clrL"];
|
|
5510
|
+
var SUPPORTED_ADJUSTMENT_KEYS = {
|
|
5511
|
+
levl: "levels",
|
|
5512
|
+
curv: "curves",
|
|
5513
|
+
hue2: "hueSaturation",
|
|
5514
|
+
vibA: "vibrance",
|
|
5515
|
+
blnc: "colorBalance",
|
|
5516
|
+
blwh: "blackWhite",
|
|
5517
|
+
nvrt: "invert",
|
|
5518
|
+
post: "posterize",
|
|
5519
|
+
thrs: "threshold",
|
|
5520
|
+
phfl: "photoFilter"
|
|
5521
|
+
};
|
|
5522
|
+
var LABELS = {
|
|
5523
|
+
levl: "Levels",
|
|
5524
|
+
curv: "Curves",
|
|
5525
|
+
hue2: "Hue/Saturation",
|
|
5526
|
+
brit: "Brightness/Contrast",
|
|
5527
|
+
nvrt: "Invert",
|
|
5528
|
+
thrs: "Threshold",
|
|
5529
|
+
post: "Posterize",
|
|
5530
|
+
expA: "Exposure",
|
|
5531
|
+
vibA: "Vibrance",
|
|
5532
|
+
blnc: "Color Balance",
|
|
5533
|
+
mixr: "Channel Mixer",
|
|
5534
|
+
grdm: "Gradient Map",
|
|
5535
|
+
phfl: "Photo Filter",
|
|
5536
|
+
selc: "Selective Color",
|
|
5537
|
+
blwh: "Black & White",
|
|
5538
|
+
clrL: "Color Lookup"
|
|
5539
|
+
};
|
|
5540
|
+
function adjustmentLabel(key) {
|
|
5541
|
+
return _nullishCoalesce(LABELS[key], () => ( "adjustment"));
|
|
5542
|
+
}
|
|
5543
|
+
var clamp2 = (v, lo, hi) => Math.min(hi, Math.max(lo, v));
|
|
5544
|
+
var toHex = (rgb) => "#" + rgb.map((v) => Math.round(clamp2(v, 0, 1) * 255).toString(16).padStart(2, "0")).join("");
|
|
5545
|
+
function canonicalBounds(b) {
|
|
5546
|
+
if (b.some((v) => !Number.isFinite(v))) return [-45, -15, 15, 45];
|
|
5547
|
+
const rem = (v) => (v % 360 + 360) % 360;
|
|
5548
|
+
const out = [b[0], b[0], b[0], b[0]];
|
|
5549
|
+
for (let k = 1; k < 4; k++) out[k] = Math.min(out[k - 1] + rem(b[k] - out[k - 1]), out[0] + 359);
|
|
5550
|
+
const centre = (out[1] + out[2]) / 2;
|
|
5551
|
+
const shift = rem(centre + 30) - 30 - centre;
|
|
5552
|
+
return out.map((v) => v + shift);
|
|
5553
|
+
}
|
|
5554
|
+
function levelsRecord(r) {
|
|
5555
|
+
const inBlack = r.u16();
|
|
5556
|
+
const inWhite = r.u16();
|
|
5557
|
+
const outBlack = r.u16();
|
|
5558
|
+
const outWhite = r.u16();
|
|
5559
|
+
const gamma = r.u16() / 100;
|
|
5560
|
+
return {
|
|
5561
|
+
inBlack: clamp2(inBlack, 0, 255),
|
|
5562
|
+
inWhite: clamp2(inWhite, 0, 255),
|
|
5563
|
+
gamma: clamp2(gamma || 1, 0.1, 9.99),
|
|
5564
|
+
outBlack: clamp2(outBlack, 0, 255),
|
|
5565
|
+
outWhite: clamp2(outWhite, 0, 255)
|
|
5566
|
+
};
|
|
5567
|
+
}
|
|
5568
|
+
function curveFromMap(map) {
|
|
5569
|
+
const pts = [];
|
|
5570
|
+
for (let i = 0; i <= 255; i += 15) pts.push({ input: i, output: map[i] });
|
|
5571
|
+
return pts;
|
|
5572
|
+
}
|
|
5573
|
+
function parseCurves(d) {
|
|
5574
|
+
const r = new PsdReader(d);
|
|
5575
|
+
const pencil = r.u8() !== 0;
|
|
5576
|
+
const version = r.u16();
|
|
5577
|
+
if (version !== 1 && version !== 4) return null;
|
|
5578
|
+
const bits = r.u32();
|
|
5579
|
+
const params = defaultAdjustmentParams("curves");
|
|
5580
|
+
const order = ["master", "red", "green", "blue"];
|
|
5581
|
+
for (let bit = 0; bit < 32; bit++) {
|
|
5582
|
+
if (!(bits & 1 << bit)) continue;
|
|
5583
|
+
let pts;
|
|
5584
|
+
if (pencil) {
|
|
5585
|
+
pts = curveFromMap(r.bytes(256));
|
|
5586
|
+
} else {
|
|
5587
|
+
const n = r.u16();
|
|
5588
|
+
r.checkCount(n, 4, "Curve points");
|
|
5589
|
+
pts = [];
|
|
5590
|
+
for (let i = 0; i < n; i++) {
|
|
5591
|
+
const output = r.u16();
|
|
5592
|
+
const input = r.u16();
|
|
5593
|
+
pts.push({ input: clamp2(input, 0, 255), output: clamp2(output, 0, 255) });
|
|
5594
|
+
}
|
|
5595
|
+
pts.sort((a, b) => a.input - b.input);
|
|
5596
|
+
}
|
|
5597
|
+
if (bit < 4 && pts.length >= 2) params[order[bit]] = pts;
|
|
5598
|
+
}
|
|
5599
|
+
return { kind: "curves", params, approximated: pencil ? "its pencil curve is approximated by points" : void 0 };
|
|
5600
|
+
}
|
|
5601
|
+
function parseHueSaturation(d) {
|
|
5602
|
+
const r = new PsdReader(d);
|
|
5603
|
+
r.u16();
|
|
5604
|
+
const colorize = r.u8() !== 0;
|
|
5605
|
+
r.u8();
|
|
5606
|
+
const triple = () => [r.i16(), r.i16(), r.i16()];
|
|
5607
|
+
const col = triple();
|
|
5608
|
+
const master = triple();
|
|
5609
|
+
const ranges = [];
|
|
5610
|
+
for (let i = 0; i < 6; i++) {
|
|
5611
|
+
if (r.remaining < 14) {
|
|
5612
|
+
ranges.push(neutralHueRange(i));
|
|
5613
|
+
continue;
|
|
5614
|
+
}
|
|
5615
|
+
const b = [r.u16(), r.u16(), r.u16(), r.u16()];
|
|
5616
|
+
const [hue2, saturation2, lightness2] = triple();
|
|
5617
|
+
ranges.push({ hue: hue2, saturation: saturation2, lightness: lightness2, bounds: canonicalBounds(b) });
|
|
5618
|
+
}
|
|
5619
|
+
const [hue, saturation, lightness] = colorize ? col : master;
|
|
5620
|
+
return { kind: "hueSaturation", params: { hue, saturation, lightness, colorize, ranges } };
|
|
5621
|
+
}
|
|
5622
|
+
var BW_KEYS = [
|
|
5623
|
+
["reds", "Rd "],
|
|
5624
|
+
["yellows", "Yllw"],
|
|
5625
|
+
["greens", "Grn "],
|
|
5626
|
+
["cyans", "Cyn "],
|
|
5627
|
+
["blues", "Bl "],
|
|
5628
|
+
["magentas", "Mgnt"]
|
|
5629
|
+
];
|
|
5630
|
+
var BW_TINT = [225 / 255, 211 / 255, 179 / 255];
|
|
5631
|
+
function descRgb(d) {
|
|
5632
|
+
if (!d) return null;
|
|
5633
|
+
if (descNumber(d, "redFloat") !== void 0) {
|
|
5634
|
+
return [descNumber(d, "redFloat"), _nullishCoalesce(descNumber(d, "greenFloat"), () => ( 0)), _nullishCoalesce(descNumber(d, "blueFloat"), () => ( 0))].map((v) => clamp2(v, 0, 1));
|
|
5635
|
+
}
|
|
5636
|
+
const r = descNumber(d, "Rd ");
|
|
5637
|
+
const g = descNumber(d, "Grn ");
|
|
5638
|
+
const b = descNumber(d, "Bl ");
|
|
5639
|
+
if (r === void 0 || g === void 0 || b === void 0) return null;
|
|
5640
|
+
return [r, g, b].map((v) => clamp2(v / 255, 0, 1));
|
|
5641
|
+
}
|
|
5642
|
+
function parseBlackWhite(d) {
|
|
5643
|
+
const desc = parseVersionedDescriptor(d);
|
|
5644
|
+
const params = defaultAdjustmentParams("blackWhite");
|
|
5645
|
+
for (const [field, key] of BW_KEYS) {
|
|
5646
|
+
const v = descNumber(desc, key);
|
|
5647
|
+
if (v !== void 0) params[field] = clamp2(v, -200, 300);
|
|
5648
|
+
}
|
|
5649
|
+
params.tint = descBool(desc, "useTint") ? toHex(_nullishCoalesce(descRgb(descObject(desc, "tintColor")), () => ( BW_TINT))) : null;
|
|
5650
|
+
return { kind: "blackWhite", params };
|
|
5651
|
+
}
|
|
5652
|
+
function labToRgb(l, a, b) {
|
|
5653
|
+
const fy = (l + 16) / 116;
|
|
5654
|
+
const fx = fy + a / 500;
|
|
5655
|
+
const fz = fy - b / 200;
|
|
5656
|
+
const f = (t) => t > 6 / 29 ? t ** 3 : 3 * (6 / 29) ** 2 * (t - 4 / 29);
|
|
5657
|
+
const xyz = [f(fx) * D50[0], f(fy) * D50[1], f(fz) * D50[2]];
|
|
5658
|
+
return XYZ_D50_TO_SRGB.map((row) => linearToSrgb(clamp2(row[0] * xyz[0] + row[1] * xyz[1] + row[2] * xyz[2], 0, 1)));
|
|
5659
|
+
}
|
|
5660
|
+
function decodePsdColor(space, c) {
|
|
5661
|
+
const n = (v) => v / 65535;
|
|
5662
|
+
switch (space) {
|
|
5663
|
+
case 0:
|
|
5664
|
+
return [n(c[0]), n(c[1]), n(c[2])];
|
|
5665
|
+
case 1: {
|
|
5666
|
+
const h = n(c[0]) * 360;
|
|
5667
|
+
const s = n(c[1]);
|
|
5668
|
+
const v = n(c[2]);
|
|
5669
|
+
const k = (m) => (m + h / 60) % 6;
|
|
5670
|
+
const f = (m) => v - v * s * Math.max(0, Math.min(k(m), 4 - k(m), 1));
|
|
5671
|
+
return [f(5), f(3), f(1)];
|
|
5672
|
+
}
|
|
5673
|
+
case 2: {
|
|
5674
|
+
const [cy, m, y, k] = c.map(n);
|
|
5675
|
+
return [cy * k, m * k, y * k];
|
|
5676
|
+
}
|
|
5677
|
+
case 7: {
|
|
5678
|
+
const signed = (v) => v << 16 >> 16;
|
|
5679
|
+
return labToRgb(Math.min(c[0], 1e4) / 100, signed(c[1]) / 100, signed(c[2]) / 100);
|
|
5680
|
+
}
|
|
5681
|
+
case 8: {
|
|
5682
|
+
const v = 1 - Math.min(c[0], 1e4) / 1e4;
|
|
5683
|
+
return [v, v, v];
|
|
5684
|
+
}
|
|
5685
|
+
default:
|
|
5686
|
+
return null;
|
|
5687
|
+
}
|
|
5688
|
+
}
|
|
5689
|
+
function parsePhotoFilter(d) {
|
|
5690
|
+
const r = new PsdReader(d);
|
|
5691
|
+
const version = r.u16();
|
|
5692
|
+
let rgb;
|
|
5693
|
+
if (version === 2) {
|
|
5694
|
+
const space = r.u16();
|
|
5695
|
+
const c = [r.u16(), r.u16(), r.u16(), r.u16()];
|
|
5696
|
+
rgb = [0, 2, 7, 8].includes(space) ? decodePsdColor(space, c) : null;
|
|
5697
|
+
} else if (version === 3) {
|
|
5698
|
+
const rel = [r.u32(), r.u32(), r.u32()].map((v) => v / 32768);
|
|
5699
|
+
if (rel.some((v) => v > 2)) return null;
|
|
5700
|
+
const xyz = [rel[0] * D50[0], rel[1], rel[2] * D50[2]];
|
|
5701
|
+
rgb = XYZ_D50_TO_SRGB.map((row) => linearToSrgb(clamp2(row[0] * xyz[0] + row[1] * xyz[1] + row[2] * xyz[2], 0, 1)));
|
|
5702
|
+
} else {
|
|
5703
|
+
return null;
|
|
5704
|
+
}
|
|
5705
|
+
if (!rgb) return null;
|
|
5706
|
+
const density = clamp2(r.u32(), 0, 100);
|
|
5707
|
+
const preserveLuminosity = r.u8() !== 0;
|
|
5708
|
+
return { kind: "photoFilter", params: { color: toHex(rgb), density, preserveLuminosity } };
|
|
5709
|
+
}
|
|
5710
|
+
function parseAdjustmentBlock(key, data) {
|
|
5711
|
+
try {
|
|
5712
|
+
const r = new PsdReader(data);
|
|
5713
|
+
switch (key) {
|
|
5714
|
+
case "nvrt":
|
|
5715
|
+
return { kind: "invert", params: {} };
|
|
5716
|
+
case "thrs":
|
|
5717
|
+
return { kind: "threshold", params: { level: clamp2(r.u16(), 1, 255) } };
|
|
5718
|
+
case "post":
|
|
5719
|
+
return { kind: "posterize", params: { levels: clamp2(r.u16(), 2, 255) } };
|
|
5720
|
+
case "levl": {
|
|
5721
|
+
r.u16();
|
|
5722
|
+
const master = levelsRecord(r);
|
|
5723
|
+
const red = levelsRecord(r);
|
|
5724
|
+
const green = levelsRecord(r);
|
|
5725
|
+
const blue = levelsRecord(r);
|
|
5726
|
+
return { kind: "levels", params: { master, red, green, blue } };
|
|
5727
|
+
}
|
|
5728
|
+
case "curv":
|
|
5729
|
+
return parseCurves(data);
|
|
5730
|
+
case "hue2":
|
|
5731
|
+
return parseHueSaturation(data);
|
|
5732
|
+
case "vibA": {
|
|
5733
|
+
const desc = parseVersionedDescriptor(data);
|
|
5734
|
+
const get = (k) => clamp2(_nullishCoalesce(descNumber(desc, k), () => ( 0)), -100, 100);
|
|
5735
|
+
return { kind: "vibrance", params: { vibrance: get("vibrance"), saturation: get("Strt") } };
|
|
5736
|
+
}
|
|
5737
|
+
case "blnc": {
|
|
5738
|
+
const tone2 = () => [r.i16(), r.i16(), r.i16()].map((v) => clamp2(v, -100, 100));
|
|
5739
|
+
const shadows = tone2();
|
|
5740
|
+
const midtones = tone2();
|
|
5741
|
+
const highlights = tone2();
|
|
5742
|
+
return { kind: "colorBalance", params: { shadows, midtones, highlights, preserveLuminosity: r.u8() !== 0 } };
|
|
5743
|
+
}
|
|
5744
|
+
case "blwh":
|
|
5745
|
+
return parseBlackWhite(data);
|
|
5746
|
+
case "phfl":
|
|
5747
|
+
return parsePhotoFilter(data);
|
|
5748
|
+
default:
|
|
5749
|
+
return null;
|
|
5750
|
+
}
|
|
5751
|
+
} catch (e13) {
|
|
5752
|
+
return null;
|
|
5753
|
+
}
|
|
5754
|
+
}
|
|
5755
|
+
var q = (v) => Math.round(clamp2(v, 0, 255));
|
|
5756
|
+
var i16 = (v) => Math.round(clamp2(v, -32768, 32767));
|
|
5757
|
+
function writeLevels(w, c) {
|
|
5758
|
+
w.u16(q(c.inBlack));
|
|
5759
|
+
w.u16(q(c.inWhite));
|
|
5760
|
+
w.u16(q(c.outBlack));
|
|
5761
|
+
w.u16(q(c.outWhite));
|
|
5762
|
+
w.u16(Math.round(clamp2(c.gamma * 100, 1, 999)));
|
|
5763
|
+
}
|
|
5764
|
+
var long = (value) => ({ type: "long", value: i16(value) });
|
|
5765
|
+
function writeAdjustmentBlock(kind, params) {
|
|
5766
|
+
const w = new PsdWriter();
|
|
5767
|
+
switch (kind) {
|
|
5768
|
+
case "invert":
|
|
5769
|
+
return { key: "nvrt", data: new Uint8Array(0) };
|
|
5770
|
+
case "threshold": {
|
|
5771
|
+
const p = params;
|
|
5772
|
+
w.u16(Math.max(1, q(p.level)));
|
|
5773
|
+
w.u16(0);
|
|
5774
|
+
return { key: "thrs", data: w.result() };
|
|
5775
|
+
}
|
|
5776
|
+
case "posterize": {
|
|
5777
|
+
const p = params;
|
|
5778
|
+
w.u16(Math.round(clamp2(p.levels, 2, 255)));
|
|
5779
|
+
w.u16(0);
|
|
5780
|
+
return { key: "post", data: w.result() };
|
|
5781
|
+
}
|
|
5782
|
+
case "levels": {
|
|
5783
|
+
const p = params;
|
|
5784
|
+
w.u16(2);
|
|
5785
|
+
for (const c of [p.master, p.red, p.green, p.blue]) writeLevels(w, c);
|
|
5786
|
+
const ident = { inBlack: 0, inWhite: 255, gamma: 1, outBlack: 0, outWhite: 255 };
|
|
5787
|
+
for (let i = 4; i < 29; i++) writeLevels(w, ident);
|
|
5788
|
+
return { key: "levl", data: w.result() };
|
|
5789
|
+
}
|
|
5790
|
+
case "curves": {
|
|
5791
|
+
const p = params;
|
|
5792
|
+
w.u8(0);
|
|
5793
|
+
w.u16(1);
|
|
5794
|
+
w.u32(15);
|
|
5795
|
+
for (const c of [p.master, p.red, p.green, p.blue]) {
|
|
5796
|
+
const pts = c.slice(0, 19);
|
|
5797
|
+
w.u16(pts.length);
|
|
5798
|
+
for (const pt of pts) {
|
|
5799
|
+
w.u16(q(pt.output));
|
|
5800
|
+
w.u16(q(pt.input));
|
|
5801
|
+
}
|
|
5802
|
+
}
|
|
5803
|
+
return { key: "curv", data: w.result() };
|
|
5804
|
+
}
|
|
5805
|
+
case "hueSaturation": {
|
|
5806
|
+
const p = params;
|
|
5807
|
+
w.u16(2);
|
|
5808
|
+
w.u8(p.colorize ? 1 : 0);
|
|
5809
|
+
w.u8(0);
|
|
5810
|
+
for (let k = 0; k < 2; k++) for (const x of [p.hue, p.saturation, p.lightness]) w.i16(i16(x));
|
|
5811
|
+
for (let i = 0; i < 6; i++) {
|
|
5812
|
+
const r = _nullishCoalesce(p.ranges[i], () => ( neutralHueRange(i)));
|
|
5813
|
+
for (const b of r.bounds) w.u16(Math.round((b % 360 + 360) % 360) % 360);
|
|
5814
|
+
for (const x of [r.hue, r.saturation, r.lightness]) w.i16(i16(x));
|
|
5815
|
+
}
|
|
5816
|
+
return { key: "hue2", data: w.result() };
|
|
5817
|
+
}
|
|
5818
|
+
case "vibrance": {
|
|
5819
|
+
const p = params;
|
|
5820
|
+
const d = descriptor("null", [
|
|
5821
|
+
["vibrance", long(clamp2(p.vibrance, -100, 100))],
|
|
5822
|
+
["Strt", long(clamp2(p.saturation, -100, 100))]
|
|
5823
|
+
]);
|
|
5824
|
+
return { key: "vibA", data: versionedDescriptorBytes(d) };
|
|
5825
|
+
}
|
|
5826
|
+
case "colorBalance": {
|
|
5827
|
+
const p = params;
|
|
5828
|
+
for (const x of [...p.shadows, ...p.midtones, ...p.highlights]) w.i16(i16(clamp2(x, -100, 100)));
|
|
5829
|
+
w.u8(p.preserveLuminosity ? 1 : 0);
|
|
5830
|
+
w.u8(0);
|
|
5831
|
+
return { key: "blnc", data: w.result() };
|
|
5832
|
+
}
|
|
5833
|
+
case "blackWhite": {
|
|
5834
|
+
const p = params;
|
|
5835
|
+
const tint = p.tint ? hexToRgb(p.tint) : BW_TINT;
|
|
5836
|
+
const dbl = (v) => ({ type: "doub", value: clamp2(v, 0, 1) * 255 });
|
|
5837
|
+
const items = BW_KEYS.map(([field, key]) => [key, long(clamp2(p[field], -200, 300))]);
|
|
5838
|
+
items.push(
|
|
5839
|
+
["useTint", { type: "bool", value: p.tint !== null }],
|
|
5840
|
+
["tintColor", { type: "Objc", value: descriptor("RGBC", [["Rd ", dbl(tint[0])], ["Grn ", dbl(tint[1])], ["Bl ", dbl(tint[2])]]) }],
|
|
5841
|
+
["bwPresetKind", { type: "long", value: 1 }],
|
|
5842
|
+
["blackAndWhitePresetFileName", { type: "TEXT", value: "" }]
|
|
5843
|
+
);
|
|
5844
|
+
return { key: "blwh", data: versionedDescriptorBytes(descriptor("null", items)) };
|
|
5845
|
+
}
|
|
5846
|
+
case "photoFilter": {
|
|
5847
|
+
const p = params;
|
|
5848
|
+
const rgb = hexToRgb(p.color);
|
|
5849
|
+
w.u16(2);
|
|
5850
|
+
w.u16(0);
|
|
5851
|
+
for (const x of rgb) w.u16(Math.round(clamp2(x, 0, 1) * 65535));
|
|
5852
|
+
w.u16(0);
|
|
5853
|
+
w.u32(Math.round(clamp2(p.density, 0, 100)));
|
|
5854
|
+
w.u8(p.preserveLuminosity ? 1 : 0);
|
|
5855
|
+
w.zeros(3);
|
|
5856
|
+
return { key: "phfl", data: w.result() };
|
|
5857
|
+
}
|
|
5858
|
+
}
|
|
5859
|
+
throw new Error(`Unknown adjustment kind "${kind}".`);
|
|
5860
|
+
}
|
|
5861
|
+
|
|
5862
|
+
// src/image-editor/psd/compression.ts
|
|
5863
|
+
var MAX_DECODED_BYTES = 2 ** 31;
|
|
5864
|
+
function rowBytes(width, depth) {
|
|
5865
|
+
return depth === 1 ? Math.ceil(width / 8) : width * Math.max(1, depth >> 3);
|
|
5866
|
+
}
|
|
5867
|
+
function decodedLength(l) {
|
|
5868
|
+
const total = l.planes * l.height * rowBytes(l.width, l.depth);
|
|
5869
|
+
if (total > MAX_DECODED_BYTES) throw new PsdError(`Decoded channel data of ${total} bytes is larger than the ${MAX_DECODED_BYTES}-byte limit.`);
|
|
5870
|
+
return total;
|
|
5871
|
+
}
|
|
5872
|
+
function packbitsBound(n) {
|
|
5873
|
+
return n + Math.ceil(n / 128);
|
|
5874
|
+
}
|
|
5875
|
+
function packbitsEncode(src, out, at) {
|
|
5876
|
+
const n = src.length;
|
|
5877
|
+
let i = 0;
|
|
5878
|
+
while (i < n) {
|
|
5879
|
+
let run = 1;
|
|
5880
|
+
while (i + run < n && run < 128 && src[i + run] === src[i]) run++;
|
|
5881
|
+
if (run >= 2) {
|
|
5882
|
+
out[at++] = 257 - run & 255;
|
|
5883
|
+
out[at++] = src[i];
|
|
5884
|
+
i += run;
|
|
5885
|
+
continue;
|
|
5886
|
+
}
|
|
5887
|
+
const start = i;
|
|
5888
|
+
let len = 0;
|
|
5889
|
+
while (i < n && len < 128) {
|
|
5890
|
+
if (i + 2 < n && src[i] === src[i + 1] && src[i] === src[i + 2]) break;
|
|
5891
|
+
i++;
|
|
5892
|
+
len++;
|
|
5893
|
+
}
|
|
5894
|
+
out[at++] = len - 1;
|
|
5895
|
+
out.set(src.subarray(start, start + len), at);
|
|
5896
|
+
at += len;
|
|
5897
|
+
}
|
|
5898
|
+
return at;
|
|
5899
|
+
}
|
|
5900
|
+
function packbitsDecodeInto(src, expected, out, at) {
|
|
5901
|
+
const target = at + expected;
|
|
5902
|
+
let i = 0;
|
|
5903
|
+
while (at < target) {
|
|
5904
|
+
if (i >= src.length) throw new PsdError("PackBits row ended early.");
|
|
5905
|
+
const h = src[i++];
|
|
5906
|
+
if (h < 128) {
|
|
5907
|
+
const len = h + 1;
|
|
5908
|
+
if (i + len > src.length) throw new PsdError("PackBits literal is truncated.");
|
|
5909
|
+
if (at + len > target) throw new PsdError("PackBits literal overflows its row.");
|
|
5910
|
+
out.set(src.subarray(i, i + len), at);
|
|
5911
|
+
at += len;
|
|
5912
|
+
i += len;
|
|
5913
|
+
} else if (h !== 128) {
|
|
5914
|
+
const len = 257 - h;
|
|
5915
|
+
if (i >= src.length) throw new PsdError("PackBits run is truncated.");
|
|
5916
|
+
const b = src[i++];
|
|
5917
|
+
if (at + len > target) throw new PsdError("PackBits run overflows its row.");
|
|
5918
|
+
out.fill(b, at, at + len);
|
|
5919
|
+
at += len;
|
|
5920
|
+
}
|
|
5921
|
+
}
|
|
5922
|
+
return at;
|
|
5923
|
+
}
|
|
5924
|
+
function inflateChecked(data, expected) {
|
|
5925
|
+
let out;
|
|
5926
|
+
try {
|
|
5927
|
+
out = _chunkH543GD6Tcjs.inflate.call(void 0, data, { maxOutput: expected + (1 << 20), sizeHint: expected, verify: false });
|
|
5928
|
+
} catch (e) {
|
|
5929
|
+
throw new PsdError(`ZIP channel data: ${e instanceof _chunkH543GD6Tcjs.ZlibError || e instanceof Error ? e.message : String(e)}`);
|
|
5930
|
+
}
|
|
5931
|
+
if (out.length < expected) throw new PsdError(`ZIP stream produced ${out.length} of ${expected} bytes.`);
|
|
5932
|
+
return out.length === expected ? out : out.subarray(0, expected);
|
|
5933
|
+
}
|
|
5934
|
+
function unpredict(buf, l) {
|
|
5935
|
+
const rb = rowBytes(l.width, l.depth);
|
|
5936
|
+
if (rb === 0) return;
|
|
5937
|
+
const w = l.width;
|
|
5938
|
+
const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
|
|
5939
|
+
for (let o = 0; o + rb <= buf.length; o += rb) {
|
|
5940
|
+
if (l.depth === 1 || l.depth === 8) {
|
|
5941
|
+
for (let i = 1; i < rb; i++) buf[o + i] = buf[o + i] + buf[o + i - 1] & 255;
|
|
5942
|
+
} else if (l.depth === 16) {
|
|
5943
|
+
for (let i = 1; i < w; i++) {
|
|
5944
|
+
const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
|
|
5945
|
+
const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
|
|
5946
|
+
const v = a + b & 65535;
|
|
5947
|
+
buf[o + 2 * i] = v >> 8;
|
|
5948
|
+
buf[o + 2 * i + 1] = v & 255;
|
|
5949
|
+
}
|
|
5950
|
+
} else if (l.depth === 32) {
|
|
5951
|
+
for (let i = 1; i < rb; i++) buf[o + i] = buf[o + i] + buf[o + i - 1] & 255;
|
|
5952
|
+
scratch.set(buf.subarray(o, o + rb));
|
|
5953
|
+
for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + 4 * i + k] = scratch[k * w + i];
|
|
5954
|
+
} else {
|
|
5955
|
+
throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
|
|
5956
|
+
}
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
function decodeRle(r, l, total) {
|
|
5960
|
+
const rows = l.planes * l.height;
|
|
5961
|
+
const rb = rowBytes(l.width, l.depth);
|
|
5962
|
+
r.checkCount(rows, l.psb ? 4 : 2, "RLE row counts");
|
|
5963
|
+
const counts = new Array(rows);
|
|
5964
|
+
for (let i = 0; i < rows; i++) counts[i] = l.psb ? r.u32() : r.u16();
|
|
5965
|
+
if (total > r.remaining * 130) throw new PsdError("RLE data is too short for its declared size.");
|
|
5966
|
+
const out = new Uint8Array(total);
|
|
5967
|
+
let at = 0;
|
|
5968
|
+
for (const c of counts) at = packbitsDecodeInto(r.bytes(c), rb, out, at);
|
|
5969
|
+
return out;
|
|
5970
|
+
}
|
|
5971
|
+
function decodePlanes(compression, data, l) {
|
|
5972
|
+
const total = decodedLength(l);
|
|
5973
|
+
switch (compression) {
|
|
5974
|
+
case 0:
|
|
5975
|
+
if (data.length < total) throw new PsdError(`Raw channel data has ${data.length} of ${total} bytes.`);
|
|
5976
|
+
return data.slice(0, total);
|
|
5977
|
+
case 1:
|
|
5978
|
+
return decodeRle(new PsdReader(data), l, total);
|
|
5979
|
+
case 2:
|
|
5980
|
+
return inflateChecked(data, total).slice();
|
|
5981
|
+
case 3: {
|
|
5982
|
+
const v = inflateChecked(data, total).slice();
|
|
5983
|
+
unpredict(v, l);
|
|
5984
|
+
return v;
|
|
5985
|
+
}
|
|
5986
|
+
default:
|
|
5987
|
+
throw new PsdError(`Unsupported compression method ${compression}.`);
|
|
5988
|
+
}
|
|
5989
|
+
}
|
|
5990
|
+
function encodeRle(decoded2, l) {
|
|
5991
|
+
const rows = l.planes * l.height;
|
|
5992
|
+
const rb = rowBytes(l.width, l.depth);
|
|
5993
|
+
const cs = l.psb ? 4 : 2;
|
|
5994
|
+
const packed = new Uint8Array(rows * packbitsBound(rb));
|
|
5995
|
+
let at = 0;
|
|
5996
|
+
const counts = new Uint8Array(rows * cs);
|
|
5997
|
+
for (let row = 0; row < rows; row++) {
|
|
5998
|
+
const start = at;
|
|
5999
|
+
at = packbitsEncode(decoded2.subarray(row * rb, (row + 1) * rb), packed, at);
|
|
6000
|
+
const n = at - start;
|
|
6001
|
+
if (cs === 2) {
|
|
6002
|
+
if (n > 65535) throw new PsdError("An RLE row is longer than 65535 bytes; write a PSB instead.");
|
|
6003
|
+
counts[row * 2] = n >> 8;
|
|
6004
|
+
counts[row * 2 + 1] = n & 255;
|
|
6005
|
+
} else {
|
|
6006
|
+
counts[row * 4] = n >>> 24;
|
|
6007
|
+
counts[row * 4 + 1] = n >>> 16 & 255;
|
|
6008
|
+
counts[row * 4 + 2] = n >>> 8 & 255;
|
|
6009
|
+
counts[row * 4 + 3] = n & 255;
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
const out = new Uint8Array(counts.length + at);
|
|
6013
|
+
out.set(counts);
|
|
6014
|
+
out.set(packed.subarray(0, at), counts.length);
|
|
6015
|
+
return out;
|
|
6016
|
+
}
|
|
6017
|
+
|
|
6018
|
+
// src/image-editor/psd/file.ts
|
|
6019
|
+
var PSD_MAX_DIMENSION = 3e4;
|
|
6020
|
+
var PSB_MAX_DIMENSION = 3e5;
|
|
6021
|
+
var MAX_CHANNELS = 56;
|
|
6022
|
+
var MAX_LAYER_CHANNELS = 64;
|
|
6023
|
+
var COLOR_MODES = {
|
|
6024
|
+
0: "bitmap",
|
|
6025
|
+
1: "grayscale",
|
|
6026
|
+
2: "indexed",
|
|
6027
|
+
3: "rgb",
|
|
6028
|
+
4: "cmyk",
|
|
6029
|
+
7: "multichannel",
|
|
6030
|
+
8: "duotone",
|
|
6031
|
+
9: "lab"
|
|
6032
|
+
};
|
|
6033
|
+
var PSB_LONG_KEYS = /* @__PURE__ */ new Set([
|
|
6034
|
+
"LMsk",
|
|
6035
|
+
"Lr16",
|
|
6036
|
+
"Lr32",
|
|
6037
|
+
"Layr",
|
|
6038
|
+
"Mt16",
|
|
6039
|
+
"Mt32",
|
|
6040
|
+
"Mtrn",
|
|
6041
|
+
"Alph",
|
|
6042
|
+
"FMsk",
|
|
6043
|
+
"lnk2",
|
|
6044
|
+
"FEid",
|
|
6045
|
+
"FXid",
|
|
6046
|
+
"PxSD",
|
|
6047
|
+
"lnk3",
|
|
6048
|
+
"lnkE",
|
|
6049
|
+
"pths",
|
|
6050
|
+
"extd",
|
|
6051
|
+
"extn",
|
|
6052
|
+
"FELS",
|
|
6053
|
+
"cinf",
|
|
6054
|
+
"artd"
|
|
6055
|
+
]);
|
|
6056
|
+
var CHANNEL_ALPHA = -1;
|
|
6057
|
+
var CHANNEL_USER_MASK = -2;
|
|
6058
|
+
var CHANNEL_REAL_USER_MASK = -3;
|
|
6059
|
+
var LAYER_FLAG_TRANSPARENCY_PROTECTED = 1;
|
|
6060
|
+
var LAYER_FLAG_HIDDEN = 2;
|
|
6061
|
+
var MASK_FLAG_DISABLED = 2;
|
|
6062
|
+
var MASK_FLAG_PARAMETERS = 16;
|
|
6063
|
+
var SECTION_OTHER = 0;
|
|
6064
|
+
var SECTION_OPEN = 1;
|
|
6065
|
+
var SECTION_CLOSED = 2;
|
|
6066
|
+
var SECTION_DIVIDER = 3;
|
|
6067
|
+
function readRect(r) {
|
|
6068
|
+
return { top: r.i32(), left: r.i32(), bottom: r.i32(), right: r.i32() };
|
|
6069
|
+
}
|
|
6070
|
+
function rectSize(rect) {
|
|
6071
|
+
const width = rect.right - rect.left;
|
|
6072
|
+
const height = rect.bottom - rect.top;
|
|
6073
|
+
if (width < 0 || height < 0) throw new PsdError("A layer rectangle has a negative size.");
|
|
6074
|
+
if (width > PSB_MAX_DIMENSION || height > PSB_MAX_DIMENSION) throw new PsdError("A layer is larger than 300000 pixels.");
|
|
6075
|
+
return { width, height };
|
|
6076
|
+
}
|
|
6077
|
+
function readHeader(r) {
|
|
6078
|
+
if (r.ascii(4) !== "8BPS") throw new PsdError('Not a PSD file: the signature is not "8BPS".');
|
|
6079
|
+
const version = r.u16();
|
|
6080
|
+
if (version !== 1 && version !== 2) throw new PsdError(`Unsupported PSD version ${version} (1 is PSD, 2 is PSB).`);
|
|
6081
|
+
r.skip(6);
|
|
6082
|
+
const h = { psb: version === 2, channels: r.u16(), height: r.u32(), width: r.u32(), depth: r.u16(), colorMode: r.u16() };
|
|
6083
|
+
if (h.channels < 1 || h.channels > MAX_CHANNELS) throw new PsdError(`Channel count ${h.channels} is outside 1 to ${MAX_CHANNELS}.`);
|
|
6084
|
+
if (h.width < 1 || h.height < 1) throw new PsdError(`Image size ${h.width} \xD7 ${h.height} must be at least 1 \xD7 1.`);
|
|
6085
|
+
const max = h.psb ? PSB_MAX_DIMENSION : PSD_MAX_DIMENSION;
|
|
6086
|
+
if (h.width > max || h.height > max) throw new PsdError(`Image size ${h.width} \xD7 ${h.height} exceeds ${max} pixels.`);
|
|
6087
|
+
if (![1, 8, 16, 32].includes(h.depth)) throw new PsdError(`Unsupported bit depth ${h.depth}.`);
|
|
6088
|
+
return h;
|
|
6089
|
+
}
|
|
6090
|
+
function readResources(r) {
|
|
6091
|
+
const s = r.sub(r.u32());
|
|
6092
|
+
const out = [];
|
|
6093
|
+
while (s.remaining >= 12) {
|
|
6094
|
+
s.ascii(4);
|
|
6095
|
+
const id = s.u16();
|
|
6096
|
+
const name = decodeLegacyName(s.pascal(2));
|
|
6097
|
+
const len = s.u32();
|
|
6098
|
+
const data = s.bytes(len);
|
|
6099
|
+
if (len % 2 && s.remaining) s.skip(1);
|
|
6100
|
+
out.push({ id, name, data });
|
|
6101
|
+
}
|
|
6102
|
+
return out;
|
|
6103
|
+
}
|
|
6104
|
+
var isSig = (r, at = 0) => {
|
|
6105
|
+
const b = r.data.subarray(r.pos + at, r.pos + at + 4);
|
|
6106
|
+
if (b.length < 4) return false;
|
|
6107
|
+
const s = String.fromCharCode(b[0], b[1], b[2], b[3]);
|
|
6108
|
+
return s === "8BIM" || s === "8B64";
|
|
6109
|
+
};
|
|
6110
|
+
function readBlocks(r, psb, alignment) {
|
|
6111
|
+
const out = [];
|
|
6112
|
+
while (r.remaining >= 12 && isSig(r)) {
|
|
6113
|
+
r.skip(4);
|
|
6114
|
+
const key = r.ascii(4);
|
|
6115
|
+
const len = r.len(psb && PSB_LONG_KEYS.has(key));
|
|
6116
|
+
const data = r.bytes(len);
|
|
6117
|
+
let pad = -1;
|
|
6118
|
+
for (let k = 0; k <= 3; k++) {
|
|
6119
|
+
if (k === r.remaining || k < r.remaining && isSig(r, k)) {
|
|
6120
|
+
pad = k;
|
|
6121
|
+
break;
|
|
6122
|
+
}
|
|
6123
|
+
}
|
|
6124
|
+
if (pad < 0) {
|
|
6125
|
+
const def = (alignment - len % alignment) % alignment;
|
|
6126
|
+
pad = r.peek(def).every((b) => b === 0) && r.remaining >= def ? def : 0;
|
|
6127
|
+
}
|
|
6128
|
+
r.skip(pad);
|
|
6129
|
+
out.push({ key, data });
|
|
6130
|
+
}
|
|
6131
|
+
return out;
|
|
6132
|
+
}
|
|
6133
|
+
function maskParameterBytes(pf) {
|
|
6134
|
+
return (pf & 1 ? 1 : 0) + (pf & 2 ? 8 : 0) + (pf & 4 ? 1 : 0) + (pf & 8 ? 8 : 0);
|
|
6135
|
+
}
|
|
6136
|
+
function realBeforeParameters(d) {
|
|
6137
|
+
const fits = (at) => {
|
|
6138
|
+
if (at >= d.length) return false;
|
|
6139
|
+
const end = at + 1 + maskParameterBytes(d[at]);
|
|
6140
|
+
return d.length >= end && d.length <= end + 3;
|
|
6141
|
+
};
|
|
6142
|
+
if (fits(18)) return false;
|
|
6143
|
+
if (!fits(36)) return false;
|
|
6144
|
+
const known = (pf) => (pf & 240) === 0;
|
|
6145
|
+
const bgOk = (at) => at + 1 < d.length && (d[at + 1] === 0 || d[at + 1] === 255);
|
|
6146
|
+
const photoshop = bgOk(18) && known(d[36]);
|
|
6147
|
+
const realAt = 19 + maskParameterBytes(d[18]);
|
|
6148
|
+
const spec = known(d[18]) && d.length >= realAt + 18 && d.length <= realAt + 21 && bgOk(realAt);
|
|
6149
|
+
return photoshop || !spec;
|
|
6150
|
+
}
|
|
6151
|
+
function parseMask(d) {
|
|
6152
|
+
try {
|
|
6153
|
+
const r = new PsdReader(d);
|
|
6154
|
+
const m = { rect: readRect(r), defaultColor: r.u8(), flags: r.u8() };
|
|
6155
|
+
const readReal = () => r.remaining >= 18 ? { flags: r.u8(), background: r.u8(), rect: readRect(r) } : void 0;
|
|
6156
|
+
const params = (m.flags & MASK_FLAG_PARAMETERS) !== 0;
|
|
6157
|
+
const realFirst = params && realBeforeParameters(d);
|
|
6158
|
+
if (realFirst) m.real = readReal();
|
|
6159
|
+
if (params) {
|
|
6160
|
+
const pf = r.u8();
|
|
6161
|
+
if (pf & 1) m.userDensity = r.u8();
|
|
6162
|
+
if (pf & 2) m.userFeather = r.f64();
|
|
6163
|
+
if (pf & 4) m.vectorDensity = r.u8();
|
|
6164
|
+
if (pf & 8) m.vectorFeather = r.f64();
|
|
6165
|
+
}
|
|
6166
|
+
if (!realFirst) m.real = readReal();
|
|
6167
|
+
return m;
|
|
6168
|
+
} catch (e14) {
|
|
6169
|
+
return void 0;
|
|
6170
|
+
}
|
|
6171
|
+
}
|
|
6172
|
+
function readLayerRecord(r, psb) {
|
|
6173
|
+
const rect = readRect(r);
|
|
6174
|
+
const n = r.u16();
|
|
6175
|
+
if (n > MAX_LAYER_CHANNELS) throw new PsdError(`A layer has ${n} channels (at most ${MAX_LAYER_CHANNELS}).`);
|
|
6176
|
+
const channels = [];
|
|
6177
|
+
const lengths = [];
|
|
6178
|
+
for (let i = 0; i < n; i++) {
|
|
6179
|
+
channels.push({ id: r.i16(), compression: null, data: new Uint8Array(0) });
|
|
6180
|
+
lengths.push(r.len(psb));
|
|
6181
|
+
}
|
|
6182
|
+
if (r.ascii(4) !== "8BIM") throw new PsdError('A layer record has no "8BIM" blend-mode signature.');
|
|
6183
|
+
const blendKey = r.ascii(4);
|
|
6184
|
+
const opacity = r.u8();
|
|
6185
|
+
const clipping = r.u8();
|
|
6186
|
+
const flags = r.u8();
|
|
6187
|
+
r.u8();
|
|
6188
|
+
const x = r.sub(r.u32());
|
|
6189
|
+
const maskBytes = x.bytes(x.u32());
|
|
6190
|
+
const mask = maskBytes.length ? parseMask(maskBytes) : void 0;
|
|
6191
|
+
x.skip(x.u32());
|
|
6192
|
+
const legacyName = decodeLegacyName(x.pascal(4));
|
|
6193
|
+
const blocks = readBlocks(x, psb, 2);
|
|
6194
|
+
return { record: { rect, channels, blendKey, opacity, clipping, flags, mask, legacyName, blocks }, lengths };
|
|
6195
|
+
}
|
|
6196
|
+
function readLayerInfo(data, psb) {
|
|
6197
|
+
const r = new PsdReader(data);
|
|
6198
|
+
const count = r.i16();
|
|
6199
|
+
const n = Math.abs(count);
|
|
6200
|
+
r.checkCount(n, 34, "Layer records");
|
|
6201
|
+
const read = [];
|
|
6202
|
+
for (let i = 0; i < n; i++) read.push(readLayerRecord(r, psb));
|
|
6203
|
+
for (const { record, lengths } of read) {
|
|
6204
|
+
record.channels.forEach((ch, i) => {
|
|
6205
|
+
const len = lengths[i];
|
|
6206
|
+
if (len === 0) return;
|
|
6207
|
+
if (len === 1) throw new PsdError("A channel has a data length of 1.");
|
|
6208
|
+
ch.compression = r.u16();
|
|
6209
|
+
ch.data = r.bytes(len - 2);
|
|
6210
|
+
});
|
|
6211
|
+
}
|
|
6212
|
+
return { layers: read.map((x) => x.record), mergedAlpha: count < 0 };
|
|
6213
|
+
}
|
|
6214
|
+
function readPsd(bytes) {
|
|
6215
|
+
const r = new PsdReader(bytes);
|
|
6216
|
+
const header = readHeader(r);
|
|
6217
|
+
const { psb } = header;
|
|
6218
|
+
const colorModeData = r.bytes(r.u32());
|
|
6219
|
+
const resources = readResources(r);
|
|
6220
|
+
const s = r.sub(r.len(psb));
|
|
6221
|
+
let layers = [];
|
|
6222
|
+
let mergedAlpha = false;
|
|
6223
|
+
let globalBlocks = [];
|
|
6224
|
+
if (s.remaining) {
|
|
6225
|
+
const liLen = s.len(psb);
|
|
6226
|
+
if (liLen > 0) ({ layers, mergedAlpha } = readLayerInfo(s.bytes(liLen), psb));
|
|
6227
|
+
if (s.remaining >= 4) {
|
|
6228
|
+
s.skip(s.u32());
|
|
6229
|
+
globalBlocks = readBlocks(s, psb, 4);
|
|
6230
|
+
const key = header.depth === 16 ? "Lr16" : header.depth === 32 ? "Lr32" : null;
|
|
6231
|
+
const block = globalBlocks.find((b) => key ? b.key === key : !layers.length && ["Layr", "Lr16", "Lr32"].includes(b.key));
|
|
6232
|
+
if (block) {
|
|
6233
|
+
({ layers, mergedAlpha } = readLayerInfo(block.data, psb));
|
|
6234
|
+
globalBlocks = globalBlocks.filter((b) => b !== block);
|
|
6235
|
+
}
|
|
6236
|
+
}
|
|
6237
|
+
}
|
|
6238
|
+
const imageCompression = r.remaining >= 2 ? r.u16() : 0;
|
|
6239
|
+
return { header, colorModeData, resources, layers, mergedAlpha, globalBlocks, imageCompression, imageData: r.rest() };
|
|
6240
|
+
}
|
|
6241
|
+
function layerBlock(rec, key) {
|
|
6242
|
+
return _optionalChain([rec, 'access', _98 => _98.blocks, 'access', _99 => _99.find, 'call', _100 => _100((b) => b.key === key), 'optionalAccess', _101 => _101.data]);
|
|
6243
|
+
}
|
|
6244
|
+
function layerName(rec) {
|
|
6245
|
+
const luni = layerBlock(rec, "luni");
|
|
6246
|
+
if (luni) {
|
|
6247
|
+
try {
|
|
6248
|
+
return new PsdReader(luni).unicode();
|
|
6249
|
+
} catch (e15) {
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
return rec.legacyName;
|
|
6253
|
+
}
|
|
6254
|
+
function sectionDivider(rec) {
|
|
6255
|
+
const d = _nullishCoalesce(layerBlock(rec, "lsct"), () => ( layerBlock(rec, "lsdk")));
|
|
6256
|
+
if (!d || d.length < 4) return void 0;
|
|
6257
|
+
const r = new PsdReader(d);
|
|
6258
|
+
const kind = r.u32();
|
|
6259
|
+
if (r.remaining >= 8 && r.ascii(4) === "8BIM") return { kind, blendKey: r.ascii(4) };
|
|
6260
|
+
return { kind };
|
|
6261
|
+
}
|
|
6262
|
+
function u32Block(rec, key) {
|
|
6263
|
+
const d = layerBlock(rec, key);
|
|
6264
|
+
return d && d.length >= 4 ? new PsdReader(d).u32() : void 0;
|
|
6265
|
+
}
|
|
6266
|
+
function u8Block(rec, key) {
|
|
6267
|
+
const d = layerBlock(rec, key);
|
|
6268
|
+
return d && d.length >= 1 ? d[0] : void 0;
|
|
6269
|
+
}
|
|
6270
|
+
function layerTree(file) {
|
|
6271
|
+
const stack = [[]];
|
|
6272
|
+
file.layers.forEach((rec, index) => {
|
|
6273
|
+
const kind = _nullishCoalesce(_optionalChain([sectionDivider, 'call', _102 => _102(rec), 'optionalAccess', _103 => _103.kind]), () => ( SECTION_OTHER));
|
|
6274
|
+
if (kind === SECTION_DIVIDER) {
|
|
6275
|
+
stack.push([]);
|
|
6276
|
+
} else if (kind === SECTION_OPEN || kind === SECTION_CLOSED) {
|
|
6277
|
+
const children = stack.length > 1 ? stack.pop() : [];
|
|
6278
|
+
stack[stack.length - 1].push({ index, children });
|
|
6279
|
+
} else {
|
|
6280
|
+
stack[stack.length - 1].push({ index });
|
|
6281
|
+
}
|
|
6282
|
+
});
|
|
6283
|
+
while (stack.length > 1) {
|
|
6284
|
+
const children = stack.pop();
|
|
6285
|
+
stack[stack.length - 1].push(...children);
|
|
6286
|
+
}
|
|
6287
|
+
return stack[0];
|
|
6288
|
+
}
|
|
6289
|
+
function channelRect(rec, id) {
|
|
6290
|
+
if (id === CHANNEL_USER_MASK && rec.mask) return rec.mask.rect;
|
|
6291
|
+
if (id === CHANNEL_REAL_USER_MASK && rec.mask) return _nullishCoalesce(_optionalChain([rec, 'access', _104 => _104.mask, 'access', _105 => _105.real, 'optionalAccess', _106 => _106.rect]), () => ( rec.mask.rect));
|
|
6292
|
+
return rec.rect;
|
|
6293
|
+
}
|
|
6294
|
+
function decodeLayerChannel(file, rec, id) {
|
|
6295
|
+
const ch = rec.channels.find((c) => c.id === id);
|
|
6296
|
+
if (!ch) return void 0;
|
|
6297
|
+
const { width, height } = rectSize(channelRect(rec, id));
|
|
6298
|
+
if (ch.compression === null) {
|
|
6299
|
+
if (width * height === 0) return new Uint8Array(0);
|
|
6300
|
+
throw new PsdError(`Channel ${id} of layer "${layerName(rec)}" has no data.`);
|
|
6301
|
+
}
|
|
6302
|
+
return decodePlanes(ch.compression, ch.data, { planes: 1, width, height, depth: file.header.depth, psb: file.header.psb });
|
|
6303
|
+
}
|
|
6304
|
+
function decodeMergedImage(file) {
|
|
6305
|
+
const { channels, width, height, depth, psb } = file.header;
|
|
6306
|
+
return decodePlanes(file.imageCompression, file.imageData, { planes: channels, width, height, depth, psb });
|
|
6307
|
+
}
|
|
6308
|
+
function resource(file, id) {
|
|
6309
|
+
return _optionalChain([file, 'access', _107 => _107.resources, 'access', _108 => _108.find, 'call', _109 => _109((r) => r.id === id), 'optionalAccess', _110 => _110.data]);
|
|
6310
|
+
}
|
|
6311
|
+
function resolution(file) {
|
|
6312
|
+
const d = resource(file, 1005);
|
|
6313
|
+
if (!d || d.length < 4) return void 0;
|
|
6314
|
+
return new PsdReader(d).u32() / 65536;
|
|
6315
|
+
}
|
|
6316
|
+
function writeRect(w, r) {
|
|
6317
|
+
w.i32(r.top);
|
|
6318
|
+
w.i32(r.left);
|
|
6319
|
+
w.i32(r.bottom);
|
|
6320
|
+
w.i32(r.right);
|
|
6321
|
+
}
|
|
6322
|
+
function writeBlocks(w, blocks, psb, alignment) {
|
|
6323
|
+
for (const b of blocks) {
|
|
6324
|
+
const long2 = psb && PSB_LONG_KEYS.has(b.key);
|
|
6325
|
+
w.ascii(long2 ? "8B64" : "8BIM");
|
|
6326
|
+
w.ascii(b.key);
|
|
6327
|
+
const pad = (alignment - b.data.length % alignment) % alignment;
|
|
6328
|
+
if (long2) w.u64(b.data.length + pad);
|
|
6329
|
+
else w.u32(b.data.length + pad);
|
|
6330
|
+
w.bytes(b.data);
|
|
6331
|
+
w.zeros(pad);
|
|
6332
|
+
}
|
|
6333
|
+
}
|
|
6334
|
+
function writeMask(w, m) {
|
|
6335
|
+
writeRect(w, m.rect);
|
|
6336
|
+
w.u8(m.defaultColor);
|
|
6337
|
+
const pf = (m.userDensity !== void 0 ? 1 : 0) | (m.userFeather !== void 0 ? 2 : 0);
|
|
6338
|
+
w.u8(pf ? m.flags | MASK_FLAG_PARAMETERS : m.flags & ~MASK_FLAG_PARAMETERS);
|
|
6339
|
+
if (pf) {
|
|
6340
|
+
w.u8(pf);
|
|
6341
|
+
if (m.userDensity !== void 0) w.u8(m.userDensity);
|
|
6342
|
+
if (m.userFeather !== void 0) w.f64(m.userFeather);
|
|
6343
|
+
}
|
|
6344
|
+
const len = 18 + (pf ? 1 + maskParameterBytes(pf) : 0);
|
|
6345
|
+
w.zeros(Math.max(0, 20 - len) + (4 - Math.max(20, len) % 4) % 4);
|
|
6346
|
+
}
|
|
6347
|
+
function writeLayerRecord(w, rec, psb, nameBytes) {
|
|
6348
|
+
writeRect(w, rec.rect);
|
|
6349
|
+
w.u16(rec.channels.length);
|
|
6350
|
+
for (const c of rec.channels) {
|
|
6351
|
+
w.i16(c.id);
|
|
6352
|
+
const len = c.compression === null ? 0 : 2 + c.data.length;
|
|
6353
|
+
if (psb) w.u64(len);
|
|
6354
|
+
else w.u32(len);
|
|
6355
|
+
}
|
|
6356
|
+
if (rec.blendKey.length !== 4) throw new PsdError(`Blend key "${rec.blendKey}" must be 4 characters.`);
|
|
6357
|
+
w.ascii("8BIM");
|
|
6358
|
+
w.ascii(rec.blendKey);
|
|
6359
|
+
w.u8(rec.opacity);
|
|
6360
|
+
w.u8(rec.clipping);
|
|
6361
|
+
w.u8(rec.flags);
|
|
6362
|
+
w.u8(0);
|
|
6363
|
+
const extra = w.beginLen(false);
|
|
6364
|
+
const mask = w.beginLen(false);
|
|
6365
|
+
if (rec.mask) writeMask(w, rec.mask);
|
|
6366
|
+
w.endLen(mask);
|
|
6367
|
+
w.u32(40);
|
|
6368
|
+
for (let i = 0; i < 5; i++) w.bytes([0, 0, 255, 255, 0, 0, 255, 255]);
|
|
6369
|
+
w.pascal(nameBytes, 4);
|
|
6370
|
+
writeBlocks(w, rec.blocks, psb, 2);
|
|
6371
|
+
w.endLen(extra);
|
|
6372
|
+
}
|
|
6373
|
+
function writePsd(file, encodeName) {
|
|
6374
|
+
const { header } = file;
|
|
6375
|
+
const { psb } = header;
|
|
6376
|
+
const w = new PsdWriter();
|
|
6377
|
+
w.ascii("8BPS");
|
|
6378
|
+
w.u16(psb ? 2 : 1);
|
|
6379
|
+
w.zeros(6);
|
|
6380
|
+
w.u16(header.channels);
|
|
6381
|
+
w.u32(header.height);
|
|
6382
|
+
w.u32(header.width);
|
|
6383
|
+
w.u16(header.depth);
|
|
6384
|
+
w.u16(header.colorMode);
|
|
6385
|
+
w.u32(file.colorModeData.length);
|
|
6386
|
+
w.bytes(file.colorModeData);
|
|
6387
|
+
const res = w.beginLen(false);
|
|
6388
|
+
for (const r of file.resources) {
|
|
6389
|
+
w.ascii("8BIM");
|
|
6390
|
+
w.u16(r.id);
|
|
6391
|
+
w.pascal(encodeName(r.name), 2);
|
|
6392
|
+
w.u32(r.data.length);
|
|
6393
|
+
w.bytes(r.data);
|
|
6394
|
+
if (r.data.length % 2) w.u8(0);
|
|
6395
|
+
}
|
|
6396
|
+
w.endLen(res);
|
|
6397
|
+
const lm = w.beginLen(psb);
|
|
6398
|
+
if (file.layers.length || file.globalBlocks.length) {
|
|
6399
|
+
const li = w.beginLen(psb);
|
|
6400
|
+
if (file.layers.length) {
|
|
6401
|
+
const start = w.length;
|
|
6402
|
+
w.i16(file.mergedAlpha ? -file.layers.length : file.layers.length);
|
|
6403
|
+
for (const rec of file.layers) writeLayerRecord(w, rec, psb, encodeName(rec.legacyName));
|
|
6404
|
+
for (const rec of file.layers) {
|
|
6405
|
+
for (const c of rec.channels) {
|
|
6406
|
+
if (c.compression === null) continue;
|
|
6407
|
+
w.u16(c.compression);
|
|
6408
|
+
w.bytes(c.data);
|
|
6409
|
+
}
|
|
6410
|
+
}
|
|
6411
|
+
if ((w.length - start) % 2) w.u8(0);
|
|
6412
|
+
}
|
|
6413
|
+
w.endLen(li);
|
|
6414
|
+
w.u32(0);
|
|
6415
|
+
writeBlocks(w, file.globalBlocks, psb, 4);
|
|
6416
|
+
}
|
|
6417
|
+
w.endLen(lm);
|
|
6418
|
+
w.u16(file.imageCompression);
|
|
6419
|
+
w.bytes(file.imageData);
|
|
6420
|
+
return w.result();
|
|
6421
|
+
}
|
|
6422
|
+
|
|
6423
|
+
// src/image-editor/psd/pixels.ts
|
|
6424
|
+
var MODE_INDEXED = 2;
|
|
6425
|
+
var MODE_RGB = 3;
|
|
6426
|
+
var MODE_CMYK = 4;
|
|
6427
|
+
var MODE_MULTICHANNEL = 7;
|
|
6428
|
+
var MODE_LAB = 9;
|
|
6429
|
+
function colorChannelCount(mode, headerChannels) {
|
|
6430
|
+
switch (mode) {
|
|
6431
|
+
case MODE_RGB:
|
|
6432
|
+
case MODE_LAB:
|
|
6433
|
+
return 3;
|
|
6434
|
+
case MODE_CMYK:
|
|
6435
|
+
return 4;
|
|
6436
|
+
case MODE_MULTICHANNEL:
|
|
6437
|
+
return Math.min(3, headerChannels);
|
|
6438
|
+
default:
|
|
6439
|
+
return 1;
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
var clamp012 = (v) => v < 0 ? 0 : v > 1 ? 1 : v;
|
|
6443
|
+
function sampler(plane, depth, width, encode, fill) {
|
|
6444
|
+
if (!plane) return () => fill;
|
|
6445
|
+
switch (depth) {
|
|
6446
|
+
case 8:
|
|
6447
|
+
return (i) => plane[i] / 255;
|
|
6448
|
+
case 16:
|
|
6449
|
+
return (i) => (plane[2 * i] << 8 | plane[2 * i + 1]) / 65535;
|
|
6450
|
+
case 32: {
|
|
6451
|
+
const view = new DataView(plane.buffer, plane.byteOffset, plane.byteLength);
|
|
6452
|
+
return (i) => {
|
|
6453
|
+
const v = clamp012(view.getFloat32(4 * i, false) || 0);
|
|
6454
|
+
return encode ? linearToSrgb(v) : v;
|
|
6455
|
+
};
|
|
6456
|
+
}
|
|
6457
|
+
case 1: {
|
|
6458
|
+
const rb = Math.ceil(width / 8);
|
|
6459
|
+
return (i) => {
|
|
6460
|
+
const x = i % width;
|
|
6461
|
+
const y = (i - x) / width;
|
|
6462
|
+
return plane[y * rb + (x >> 3)] >> 7 - (x & 7) & 1 ? 0 : 1;
|
|
6463
|
+
};
|
|
6464
|
+
}
|
|
6465
|
+
default:
|
|
6466
|
+
throw new PsdError(`Unsupported bit depth ${depth}.`);
|
|
6467
|
+
}
|
|
6468
|
+
}
|
|
6469
|
+
function labToSrgb(l, a, b) {
|
|
6470
|
+
const fy = (l + 16) / 116;
|
|
6471
|
+
const f = (t) => t > 6 / 29 ? t ** 3 : 3 * (6 / 29) ** 2 * (t - 4 / 29);
|
|
6472
|
+
const x = f(fy + a / 500) * D50[0];
|
|
6473
|
+
const y = f(fy) * D50[1];
|
|
6474
|
+
const z = f(fy - b / 200) * D50[2];
|
|
6475
|
+
const m = XYZ_D50_TO_SRGB;
|
|
6476
|
+
return [
|
|
6477
|
+
linearToSrgb(clamp012(m[0][0] * x + m[0][1] * y + m[0][2] * z)),
|
|
6478
|
+
linearToSrgb(clamp012(m[1][0] * x + m[1][1] * y + m[1][2] * z)),
|
|
6479
|
+
linearToSrgb(clamp012(m[2][0] * x + m[2][1] * y + m[2][2] * z))
|
|
6480
|
+
];
|
|
6481
|
+
}
|
|
6482
|
+
function toRgba8(set) {
|
|
6483
|
+
const { width, height, depth, mode } = set;
|
|
6484
|
+
const n = width * height;
|
|
6485
|
+
const out = new Uint8ClampedArray(n * 4);
|
|
6486
|
+
const linear = depth === 32;
|
|
6487
|
+
const isLab = mode === MODE_LAB;
|
|
6488
|
+
const cmyk = mode === MODE_CMYK;
|
|
6489
|
+
const planes = set.color.map((p) => sampler(p, depth, width, linear && !isLab && !cmyk, cmyk ? 1 : 0));
|
|
6490
|
+
const alpha = sampler(set.alpha, depth, width, false, 1);
|
|
6491
|
+
const fast8 = depth === 8 && mode === MODE_RGB && set.color.every(Boolean);
|
|
6492
|
+
if (fast8) {
|
|
6493
|
+
const [r, g, b] = set.color;
|
|
6494
|
+
const a = set.alpha;
|
|
6495
|
+
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
6496
|
+
out[o] = r[i];
|
|
6497
|
+
out[o + 1] = g[i];
|
|
6498
|
+
out[o + 2] = b[i];
|
|
6499
|
+
out[o + 3] = a ? a[i] : 255;
|
|
6500
|
+
}
|
|
6501
|
+
return out;
|
|
6502
|
+
}
|
|
6503
|
+
const palette = set.palette;
|
|
6504
|
+
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
6505
|
+
let r;
|
|
6506
|
+
let g;
|
|
6507
|
+
let b;
|
|
6508
|
+
switch (mode) {
|
|
6509
|
+
case MODE_RGB:
|
|
6510
|
+
case MODE_MULTICHANNEL:
|
|
6511
|
+
r = planes[0](i);
|
|
6512
|
+
g = planes[1] ? planes[1](i) : r;
|
|
6513
|
+
b = planes[2] ? planes[2](i) : r;
|
|
6514
|
+
break;
|
|
6515
|
+
case MODE_CMYK: {
|
|
6516
|
+
const k = planes[3] ? planes[3](i) : 1;
|
|
6517
|
+
r = planes[0](i) * k;
|
|
6518
|
+
g = planes[1](i) * k;
|
|
6519
|
+
b = planes[2](i) * k;
|
|
6520
|
+
break;
|
|
6521
|
+
}
|
|
6522
|
+
case MODE_LAB:
|
|
6523
|
+
[r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128);
|
|
6524
|
+
break;
|
|
6525
|
+
case MODE_INDEXED: {
|
|
6526
|
+
const idx = Math.round(planes[0](i) * 255);
|
|
6527
|
+
if (palette && palette.length >= 768) {
|
|
6528
|
+
out[o] = palette[idx];
|
|
6529
|
+
out[o + 1] = palette[256 + idx];
|
|
6530
|
+
out[o + 2] = palette[512 + idx];
|
|
6531
|
+
out[o + 3] = Math.round(alpha(i) * 255);
|
|
6532
|
+
continue;
|
|
6533
|
+
}
|
|
6534
|
+
r = g = b = idx / 255;
|
|
6535
|
+
break;
|
|
6536
|
+
}
|
|
6537
|
+
default:
|
|
6538
|
+
r = g = b = planes[0](i);
|
|
6539
|
+
}
|
|
6540
|
+
out[o] = Math.round(r * 255);
|
|
6541
|
+
out[o + 1] = Math.round(g * 255);
|
|
6542
|
+
out[o + 2] = Math.round(b * 255);
|
|
6543
|
+
out[o + 3] = Math.round(alpha(i) * 255);
|
|
6544
|
+
}
|
|
6545
|
+
return out;
|
|
6546
|
+
}
|
|
6547
|
+
function toMask8(plane, width, height, depth) {
|
|
6548
|
+
if (depth === 8) return new Uint8ClampedArray(plane.buffer, plane.byteOffset, width * height);
|
|
6549
|
+
const s = sampler(plane, depth, width, false, 0);
|
|
6550
|
+
const out = new Uint8ClampedArray(width * height);
|
|
6551
|
+
for (let i = 0; i < out.length; i++) out[i] = Math.round(s(i) * 255);
|
|
6552
|
+
return out;
|
|
6553
|
+
}
|
|
6554
|
+
function rgbaToPlanes(data, n) {
|
|
6555
|
+
const planes = [new Uint8Array(n), new Uint8Array(n), new Uint8Array(n), new Uint8Array(n)];
|
|
6556
|
+
for (let i = 0, o = 0; i < n; i++, o += 4) {
|
|
6557
|
+
planes[0][i] = data[o];
|
|
6558
|
+
planes[1][i] = data[o + 1];
|
|
6559
|
+
planes[2][i] = data[o + 2];
|
|
6560
|
+
planes[3][i] = data[o + 3];
|
|
6561
|
+
}
|
|
6562
|
+
return planes;
|
|
6563
|
+
}
|
|
6564
|
+
function unmatteWhite(data) {
|
|
6565
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
6566
|
+
const a = data[i + 3];
|
|
6567
|
+
if (a === 255 || a === 0) continue;
|
|
6568
|
+
const k = 255 - a;
|
|
6569
|
+
for (let c = 0; c < 3; c++) data[i + c] = Math.round((data[i + c] - k) * 255 / a);
|
|
6570
|
+
}
|
|
6571
|
+
}
|
|
6572
|
+
function matteWhite(data) {
|
|
6573
|
+
const out = Uint8ClampedArray.from(data);
|
|
6574
|
+
for (let i = 0; i < out.length; i += 4) {
|
|
6575
|
+
const a = out[i + 3];
|
|
6576
|
+
if (a === 255) continue;
|
|
6577
|
+
for (let c = 0; c < 3; c++) out[i + c] = Math.round((out[i + c] * a + 255 * (255 - a)) / 255);
|
|
6578
|
+
}
|
|
6579
|
+
return out;
|
|
6580
|
+
}
|
|
6581
|
+
|
|
6582
|
+
// src/image-editor/psd/import.ts
|
|
6583
|
+
var PSD_BLEND_KEYS = {
|
|
6584
|
+
pass: "pass-through",
|
|
6585
|
+
norm: "normal",
|
|
6586
|
+
dark: "darken",
|
|
6587
|
+
"mul ": "multiply",
|
|
6588
|
+
idiv: "color-burn",
|
|
6589
|
+
lbrn: "linear-burn",
|
|
6590
|
+
dkCl: "darker-color",
|
|
6591
|
+
lite: "lighten",
|
|
6592
|
+
scrn: "screen",
|
|
6593
|
+
"div ": "color-dodge",
|
|
6594
|
+
lddg: "linear-dodge",
|
|
6595
|
+
lgCl: "lighter-color",
|
|
6596
|
+
over: "overlay",
|
|
6597
|
+
sLit: "soft-light",
|
|
6598
|
+
hLit: "hard-light",
|
|
6599
|
+
vLit: "vivid-light",
|
|
6600
|
+
lLit: "linear-light",
|
|
6601
|
+
pLit: "pin-light",
|
|
6602
|
+
hMix: "hard-mix",
|
|
6603
|
+
diff: "difference",
|
|
6604
|
+
smud: "exclusion",
|
|
6605
|
+
fsub: "subtract",
|
|
6606
|
+
fdiv: "divide",
|
|
6607
|
+
"hue ": "hue",
|
|
6608
|
+
"sat ": "saturation",
|
|
6609
|
+
colr: "color",
|
|
6610
|
+
"lum ": "luminosity"
|
|
6611
|
+
};
|
|
6612
|
+
var BLEND_TO_PSD = Object.fromEntries(
|
|
6613
|
+
Object.entries(PSD_BLEND_KEYS).map(([k, v]) => [v, k])
|
|
6614
|
+
);
|
|
6615
|
+
var FILL_KEYS = ["SoCo", "GdFl", "PtFl"];
|
|
6616
|
+
var TYPE_KEYS = ["TySh", "tySh"];
|
|
6617
|
+
var SMART_KEYS = ["SoLd", "SoLE", "PlLd"];
|
|
6618
|
+
var VECTOR_KEYS = ["vmsk", "vsms"];
|
|
6619
|
+
var EFFECT_KEYS = ["lfx2", "lfxs", "lmfx"];
|
|
6620
|
+
var percent = (v) => Math.round(v / 255 * 100) / 100;
|
|
6621
|
+
var Warnings = (_class5 = class {constructor() { _class5.prototype.__init26.call(this);_class5.prototype.__init27.call(this); }
|
|
6622
|
+
__init26() {this.groups = /* @__PURE__ */ new Map()}
|
|
6623
|
+
__init27() {this.extra = []}
|
|
6624
|
+
add(message, layer) {
|
|
6625
|
+
const list = _nullishCoalesce(this.groups.get(message), () => ( []));
|
|
6626
|
+
if (!list.includes(layer)) list.push(layer);
|
|
6627
|
+
this.groups.set(message, list);
|
|
6628
|
+
}
|
|
6629
|
+
list() {
|
|
6630
|
+
const out = [...this.extra];
|
|
6631
|
+
for (const [message, layers] of this.groups) {
|
|
6632
|
+
const names = layers.map((n) => `"${n}"`);
|
|
6633
|
+
const shown = names.length > 6 ? `${names.slice(0, 6).join(", ")} and ${names.length - 6} more` : names.join(", ");
|
|
6634
|
+
out.push(`${message} (${layers.length === 1 ? "layer" : "layers"} ${shown}).`);
|
|
6635
|
+
}
|
|
6636
|
+
return out;
|
|
6637
|
+
}
|
|
6638
|
+
}, _class5);
|
|
6639
|
+
function psdKind(rec) {
|
|
6640
|
+
if (rec.blocks.some((b) => TYPE_KEYS.includes(b.key))) return "type";
|
|
6641
|
+
if (rec.blocks.some((b) => SMART_KEYS.includes(b.key))) return "smart-object";
|
|
6642
|
+
const fill = rec.blocks.some((b) => FILL_KEYS.includes(b.key));
|
|
6643
|
+
const vector = rec.blocks.some((b) => VECTOR_KEYS.includes(b.key) || b.key === "vstk");
|
|
6644
|
+
if (fill && vector) return "shape";
|
|
6645
|
+
if (fill) return "fill";
|
|
6646
|
+
const adj = rec.blocks.find((b) => ADJUSTMENT_KEYS.includes(b.key));
|
|
6647
|
+
if (adj) return adjustmentLabel(adj.key);
|
|
6648
|
+
return "pixel";
|
|
6649
|
+
}
|
|
6650
|
+
function locksOf(rec) {
|
|
6651
|
+
const v = u32Block(rec, "lspf");
|
|
6652
|
+
if (!v) return void 0;
|
|
6653
|
+
const locks = {};
|
|
6654
|
+
if (v & 2147483648) locks.all = true;
|
|
6655
|
+
if (v & 1) locks.transparency = true;
|
|
6656
|
+
if (v & 2) locks.pixels = true;
|
|
6657
|
+
if (v & 4) locks.position = true;
|
|
6658
|
+
return Object.keys(locks).length ? locks : void 0;
|
|
6659
|
+
}
|
|
6660
|
+
function decodeOr(ctx, rec, id, name) {
|
|
6661
|
+
try {
|
|
6662
|
+
return decodeLayerChannel(ctx.file, rec, id);
|
|
6663
|
+
} catch (e) {
|
|
6664
|
+
ctx.warn.add(`A channel could not be decoded (${e instanceof Error ? e.message : String(e)}) and the layer is treated as empty`, name);
|
|
6665
|
+
return void 0;
|
|
6666
|
+
}
|
|
6667
|
+
}
|
|
6668
|
+
function safeSize(ctx, rect, name) {
|
|
6669
|
+
try {
|
|
6670
|
+
return rectSize(rect);
|
|
6671
|
+
} catch (e) {
|
|
6672
|
+
ctx.warn.add(`A malformed rectangle (${e instanceof Error ? e.message : String(e)}) left the layer or its mask empty`, name);
|
|
6673
|
+
return { width: 0, height: 0 };
|
|
6674
|
+
}
|
|
6675
|
+
}
|
|
6676
|
+
function recordPixels(ctx, rec, name) {
|
|
6677
|
+
const { width, height } = safeSize(ctx, rec.rect, name);
|
|
6678
|
+
if (!width || !height || ctx.skipPixels) return _chunkZOOEX3WTcjs.emptySurface.call(void 0, 4);
|
|
6679
|
+
const ids = [...Array.from({ length: ctx.colorCount }, (_, i) => i), CHANNEL_ALPHA];
|
|
6680
|
+
const planes = ids.map((id) => rec.channels.some((c) => c.id === id) ? _nullishCoalesce(decodeOr(ctx, rec, id, name), () => ( null)) : void 0);
|
|
6681
|
+
if (planes.some((p) => p === null)) return _chunkZOOEX3WTcjs.emptySurface.call(void 0, 4);
|
|
6682
|
+
if (planes.every((p) => p === void 0)) return _chunkZOOEX3WTcjs.emptySurface.call(void 0, 4);
|
|
6683
|
+
const data = toRgba8({
|
|
6684
|
+
width,
|
|
6685
|
+
height,
|
|
6686
|
+
depth: ctx.file.header.depth,
|
|
6687
|
+
mode: ctx.file.header.colorMode,
|
|
6688
|
+
color: planes.slice(0, ctx.colorCount),
|
|
6689
|
+
alpha: planes[ctx.colorCount],
|
|
6690
|
+
palette: ctx.palette
|
|
6691
|
+
});
|
|
6692
|
+
return _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data }, 4, rec.rect.left, rec.rect.top);
|
|
6693
|
+
}
|
|
6694
|
+
function recordMask(ctx, rec, name) {
|
|
6695
|
+
const m = rec.mask;
|
|
6696
|
+
if (!m) return void 0;
|
|
6697
|
+
const useReal = rec.channels.some((c) => c.id === CHANNEL_REAL_USER_MASK) && m.real;
|
|
6698
|
+
const id = useReal ? CHANNEL_REAL_USER_MASK : CHANNEL_USER_MASK;
|
|
6699
|
+
if (!rec.channels.some((c) => c.id === id)) return void 0;
|
|
6700
|
+
const rect = useReal ? m.real.rect : m.rect;
|
|
6701
|
+
const def = (useReal ? m.real.background : m.defaultColor) >= 128 ? 255 : 0;
|
|
6702
|
+
const flags = useReal ? m.real.flags : m.flags;
|
|
6703
|
+
let surface = _chunkZOOEX3WTcjs.emptySurface.call(void 0, 1, def);
|
|
6704
|
+
const { width, height } = safeSize(ctx, rect, name);
|
|
6705
|
+
if (width && height && !ctx.skipPixels) {
|
|
6706
|
+
const plane = decodeOr(ctx, rec, id, name);
|
|
6707
|
+
if (plane) surface = _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data: toMask8(plane, width, height, ctx.file.header.depth) }, 1, rect.left, rect.top, def);
|
|
6708
|
+
}
|
|
6709
|
+
const mask = { surface, defaultValue: def };
|
|
6710
|
+
if (m.userDensity !== void 0 && m.userDensity < 255) mask.density = percent(m.userDensity);
|
|
6711
|
+
if (m.userFeather !== void 0 && m.userFeather > 0) mask.feather = Math.min(1e3, m.userFeather);
|
|
6712
|
+
if (flags & MASK_FLAG_DISABLED) mask.enabled = false;
|
|
6713
|
+
return mask;
|
|
6714
|
+
}
|
|
6715
|
+
function baseProps(ctx, rec, name, notes) {
|
|
6716
|
+
let blend = PSD_BLEND_KEYS[rec.blendKey];
|
|
6717
|
+
if (rec.blendKey === "diss") {
|
|
6718
|
+
ctx.warn.add("Dissolve is not supported and became Normal", name);
|
|
6719
|
+
notes.push("Dissolve became Normal");
|
|
6720
|
+
} else if (!blend) {
|
|
6721
|
+
ctx.warn.add(`An unknown blend mode became Normal`, name);
|
|
6722
|
+
notes.push(`unknown blend mode "${rec.blendKey}"`);
|
|
6723
|
+
}
|
|
6724
|
+
if (!blend || blend === "pass-through") blend = "normal";
|
|
6725
|
+
const props = {
|
|
6726
|
+
name,
|
|
6727
|
+
visible: (rec.flags & LAYER_FLAG_HIDDEN) === 0,
|
|
6728
|
+
opacity: percent(rec.opacity),
|
|
6729
|
+
blend
|
|
6730
|
+
};
|
|
6731
|
+
if (rec.clipping) props.clipped = true;
|
|
6732
|
+
const locks = locksOf(rec);
|
|
6733
|
+
if (locks) props.locks = locks;
|
|
6734
|
+
if (rec.blocks.some((b) => EFFECT_KEYS.includes(b.key))) {
|
|
6735
|
+
ctx.warn.add("Layer effects (lfx2) are not rendered", name);
|
|
6736
|
+
notes.push("layer effects are not rendered");
|
|
6737
|
+
}
|
|
6738
|
+
if (rec.blocks.some((b) => b.key === "artb" || b.key === "artd" || b.key === "abdd")) {
|
|
6739
|
+
ctx.warn.add("Artboards are not supported; they came in as plain groups, without their background colour and clipping", name);
|
|
6740
|
+
notes.push("artboard imported as a group");
|
|
6741
|
+
}
|
|
6742
|
+
if (rec.blocks.some((b) => VECTOR_KEYS.includes(b.key)) && psdKind(rec) === "pixel") {
|
|
6743
|
+
ctx.warn.add("Vector masks are not supported and were ignored", name);
|
|
6744
|
+
notes.push("vector mask ignored");
|
|
6745
|
+
}
|
|
6746
|
+
return props;
|
|
6747
|
+
}
|
|
6748
|
+
function importNode(ctx, node, depth) {
|
|
6749
|
+
const rec = ctx.file.layers[node.index];
|
|
6750
|
+
const name = layerName(rec);
|
|
6751
|
+
const notes = [];
|
|
6752
|
+
const kind = psdKind(rec);
|
|
6753
|
+
const entry = { name, type: null, status: "mapped", psdKind: node.children ? "group" : kind, notes, depth };
|
|
6754
|
+
ctx.summary.push(entry);
|
|
6755
|
+
if (node.children) {
|
|
6756
|
+
const props2 = baseProps(ctx, rec, name, notes);
|
|
6757
|
+
const divider = sectionDivider(rec);
|
|
6758
|
+
const key = _nullishCoalesce(_optionalChain([divider, 'optionalAccess', _111 => _111.blendKey]), () => ( rec.blendKey));
|
|
6759
|
+
const groupBlend = key === "pass" ? "pass-through" : _nullishCoalesce(PSD_BLEND_KEYS[key], () => ( "normal"));
|
|
6760
|
+
const children = [];
|
|
6761
|
+
for (const child of node.children) {
|
|
6762
|
+
const layer2 = importNode(ctx, child, depth + 1);
|
|
6763
|
+
if (layer2) children.push(layer2);
|
|
6764
|
+
}
|
|
6765
|
+
const group = { type: "group", id: ctx.newId(name), ...props2, blend: groupBlend, children };
|
|
6766
|
+
if (_optionalChain([divider, 'optionalAccess', _112 => _112.kind]) === SECTION_CLOSED) group.collapsed = true;
|
|
6767
|
+
const mask2 = recordMask(ctx, rec, name);
|
|
6768
|
+
if (mask2) group.mask = mask2;
|
|
6769
|
+
entry.type = "group";
|
|
6770
|
+
entry.id = group.id;
|
|
6771
|
+
entry.status = notes.length ? "approximated" : "mapped";
|
|
6772
|
+
return group;
|
|
6773
|
+
}
|
|
6774
|
+
const adjBlock = rec.blocks.find((b) => ADJUSTMENT_KEYS.includes(b.key));
|
|
6775
|
+
if (adjBlock) {
|
|
6776
|
+
const parsed = parseAdjustmentBlock(adjBlock.key, adjBlock.data);
|
|
6777
|
+
if (!parsed) {
|
|
6778
|
+
const label = adjustmentLabel(adjBlock.key);
|
|
6779
|
+
ctx.warn.add(`${label} adjustment layers are not supported and were left out`, name);
|
|
6780
|
+
notes.push(`${label} is not supported`);
|
|
6781
|
+
entry.status = "dropped";
|
|
6782
|
+
return null;
|
|
6783
|
+
}
|
|
6784
|
+
const props2 = baseProps(ctx, rec, name, notes);
|
|
6785
|
+
if (parsed.approximated) {
|
|
6786
|
+
ctx.warn.add(`A ${adjustmentLabel(adjBlock.key)} layer was approximated: ${parsed.approximated}`, name);
|
|
6787
|
+
notes.push(parsed.approximated);
|
|
6788
|
+
}
|
|
6789
|
+
const layer2 = { type: "adjustment", id: ctx.newId(name), ...props2, kind: parsed.kind, params: parsed.params };
|
|
6790
|
+
const mask2 = recordMask(ctx, rec, name);
|
|
6791
|
+
if (mask2) layer2.mask = mask2;
|
|
6792
|
+
entry.type = "adjustment";
|
|
6793
|
+
entry.id = layer2.id;
|
|
6794
|
+
entry.status = notes.length ? "approximated" : "mapped";
|
|
6795
|
+
return layer2;
|
|
6796
|
+
}
|
|
6797
|
+
const props = baseProps(ctx, rec, name, notes);
|
|
6798
|
+
if (kind !== "pixel") {
|
|
6799
|
+
const what = kind === "smart-object" ? "Smart objects" : kind === "type" ? "Type layers" : kind === "shape" ? "Shape layers" : "Fill layers";
|
|
6800
|
+
ctx.warn.add(`${what} came in as pixel layers (their stored pixels)`, name);
|
|
6801
|
+
notes.push(`${kind} layer imported as pixels`);
|
|
6802
|
+
}
|
|
6803
|
+
const layer = { type: "pixel", id: ctx.newId(name), ...props, surface: recordPixels(ctx, rec, name), offset: { x: 0, y: 0 } };
|
|
6804
|
+
const fill = u8Block(rec, "iOpa");
|
|
6805
|
+
if (fill !== void 0 && fill < 255) layer.fillOpacity = percent(fill);
|
|
6806
|
+
const mask = recordMask(ctx, rec, name);
|
|
6807
|
+
if (mask) layer.mask = mask;
|
|
6808
|
+
entry.type = "pixel";
|
|
6809
|
+
entry.id = layer.id;
|
|
6810
|
+
entry.status = notes.length ? "approximated" : "mapped";
|
|
6811
|
+
return layer;
|
|
6812
|
+
}
|
|
6813
|
+
function mergedLayer(ctx) {
|
|
6814
|
+
const { header } = ctx.file;
|
|
6815
|
+
const { width, height } = header;
|
|
6816
|
+
let planes;
|
|
6817
|
+
try {
|
|
6818
|
+
planes = decodeMergedImage(ctx.file);
|
|
6819
|
+
} catch (e) {
|
|
6820
|
+
ctx.warn.extra.push(`The merged image could not be decoded (${e instanceof Error ? e.message : String(e)}).`);
|
|
6821
|
+
return null;
|
|
6822
|
+
}
|
|
6823
|
+
const size = rowBytes(width, header.depth) * height;
|
|
6824
|
+
const plane = (i) => i < header.channels ? planes.subarray(i * size, (i + 1) * size) : void 0;
|
|
6825
|
+
const cc = ctx.colorCount;
|
|
6826
|
+
const hasAlpha = header.channels > cc && (ctx.file.layers.length === 0 || ctx.file.mergedAlpha);
|
|
6827
|
+
const data = toRgba8({
|
|
6828
|
+
width,
|
|
6829
|
+
height,
|
|
6830
|
+
depth: header.depth,
|
|
6831
|
+
mode: header.colorMode,
|
|
6832
|
+
color: Array.from({ length: cc }, (_, i) => plane(i)),
|
|
6833
|
+
alpha: hasAlpha ? plane(cc) : void 0,
|
|
6834
|
+
palette: ctx.palette
|
|
6835
|
+
});
|
|
6836
|
+
if (hasAlpha) unmatteWhite(data);
|
|
6837
|
+
return {
|
|
6838
|
+
type: "pixel",
|
|
6839
|
+
id: ctx.newId("Background"),
|
|
6840
|
+
name: "Background",
|
|
6841
|
+
visible: true,
|
|
6842
|
+
opacity: 1,
|
|
6843
|
+
blend: "normal",
|
|
6844
|
+
surface: _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data }, 4),
|
|
6845
|
+
offset: { x: 0, y: 0 }
|
|
6846
|
+
};
|
|
6847
|
+
}
|
|
6848
|
+
function psdToLayers(file, options = {}) {
|
|
6849
|
+
const { header } = file;
|
|
6850
|
+
const warn = new Warnings();
|
|
6851
|
+
let n = 0;
|
|
6852
|
+
const ctx = {
|
|
6853
|
+
file,
|
|
6854
|
+
warn,
|
|
6855
|
+
newId: _nullishCoalesce(options.newId, () => ( (() => `psd-${++n}`))),
|
|
6856
|
+
skipPixels: _nullishCoalesce(options.skipPixels, () => ( false)),
|
|
6857
|
+
summary: [],
|
|
6858
|
+
colorCount: colorChannelCount(header.colorMode, header.channels),
|
|
6859
|
+
palette: header.colorMode === MODE_INDEXED ? file.colorModeData : void 0
|
|
6860
|
+
};
|
|
6861
|
+
const mode = _nullishCoalesce(COLOR_MODES[header.colorMode], () => ( `mode ${header.colorMode}`));
|
|
6862
|
+
if (mode !== "rgb" || header.depth !== 8) {
|
|
6863
|
+
warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to 8-bit RGB.`);
|
|
6864
|
+
}
|
|
6865
|
+
if (resource(file, 1039)) warn.extra.push("The embedded ICC profile is ignored; colours are read as sRGB.");
|
|
6866
|
+
let layers = [];
|
|
6867
|
+
if (file.layers.length) {
|
|
6868
|
+
const tree = layerTree(file);
|
|
6869
|
+
const built = [];
|
|
6870
|
+
for (const node of tree) {
|
|
6871
|
+
const layer = importNode(ctx, node, 0);
|
|
6872
|
+
if (layer) built.push(layer);
|
|
6873
|
+
}
|
|
6874
|
+
layers = built;
|
|
6875
|
+
if (!layers.length && !ctx.skipPixels) {
|
|
6876
|
+
const bg = mergedLayer(ctx);
|
|
6877
|
+
if (bg) {
|
|
6878
|
+
layers = [bg];
|
|
6879
|
+
warn.extra.push("No layer could be imported, so the merged image was opened as the Background.");
|
|
6880
|
+
}
|
|
6881
|
+
}
|
|
6882
|
+
} else if (!ctx.skipPixels) {
|
|
6883
|
+
const bg = mergedLayer(ctx);
|
|
6884
|
+
if (bg) layers = [bg];
|
|
6885
|
+
}
|
|
6886
|
+
return {
|
|
6887
|
+
width: header.width,
|
|
6888
|
+
height: header.height,
|
|
6889
|
+
layers,
|
|
6890
|
+
warnings: warn.list(),
|
|
6891
|
+
summary: ctx.summary,
|
|
6892
|
+
resolution: resolution(file),
|
|
6893
|
+
info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels }
|
|
6894
|
+
};
|
|
6895
|
+
}
|
|
6896
|
+
function importPsd(bytes, options = {}) {
|
|
6897
|
+
if (bytes.length < 26) throw new PsdError("Not a PSD file: it is shorter than a PSD header.");
|
|
6898
|
+
return psdToLayers(readPsd(bytes), options);
|
|
6899
|
+
}
|
|
6900
|
+
|
|
6901
|
+
// src/image-editor/psd/export.ts
|
|
6902
|
+
var FLAG_PIXELS_IRRELEVANT = 8 | 16;
|
|
6903
|
+
var EMPTY_RECT = { top: 0, left: 0, bottom: 0, right: 0 };
|
|
6904
|
+
function unicodeBlock(s) {
|
|
6905
|
+
const w = new PsdWriter();
|
|
6906
|
+
w.unicode(s);
|
|
6907
|
+
return w.result();
|
|
6908
|
+
}
|
|
6909
|
+
function u32Bytes(v) {
|
|
6910
|
+
const w = new PsdWriter();
|
|
6911
|
+
w.u32(v);
|
|
6912
|
+
return w.result();
|
|
6913
|
+
}
|
|
6914
|
+
function sectionBlock(kind, blendKey) {
|
|
6915
|
+
const w = new PsdWriter();
|
|
6916
|
+
w.u32(kind);
|
|
6917
|
+
if (blendKey) {
|
|
6918
|
+
w.ascii("8BIM");
|
|
6919
|
+
w.ascii(blendKey);
|
|
6920
|
+
}
|
|
6921
|
+
return w.result();
|
|
6922
|
+
}
|
|
6923
|
+
var toRect = (r) => ({ top: r.y, left: r.x, bottom: r.y + r.height, right: r.x + r.width });
|
|
6924
|
+
function rleChannel(id, plane, width, height, psb) {
|
|
6925
|
+
return { id, compression: 1, data: encodeRle(plane, { planes: 1, width, height, depth: 8, psb }) };
|
|
6926
|
+
}
|
|
6927
|
+
var emptyChannel = (id) => ({ id, compression: 0, data: new Uint8Array(0) });
|
|
6928
|
+
function maskChannel(mask, ox, oy, psb) {
|
|
6929
|
+
if (mask.source) throw new PsdError("A parametric mask must be baked before export.");
|
|
6930
|
+
const bounds = _chunkZOOEX3WTcjs.contentBounds.call(void 0, mask.surface);
|
|
6931
|
+
const def = mask.defaultValue;
|
|
6932
|
+
const m = { rect: EMPTY_RECT, defaultColor: def, flags: mask.enabled === false ? MASK_FLAG_DISABLED : 0 };
|
|
6933
|
+
if ((_nullishCoalesce(mask.density, () => ( 1))) < 1) m.userDensity = Math.round(Math.max(0, _nullishCoalesce(mask.density, () => ( 1))) * 255);
|
|
6934
|
+
if ((_nullishCoalesce(mask.feather, () => ( 0))) > 0) m.userFeather = mask.feather;
|
|
6935
|
+
if (!bounds) return { channel: emptyChannel(CHANNEL_USER_MASK), mask: m };
|
|
6936
|
+
const plane = _chunkZOOEX3WTcjs.readRegion.call(void 0, mask.surface, bounds);
|
|
6937
|
+
m.rect = toRect({ ...bounds, x: bounds.x + ox, y: bounds.y + oy });
|
|
6938
|
+
return { channel: rleChannel(CHANNEL_USER_MASK, new Uint8Array(plane.buffer, plane.byteOffset, plane.length), bounds.width, bounds.height, psb), mask: m };
|
|
6939
|
+
}
|
|
6940
|
+
function lockBits(layer) {
|
|
6941
|
+
const l = layer.locks;
|
|
6942
|
+
if (!l) return 0;
|
|
6943
|
+
return (l.all ? 2147483648 : 0) | (l.transparency ? 1 : 0) | (l.pixels ? 2 : 0) | (l.position ? 4 : 0);
|
|
6944
|
+
}
|
|
6945
|
+
function exportPsd(input) {
|
|
6946
|
+
const { width, height } = input;
|
|
6947
|
+
if (width < 1 || height < 1) throw new PsdError("The document is empty.");
|
|
6948
|
+
const psb = width > PSD_MAX_DIMENSION || height > PSD_MAX_DIMENSION;
|
|
6949
|
+
const records = [];
|
|
6950
|
+
let nextId = 0;
|
|
6951
|
+
const common = (layer, extra = []) => {
|
|
6952
|
+
const name = layer.name || (layer.type === "adjustment" ? adjustmentKindLabel(layer.kind) : "");
|
|
6953
|
+
const blocks = [{ key: "luni", data: unicodeBlock(name) }, { key: "lyid", data: u32Bytes(++nextId) }, ...extra];
|
|
6954
|
+
const locks = lockBits(layer);
|
|
6955
|
+
if (locks) blocks.push({ key: "lspf", data: u32Bytes(locks >>> 0) });
|
|
6956
|
+
return {
|
|
6957
|
+
opacity: Math.round(Math.min(1, Math.max(0, layer.opacity)) * 255),
|
|
6958
|
+
clipping: layer.clipped ? 1 : 0,
|
|
6959
|
+
flags: (layer.visible ? 0 : LAYER_FLAG_HIDDEN) | (_optionalChain([layer, 'access', _113 => _113.locks, 'optionalAccess', _114 => _114.transparency]) ? LAYER_FLAG_TRANSPARENCY_PROTECTED : 0),
|
|
6960
|
+
legacyName: name,
|
|
6961
|
+
blocks
|
|
6962
|
+
};
|
|
6963
|
+
};
|
|
6964
|
+
const write = (layer) => {
|
|
6965
|
+
switch (layer.type) {
|
|
6966
|
+
case "group": {
|
|
6967
|
+
records.push({
|
|
6968
|
+
rect: EMPTY_RECT,
|
|
6969
|
+
channels: [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel),
|
|
6970
|
+
blendKey: "norm",
|
|
6971
|
+
opacity: 255,
|
|
6972
|
+
clipping: 0,
|
|
6973
|
+
flags: FLAG_PIXELS_IRRELEVANT | (layer.visible ? 0 : LAYER_FLAG_HIDDEN),
|
|
6974
|
+
legacyName: "</Layer group>",
|
|
6975
|
+
blocks: [
|
|
6976
|
+
{ key: "luni", data: unicodeBlock("</Layer group>") },
|
|
6977
|
+
{ key: "lsct", data: sectionBlock(SECTION_DIVIDER) }
|
|
6978
|
+
]
|
|
6979
|
+
});
|
|
6980
|
+
for (const child of layer.children) write(child);
|
|
6981
|
+
const blendKey = _nullishCoalesce(BLEND_TO_PSD[layer.blend], () => ( "norm"));
|
|
6982
|
+
const base = common(layer, [{ key: "lsct", data: sectionBlock(layer.collapsed ? SECTION_CLOSED : SECTION_OPEN, blendKey) }]);
|
|
6983
|
+
const rec = {
|
|
6984
|
+
...base,
|
|
6985
|
+
rect: EMPTY_RECT,
|
|
6986
|
+
channels: [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel),
|
|
6987
|
+
blendKey,
|
|
6988
|
+
flags: base.flags | FLAG_PIXELS_IRRELEVANT
|
|
6989
|
+
};
|
|
6990
|
+
if (layer.mask) {
|
|
6991
|
+
const m = maskChannel(layer.mask, 0, 0, psb);
|
|
6992
|
+
rec.channels.push(m.channel);
|
|
6993
|
+
rec.mask = m.mask;
|
|
6994
|
+
}
|
|
6995
|
+
records.push(rec);
|
|
6996
|
+
return;
|
|
6997
|
+
}
|
|
6998
|
+
case "adjustment": {
|
|
6999
|
+
const block = writeAdjustmentBlock(layer.kind, layer.params);
|
|
7000
|
+
const rec = {
|
|
7001
|
+
...common(layer, [{ key: block.key, data: block.data }]),
|
|
7002
|
+
rect: EMPTY_RECT,
|
|
7003
|
+
channels: [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel),
|
|
7004
|
+
blendKey: _nullishCoalesce(BLEND_TO_PSD[layer.blend], () => ( "norm"))
|
|
7005
|
+
};
|
|
7006
|
+
if (layer.mask) {
|
|
7007
|
+
const m = maskChannel(layer.mask, 0, 0, psb);
|
|
7008
|
+
rec.channels.push(m.channel);
|
|
7009
|
+
rec.mask = m.mask;
|
|
7010
|
+
}
|
|
7011
|
+
records.push(rec);
|
|
7012
|
+
return;
|
|
7013
|
+
}
|
|
7014
|
+
case "pixel": {
|
|
7015
|
+
if (layer.source === "document") throw new PsdError(`Layer "${layer.name}" reads the document image; resolve its pixels before export.`);
|
|
7016
|
+
if (_optionalChain([layer, 'access', _115 => _115.filters, 'optionalAccess', _116 => _116.some, 'call', _117 => _117(isActiveFilter)])) throw new PsdError(`Layer "${layer.name}" has live filters; bake them before export.`);
|
|
7017
|
+
const extra = [];
|
|
7018
|
+
if (layer.fillOpacity !== void 0 && layer.fillOpacity < 1) {
|
|
7019
|
+
extra.push({ key: "iOpa", data: Uint8Array.from([Math.round(Math.max(0, layer.fillOpacity) * 255), 0, 0, 0]) });
|
|
7020
|
+
}
|
|
7021
|
+
const rec = { ...common(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: _nullishCoalesce(BLEND_TO_PSD[layer.blend], () => ( "norm")) };
|
|
7022
|
+
const bounds = _chunkZOOEX3WTcjs.contentBounds.call(void 0, layer.surface);
|
|
7023
|
+
if (bounds) {
|
|
7024
|
+
const n2 = bounds.width * bounds.height;
|
|
7025
|
+
const [r2, g2, b2, a2] = rgbaToPlanes(_chunkZOOEX3WTcjs.readRegion.call(void 0, layer.surface, bounds), n2);
|
|
7026
|
+
rec.rect = toRect({ ...bounds, x: bounds.x + layer.offset.x, y: bounds.y + layer.offset.y });
|
|
7027
|
+
rec.channels = [
|
|
7028
|
+
rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
|
|
7029
|
+
rleChannel(0, r2, bounds.width, bounds.height, psb),
|
|
7030
|
+
rleChannel(1, g2, bounds.width, bounds.height, psb),
|
|
7031
|
+
rleChannel(2, b2, bounds.width, bounds.height, psb)
|
|
7032
|
+
];
|
|
7033
|
+
} else {
|
|
7034
|
+
rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
|
|
7035
|
+
}
|
|
7036
|
+
if (layer.mask) {
|
|
7037
|
+
const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb);
|
|
7038
|
+
rec.channels.push(m.channel);
|
|
7039
|
+
rec.mask = m.mask;
|
|
7040
|
+
}
|
|
7041
|
+
records.push(rec);
|
|
7042
|
+
return;
|
|
7043
|
+
}
|
|
7044
|
+
case "annotation":
|
|
7045
|
+
throw new PsdError(`Annotation layer "${layer.name}" must be rasterized before export.`);
|
|
7046
|
+
}
|
|
7047
|
+
};
|
|
7048
|
+
for (const layer of input.layers) write(layer);
|
|
7049
|
+
if (records.length > 32767) throw new PsdError("A PSD holds at most 32767 layer records.");
|
|
7050
|
+
const n = width * height;
|
|
7051
|
+
if (input.merged.length < n * 4) throw new PsdError(`The merged image has ${input.merged.length} bytes, expected ${n * 4}.`);
|
|
7052
|
+
const [r, g, b, a] = rgbaToPlanes(matteWhite(input.merged), n);
|
|
7053
|
+
const transparent = a.some((v) => v !== 255);
|
|
7054
|
+
const planes = transparent ? [r, g, b, a] : [r, g, b];
|
|
7055
|
+
const merged = new Uint8Array(n * planes.length);
|
|
7056
|
+
planes.forEach((p, i) => merged.set(p, i * n));
|
|
7057
|
+
const res = Math.max(1, _nullishCoalesce(input.resolution, () => ( 72)));
|
|
7058
|
+
const rw = new PsdWriter();
|
|
7059
|
+
for (let k = 0; k < 2; k++) {
|
|
7060
|
+
rw.u32(Math.round(res * 65536));
|
|
7061
|
+
rw.u16(1);
|
|
7062
|
+
rw.u16(1);
|
|
7063
|
+
}
|
|
7064
|
+
const version = new PsdWriter();
|
|
7065
|
+
version.u32(1);
|
|
7066
|
+
version.u8(1);
|
|
7067
|
+
version.unicode("Pixerate Editor");
|
|
7068
|
+
version.unicode("Pixerate Editor");
|
|
7069
|
+
version.u32(1);
|
|
7070
|
+
const resources = [
|
|
7071
|
+
{ id: 1005, name: "", data: rw.result() },
|
|
7072
|
+
{ id: 1057, name: "", data: version.result() }
|
|
7073
|
+
];
|
|
7074
|
+
const bytes = writePsd(
|
|
7075
|
+
{
|
|
7076
|
+
header: { psb, channels: planes.length, width, height, depth: 8, colorMode: 3 },
|
|
7077
|
+
colorModeData: new Uint8Array(0),
|
|
7078
|
+
resources,
|
|
7079
|
+
layers: records,
|
|
7080
|
+
mergedAlpha: transparent && records.length > 0,
|
|
7081
|
+
globalBlocks: [],
|
|
7082
|
+
imageCompression: 1,
|
|
7083
|
+
imageData: encodeRle(merged, { planes: planes.length, width, height, depth: 8, psb })
|
|
7084
|
+
},
|
|
7085
|
+
encodeLegacyName
|
|
7086
|
+
);
|
|
7087
|
+
return { bytes, psb, records: records.length };
|
|
7088
|
+
}
|
|
7089
|
+
|
|
4979
7090
|
// src/image-editor/controller.ts
|
|
4980
7091
|
var IMAGE_EDITOR_SCHEMA_VERSION = LAYERED_SCHEMA_VERSION;
|
|
4981
7092
|
function paintCoverageInto(base, coverage, apply, rects) {
|
|
@@ -4986,7 +7097,7 @@ function paintCoverageInto(base, coverage, apply, rects) {
|
|
|
4986
7097
|
const key = _chunkZOOEX3WTcjs.tileKey.call(void 0, t.tx, t.ty);
|
|
4987
7098
|
if (done.has(key)) continue;
|
|
4988
7099
|
done.add(key);
|
|
4989
|
-
const src = _nullishCoalesce(_optionalChain([base, 'access',
|
|
7100
|
+
const src = _nullishCoalesce(_optionalChain([base, 'access', _118 => _118.tiles, 'access', _119 => _119.get, 'call', _120 => _120(key), 'optionalAccess', _121 => _121.data]), () => ( defaultTile(base)));
|
|
4990
7101
|
const data = _chunkPDCITYBTcjs.applyStrokeToTile.call(void 0, coverage, src, base.channels, t.tx, t.ty, apply);
|
|
4991
7102
|
const tile = _chunkZOOEX3WTcjs.finishTile.call(void 0, data, base.channels, base.defaultValue);
|
|
4992
7103
|
if (tile) tiles.set(key, tile);
|
|
@@ -5000,8 +7111,8 @@ function defaultTile(s) {
|
|
|
5000
7111
|
if (s.defaultValue) d.fill(s.defaultValue);
|
|
5001
7112
|
return d;
|
|
5002
7113
|
}
|
|
5003
|
-
var PaintStrokeSession = (
|
|
5004
|
-
constructor(controller, target, stroke, apply) {;
|
|
7114
|
+
var PaintStrokeSession = (_class6 = class {
|
|
7115
|
+
constructor(controller, target, stroke, apply) {;_class6.prototype.__init28.call(this);_class6.prototype.__init29.call(this);_class6.prototype.__init30.call(this);
|
|
5005
7116
|
this.controller = controller;
|
|
5006
7117
|
this.target = target;
|
|
5007
7118
|
this.stroke = stroke;
|
|
@@ -5017,9 +7128,9 @@ var PaintStrokeSession = (_class4 = class {
|
|
|
5017
7128
|
|
|
5018
7129
|
|
|
5019
7130
|
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
7131
|
+
__init28() {this.touched = /* @__PURE__ */ new Set()}
|
|
7132
|
+
__init29() {this.last = null}
|
|
7133
|
+
__init30() {this.closed = false}
|
|
5023
7134
|
get layerId() {
|
|
5024
7135
|
return this.target.id;
|
|
5025
7136
|
}
|
|
@@ -5041,8 +7152,8 @@ var PaintStrokeSession = (_class4 = class {
|
|
|
5041
7152
|
}
|
|
5042
7153
|
}
|
|
5043
7154
|
for (const [key, { tx, ty, r }] of regions) {
|
|
5044
|
-
const src = _nullishCoalesce(_optionalChain([this, 'access',
|
|
5045
|
-
const prev = this.touched.has(key) ? _optionalChain([this, 'access',
|
|
7155
|
+
const src = _nullishCoalesce(_optionalChain([this, 'access', _122 => _122.base, 'access', _123 => _123.tiles, 'access', _124 => _124.get, 'call', _125 => _125(key), 'optionalAccess', _126 => _126.data]), () => ( defaultTile(this.base)));
|
|
7156
|
+
const prev = this.touched.has(key) ? _optionalChain([this, 'access', _127 => _127.live, 'access', _128 => _128.get, 'call', _129 => _129(key), 'optionalAccess', _130 => _130.data]) : void 0;
|
|
5046
7157
|
this.touched.add(key);
|
|
5047
7158
|
const data = _chunkPDCITYBTcjs.applyStrokeToTile.call(void 0, this.stroke.coverage, src, ch, tx, ty, this.apply, prev ? { into: prev, region: r } : {});
|
|
5048
7159
|
this.live.set(key, { data, uniform: null });
|
|
@@ -5076,7 +7187,7 @@ var PaintStrokeSession = (_class4 = class {
|
|
|
5076
7187
|
this.closed = true;
|
|
5077
7188
|
this.controller._strokeCommit(this.before, this.target.id, this.target.channel, null);
|
|
5078
7189
|
}
|
|
5079
|
-
},
|
|
7190
|
+
}, _class6);
|
|
5080
7191
|
function sameTile(a, b) {
|
|
5081
7192
|
if (!a || !b) return !a && !b;
|
|
5082
7193
|
if (a === b) return true;
|
|
@@ -5113,14 +7224,14 @@ function migrateSerializedImageEditorState(data) {
|
|
|
5113
7224
|
const legacy = data;
|
|
5114
7225
|
const adjustments = normalizeStoredAdjustments(legacy.adjustments);
|
|
5115
7226
|
return {
|
|
5116
|
-
version: _optionalChain([adjustments, 'access',
|
|
7227
|
+
version: _optionalChain([adjustments, 'access', _131 => _131.layers, 'optionalAccess', _132 => _132.length]) ? 2 : 1,
|
|
5117
7228
|
crop: legacy.crop ? { ...legacy.crop } : null,
|
|
5118
7229
|
transform: { ...DEFAULT_TRANSFORM, ...legacy.transform },
|
|
5119
7230
|
adjustments: serializeAdjustments(adjustments),
|
|
5120
7231
|
depthMask: {
|
|
5121
7232
|
...DEFAULT_DEPTH_MASK,
|
|
5122
7233
|
...legacy.depthMask,
|
|
5123
|
-
depthRange: [..._nullishCoalesce(_optionalChain([legacy, 'access',
|
|
7234
|
+
depthRange: [..._nullishCoalesce(_optionalChain([legacy, 'access', _133 => _133.depthMask, 'optionalAccess', _134 => _134.depthRange]), () => ( DEFAULT_DEPTH_MASK.depthRange))]
|
|
5124
7235
|
},
|
|
5125
7236
|
annotations: JSON.parse(JSON.stringify(_nullishCoalesce(legacy.annotations, () => ( [])))),
|
|
5126
7237
|
...legacy.selection ? { selection: { ...legacy.selection } } : {}
|
|
@@ -5149,29 +7260,29 @@ function migrateToLayeredState(data, size) {
|
|
|
5149
7260
|
var DEFAULT_TRANSFORM = DEFAULT_TRANSFORM_VALUES;
|
|
5150
7261
|
var DEFAULT_DEPTH_MASK = DEFAULT_DEPTH_MASK_VALUES;
|
|
5151
7262
|
var DEVELOP_KEYS = ["brightness", "contrast", "saturation", "exposure", "temperature", "tint"];
|
|
5152
|
-
var ImageEditorController = (
|
|
7263
|
+
var ImageEditorController = (_class7 = class {
|
|
5153
7264
|
|
|
5154
7265
|
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
7266
|
+
__init31() {this.imageElement = null}
|
|
7267
|
+
__init32() {this.listeners = /* @__PURE__ */ new Set()}
|
|
7268
|
+
__init33() {this.histogramListeners = /* @__PURE__ */ new Set()}
|
|
5158
7269
|
|
|
5159
7270
|
// History stacks
|
|
5160
|
-
|
|
5161
|
-
|
|
7271
|
+
__init34() {this.undoStack = []}
|
|
7272
|
+
__init35() {this.redoStack = []}
|
|
5162
7273
|
|
|
5163
7274
|
|
|
5164
|
-
|
|
7275
|
+
__init36() {this.isApplyingHistory = false}
|
|
5165
7276
|
|
|
5166
7277
|
/** Pixels the selection tools sample (host-provided or read back from the source). */
|
|
5167
|
-
|
|
5168
|
-
|
|
7278
|
+
__init37() {this.samplePixels = null}
|
|
7279
|
+
__init38() {this.samplePixelsOverride = false}
|
|
5169
7280
|
/** Decoded source pixels (the Background's surface), by the buffer or element they came from. */
|
|
5170
|
-
|
|
5171
|
-
|
|
7281
|
+
__init39() {this.sourceSurfaces = /* @__PURE__ */ new WeakMap()}
|
|
7282
|
+
__init40() {this.viewKey = []}
|
|
5172
7283
|
/** For `compositePixels` and mask evaluation (the renderer keeps its own for the viewport). */
|
|
5173
|
-
|
|
5174
|
-
constructor(options = {}) {;
|
|
7284
|
+
__init41() {this.compositor = new LayerCompositor()}
|
|
7285
|
+
constructor(options = {}) {;_class7.prototype.__init31.call(this);_class7.prototype.__init32.call(this);_class7.prototype.__init33.call(this);_class7.prototype.__init34.call(this);_class7.prototype.__init35.call(this);_class7.prototype.__init36.call(this);_class7.prototype.__init37.call(this);_class7.prototype.__init38.call(this);_class7.prototype.__init39.call(this);_class7.prototype.__init40.call(this);_class7.prototype.__init41.call(this);_class7.prototype.__init42.call(this);_class7.prototype.__init43.call(this);_class7.prototype.__init44.call(this);_class7.prototype.__init45.call(this);_class7.prototype.__init46.call(this);_class7.prototype.__init47.call(this);_class7.prototype.__init48.call(this);_class7.prototype.__init49.call(this);
|
|
5175
7286
|
this.maxHistoryDepth = _nullishCoalesce(options.maxHistoryDepth, () => ( 50));
|
|
5176
7287
|
this.maxHistoryBytes = _nullishCoalesce(options.maxHistoryBytes, () => ( 512 * 1024 * 1024));
|
|
5177
7288
|
this.onStateChange = options.onStateChange;
|
|
@@ -5215,10 +7326,10 @@ var ImageEditorController = (_class5 = class {
|
|
|
5215
7326
|
};
|
|
5216
7327
|
}
|
|
5217
7328
|
this.applyStored(_nullishCoalesce(options.initialState, () => ( {})));
|
|
5218
|
-
if (_optionalChain([options, 'access',
|
|
7329
|
+
if (_optionalChain([options, 'access', _135 => _135.initialState, 'optionalAccess', _136 => _136.selection])) {
|
|
5219
7330
|
try {
|
|
5220
7331
|
this.state.selection = normalizeSelection(deserializeSelection(options.initialState.selection));
|
|
5221
|
-
} catch (
|
|
7332
|
+
} catch (e16) {
|
|
5222
7333
|
}
|
|
5223
7334
|
}
|
|
5224
7335
|
this.initialSnapshot = this.captureHistoryEntry();
|
|
@@ -5259,7 +7370,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5259
7370
|
height: img.naturalHeight || img.height || 600
|
|
5260
7371
|
}
|
|
5261
7372
|
};
|
|
5262
|
-
} catch (
|
|
7373
|
+
} catch (e17) {
|
|
5263
7374
|
return { sourceUrl: src, element: null, dimensions: { ...this.state.imageDimensions } };
|
|
5264
7375
|
}
|
|
5265
7376
|
}
|
|
@@ -5292,13 +7403,13 @@ var ImageEditorController = (_class5 = class {
|
|
|
5292
7403
|
* Where layer pixels changed since the last viewport render, when only strokes changed them
|
|
5293
7404
|
* (the renderer then recomposites just those rectangles); `'all'` after any other change.
|
|
5294
7405
|
*/
|
|
5295
|
-
|
|
7406
|
+
__init42() {this.pendingDirty = "all"}
|
|
5296
7407
|
notify(strokeRects) {
|
|
5297
7408
|
if (strokeRects && this.pendingDirty !== "all") this.pendingDirty.push(...strokeRects);
|
|
5298
7409
|
else if (!strokeRects) this.pendingDirty = "all";
|
|
5299
7410
|
this.syncViews();
|
|
5300
7411
|
const currentState = { ...this.state };
|
|
5301
|
-
_optionalChain([this, 'access',
|
|
7412
|
+
_optionalChain([this, 'access', _137 => _137.onStateChange, 'optionalCall', _138 => _138(currentState)]);
|
|
5302
7413
|
this.listeners.forEach((l) => l(currentState));
|
|
5303
7414
|
}
|
|
5304
7415
|
/** Recomputes the compatibility views (`adjustments`, `depthMask`, `annotations`) when the stack changed. */
|
|
@@ -5503,7 +7614,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5503
7614
|
return this.state.layers;
|
|
5504
7615
|
}
|
|
5505
7616
|
getLayer(id) {
|
|
5506
|
-
return _optionalChain([_chunkH543GD6Tcjs.findLayer.call(void 0, this.state.layers, id), 'optionalAccess',
|
|
7617
|
+
return _optionalChain([_chunkH543GD6Tcjs.findLayer.call(void 0, this.state.layers, id), 'optionalAccess', _139 => _139.layer]);
|
|
5507
7618
|
}
|
|
5508
7619
|
/** The active layer, or `undefined`. */
|
|
5509
7620
|
getActiveLayer() {
|
|
@@ -5516,7 +7627,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5516
7627
|
setActiveLayer(id, target = "pixels") {
|
|
5517
7628
|
if (id !== null && !this.getLayer(id)) return false;
|
|
5518
7629
|
const layer = id ? this.getLayer(id) : void 0;
|
|
5519
|
-
const t = target === "mask" && _optionalChain([layer, 'optionalAccess',
|
|
7630
|
+
const t = target === "mask" && _optionalChain([layer, 'optionalAccess', _140 => _140.mask]) ? "mask" : "pixels";
|
|
5520
7631
|
if (this.state.activeLayerId === id && this.state.activeTarget === t) return true;
|
|
5521
7632
|
this.state.activeLayerId = id;
|
|
5522
7633
|
this.state.activeTarget = t;
|
|
@@ -5535,7 +7646,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5535
7646
|
if (!b) return null;
|
|
5536
7647
|
return { x: b.x + layer.offset.x, y: b.y + layer.offset.y, width: b.width, height: b.height, data: _chunkZOOEX3WTcjs.readRegion.call(void 0, surface, b) };
|
|
5537
7648
|
}
|
|
5538
|
-
|
|
7649
|
+
__init43() {this.boundsCache = /* @__PURE__ */ new WeakMap()}
|
|
5539
7650
|
/**
|
|
5540
7651
|
* Document bounds of a layer's non-transparent pixels (pixel layers; the Background's source
|
|
5541
7652
|
* included), or `null` for an empty or non-pixel layer.
|
|
@@ -5571,8 +7682,8 @@ var ImageEditorController = (_class5 = class {
|
|
|
5571
7682
|
const { width, height } = this.naturalSize;
|
|
5572
7683
|
return { width, height, surfaceOf: (l) => this.surfaceOf(l), version: this.sourceVersion() };
|
|
5573
7684
|
}
|
|
5574
|
-
|
|
5575
|
-
|
|
7685
|
+
__init44() {this.sourceIds = /* @__PURE__ */ new WeakMap()}
|
|
7686
|
+
__init45() {this.nextSourceId = 1}
|
|
5576
7687
|
/** Changes whenever the Background's source pixels can have changed. */
|
|
5577
7688
|
sourceVersion() {
|
|
5578
7689
|
const key = this.samplePixelsOverride ? this.samplePixels : _nullishCoalesce(this.imageElement, () => ( this.samplePixels));
|
|
@@ -5621,7 +7732,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5621
7732
|
}
|
|
5622
7733
|
return fits ? fromPixels(px) : null;
|
|
5623
7734
|
}
|
|
5624
|
-
|
|
7735
|
+
__init46() {this.opaqueCache = /* @__PURE__ */ new WeakMap()}
|
|
5625
7736
|
/** Whether every source pixel is opaque (some legacy renders depend on it). */
|
|
5626
7737
|
sourceIsOpaque() {
|
|
5627
7738
|
const s = this.sourceSurface();
|
|
@@ -5645,9 +7756,9 @@ var ImageEditorController = (_class5 = class {
|
|
|
5645
7756
|
if (!ctx || typeof ctx.getImageData !== "function") return null;
|
|
5646
7757
|
ctx.drawImage(el, 0, 0, width, height);
|
|
5647
7758
|
const data = ctx.getImageData(0, 0, width, height);
|
|
5648
|
-
if (!_optionalChain([data, 'optionalAccess',
|
|
7759
|
+
if (!_optionalChain([data, 'optionalAccess', _141 => _141.data]) || data.data.length < width * height * 4) return null;
|
|
5649
7760
|
return { width, height, data: data.data };
|
|
5650
|
-
} catch (
|
|
7761
|
+
} catch (e18) {
|
|
5651
7762
|
return null;
|
|
5652
7763
|
}
|
|
5653
7764
|
}
|
|
@@ -5656,7 +7767,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5656
7767
|
commitLayers(next, extra, commitToHistory = true) {
|
|
5657
7768
|
if (commitToHistory) this.recordHistory();
|
|
5658
7769
|
this.state.layers = next;
|
|
5659
|
-
_optionalChain([extra, 'optionalCall',
|
|
7770
|
+
_optionalChain([extra, 'optionalCall', _142 => _142()]);
|
|
5660
7771
|
if (this.state.activeLayerId && !_chunkH543GD6Tcjs.findLayer.call(void 0, next, this.state.activeLayerId)) {
|
|
5661
7772
|
this.state.activeLayerId = null;
|
|
5662
7773
|
this.state.activeTarget = "pixels";
|
|
@@ -5693,7 +7804,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5693
7804
|
const layer = {
|
|
5694
7805
|
type: "pixel",
|
|
5695
7806
|
id: init.id && !ids.has(init.id) ? init.id : newLayerId(),
|
|
5696
|
-
name: _optionalChain([init, 'access',
|
|
7807
|
+
name: _optionalChain([init, 'access', _143 => _143.name, 'optionalAccess', _144 => _144.trim, 'call', _145 => _145()]) || this.nextLayerName(),
|
|
5697
7808
|
visible: _nullishCoalesce(init.visible, () => ( true)),
|
|
5698
7809
|
opacity: _nullishCoalesce(init.opacity, () => ( 1)),
|
|
5699
7810
|
blend: _nullishCoalesce(blend, () => ( "normal")),
|
|
@@ -5720,12 +7831,12 @@ var ImageEditorController = (_class5 = class {
|
|
|
5720
7831
|
async decodeImage(image) {
|
|
5721
7832
|
const trimmed = image.trim();
|
|
5722
7833
|
let png = null;
|
|
5723
|
-
if (/^data:image\/png/i.test(trimmed)) png = _nullishCoalesce(_optionalChain([_chunkH543GD6Tcjs.parseDataUrl.call(void 0, trimmed), 'optionalAccess',
|
|
7834
|
+
if (/^data:image\/png/i.test(trimmed)) png = _nullishCoalesce(_optionalChain([_chunkH543GD6Tcjs.parseDataUrl.call(void 0, trimmed), 'optionalAccess', _146 => _146.bytes]), () => ( null));
|
|
5724
7835
|
else if (/^[A-Za-z0-9+/=\s]+$/.test(trimmed) && trimmed.length > 16) {
|
|
5725
7836
|
try {
|
|
5726
7837
|
const bytes = _chunkH543GD6Tcjs.base64ToBytes.call(void 0, trimmed);
|
|
5727
7838
|
if (_chunkH543GD6Tcjs.isPng.call(void 0, bytes)) png = bytes;
|
|
5728
|
-
} catch (
|
|
7839
|
+
} catch (e19) {
|
|
5729
7840
|
png = null;
|
|
5730
7841
|
}
|
|
5731
7842
|
}
|
|
@@ -5733,14 +7844,14 @@ var ImageEditorController = (_class5 = class {
|
|
|
5733
7844
|
try {
|
|
5734
7845
|
const d = _chunkH543GD6Tcjs.decodePng.call(void 0, png);
|
|
5735
7846
|
return { width: d.width, height: d.height, data: d.data };
|
|
5736
|
-
} catch (
|
|
7847
|
+
} catch (e20) {
|
|
5737
7848
|
}
|
|
5738
7849
|
}
|
|
5739
7850
|
const src = png ? `data:image/png;base64,${_chunkH543GD6Tcjs.bytesToBase64.call(void 0, png)}` : trimmed;
|
|
5740
7851
|
let img;
|
|
5741
7852
|
try {
|
|
5742
7853
|
img = await this.renderer.imageCache.get(src);
|
|
5743
|
-
} catch (
|
|
7854
|
+
} catch (e21) {
|
|
5744
7855
|
throw new LayerOperationError("The image could not be decoded here. Pass a PNG (data URL or base64), or run in a browser for other formats and URLs.");
|
|
5745
7856
|
}
|
|
5746
7857
|
const w = img.naturalWidth || img.width;
|
|
@@ -5778,9 +7889,9 @@ var ImageEditorController = (_class5 = class {
|
|
|
5778
7889
|
moveLayer(id, placement) {
|
|
5779
7890
|
const next = moveLayer(this.state.layers, id, placement);
|
|
5780
7891
|
const loc = _chunkH543GD6Tcjs.findLayer.call(void 0, next, id);
|
|
5781
|
-
if (next === this.state.layers) return { parentId: _nullishCoalesce(_optionalChain([loc, 'access',
|
|
7892
|
+
if (next === this.state.layers) return { parentId: _nullishCoalesce(_optionalChain([loc, 'access', _147 => _147.parent, 'optionalAccess', _148 => _148.id]), () => ( null)), index: loc.index };
|
|
5782
7893
|
this.commitLayers(next);
|
|
5783
|
-
return { parentId: _nullishCoalesce(_optionalChain([loc, 'access',
|
|
7894
|
+
return { parentId: _nullishCoalesce(_optionalChain([loc, 'access', _149 => _149.parent, 'optionalAccess', _150 => _150.id]), () => ( null)), index: loc.index };
|
|
5784
7895
|
}
|
|
5785
7896
|
/**
|
|
5786
7897
|
* Changes name, visibility, opacity, fill, blend, clipping, locks or (groups) collapsed state, as
|
|
@@ -5797,7 +7908,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5797
7908
|
const group = {
|
|
5798
7909
|
type: "group",
|
|
5799
7910
|
id: newLayerId("group"),
|
|
5800
|
-
name: _optionalChain([init, 'access',
|
|
7911
|
+
name: _optionalChain([init, 'access', _151 => _151.name, 'optionalAccess', _152 => _152.trim, 'call', _153 => _153()]) || "Group",
|
|
5801
7912
|
visible: true,
|
|
5802
7913
|
opacity: 1,
|
|
5803
7914
|
blend,
|
|
@@ -5847,7 +7958,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5847
7958
|
let mask;
|
|
5848
7959
|
if (from === "selection") {
|
|
5849
7960
|
const sel = this.state.selection;
|
|
5850
|
-
if (!_optionalChain([sel, 'optionalAccess',
|
|
7961
|
+
if (!_optionalChain([sel, 'optionalAccess', _154 => _154.bounds])) throw new LayerOperationError("Nothing is selected; select first, or use reveal-all / hide-all.");
|
|
5851
7962
|
mask = this.maskFromSelection(sel, props);
|
|
5852
7963
|
if (layer.type === "pixel" && (layer.offset.x || layer.offset.y)) {
|
|
5853
7964
|
mask = { ...mask, surface: _chunkZOOEX3WTcjs.translateSurface.call(void 0, mask.surface, -layer.offset.x, -layer.offset.y) };
|
|
@@ -5925,7 +8036,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
5925
8036
|
const layer = loc.layer;
|
|
5926
8037
|
if (layer.type !== "pixel") throw new LayerOperationError(`Layer via copy needs a pixel layer; "${id}" is a ${layer.type} layer.`);
|
|
5927
8038
|
const sel = this.state.selection;
|
|
5928
|
-
if (!_optionalChain([sel, 'optionalAccess',
|
|
8039
|
+
if (!_optionalChain([sel, 'optionalAccess', _155 => _155.bounds])) throw new LayerOperationError("Nothing is selected; select the pixels to copy first.");
|
|
5929
8040
|
if (options.cut) requireUnlocked(layer, "pixels", "cut from it");
|
|
5930
8041
|
const surface = this.surfaceOf(layer);
|
|
5931
8042
|
const sb = sel.bounds;
|
|
@@ -5943,14 +8054,14 @@ var ImageEditorController = (_class5 = class {
|
|
|
5943
8054
|
const copy = {
|
|
5944
8055
|
type: "pixel",
|
|
5945
8056
|
id: newLayerId(),
|
|
5946
|
-
name: _optionalChain([options, 'access',
|
|
8057
|
+
name: _optionalChain([options, 'access', _156 => _156.name, 'optionalAccess', _157 => _157.trim, 'call', _158 => _158()]) || `${layer.name || "Layer"} ${options.cut ? "cut" : "copy"}`,
|
|
5947
8058
|
visible: true,
|
|
5948
8059
|
opacity: 1,
|
|
5949
8060
|
blend: "normal",
|
|
5950
8061
|
surface: _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width: src.width, height: src.height, data: px }, 4, src.x, src.y),
|
|
5951
8062
|
offset: { ...layer.offset }
|
|
5952
8063
|
};
|
|
5953
|
-
let next = _chunkH543GD6Tcjs.insertLayer.call(void 0, this.state.layers, copy, _nullishCoalesce(_optionalChain([loc, 'access',
|
|
8064
|
+
let next = _chunkH543GD6Tcjs.insertLayer.call(void 0, this.state.layers, copy, _nullishCoalesce(_optionalChain([loc, 'access', _159 => _159.parent, 'optionalAccess', _160 => _160.id]), () => ( null)), loc.index + 1);
|
|
5954
8065
|
if (kept) {
|
|
5955
8066
|
const cutLayer = { ...layer, surface: _chunkZOOEX3WTcjs.writeRegion.call(void 0, surface, src, kept) };
|
|
5956
8067
|
delete cutLayer.source;
|
|
@@ -6089,7 +8200,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6089
8200
|
});
|
|
6090
8201
|
return bg.id;
|
|
6091
8202
|
}
|
|
6092
|
-
|
|
8203
|
+
__init47() {this.thumbCache = /* @__PURE__ */ new WeakMap()}
|
|
6093
8204
|
/**
|
|
6094
8205
|
* A small RGBA preview of a pixel layer over the canvas (or of its mask with `mask: true`),
|
|
6095
8206
|
* longest side `maxSide` px, point-sampled; `null` for layers without pixels.
|
|
@@ -6108,7 +8219,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6108
8219
|
const oy = layer.type === "pixel" ? layer.offset.y : 0;
|
|
6109
8220
|
const key = `${tw}x${th}:${ox},${oy}`;
|
|
6110
8221
|
let byKey = this.thumbCache.get(surface);
|
|
6111
|
-
const hit = _optionalChain([byKey, 'optionalAccess',
|
|
8222
|
+
const hit = _optionalChain([byKey, 'optionalAccess', _161 => _161.get, 'call', _162 => _162(key)]);
|
|
6112
8223
|
if (hit) return hit;
|
|
6113
8224
|
const out = new Uint8ClampedArray(tw * th * 4);
|
|
6114
8225
|
for (let y = 0; y < th; y++) {
|
|
@@ -6137,8 +8248,8 @@ var ImageEditorController = (_class5 = class {
|
|
|
6137
8248
|
const cur = this.state.paint;
|
|
6138
8249
|
const next = {
|
|
6139
8250
|
brush: options.brush ? _chunkPDCITYBTcjs.normalizeBrush.call(void 0, { ...cur.brush, ...options.brush }) : cur.brush,
|
|
6140
|
-
foreground: options.foreground !== void 0 ?
|
|
6141
|
-
background: options.background !== void 0 ?
|
|
8251
|
+
foreground: options.foreground !== void 0 ? toHex2(parseColor(options.foreground)) : cur.foreground,
|
|
8252
|
+
background: options.background !== void 0 ? toHex2(parseColor(options.background)) : cur.background
|
|
6142
8253
|
};
|
|
6143
8254
|
this.state.paint = next;
|
|
6144
8255
|
this.notify();
|
|
@@ -6170,7 +8281,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6170
8281
|
if (!layer.visible) throw new LayerOperationError(`Layer "${layer.name || id}" is hidden; show it before you ${action}.`);
|
|
6171
8282
|
const offset = layer.type === "pixel" ? layer.offset : { x: 0, y: 0 };
|
|
6172
8283
|
const surface = ch === "mask" ? layer.mask.surface : this.surfaceOf(layer);
|
|
6173
|
-
const lockTransparency = ch === "pixels" && Boolean(_optionalChain([layer, 'access',
|
|
8284
|
+
const lockTransparency = ch === "pixels" && Boolean(_optionalChain([layer, 'access', _163 => _163.locks, 'optionalAccess', _164 => _164.transparency]));
|
|
6174
8285
|
return { id, layer, channel: ch, offset, surface, lockTransparency };
|
|
6175
8286
|
}
|
|
6176
8287
|
/** The layer with its pixels (or mask) replaced by `surface`. */
|
|
@@ -6203,7 +8314,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6203
8314
|
opacity: brush.opacity,
|
|
6204
8315
|
blend: target.channel === "mask" ? "normal" : brush.blend,
|
|
6205
8316
|
lockTransparency: target.lockTransparency,
|
|
6206
|
-
selection: _optionalChain([this, 'access',
|
|
8317
|
+
selection: _optionalChain([this, 'access', _165 => _165.state, 'access', _166 => _166.selection, 'optionalAccess', _167 => _167.bounds]) ? this.state.selection : null,
|
|
6207
8318
|
offset: target.offset
|
|
6208
8319
|
};
|
|
6209
8320
|
return new PaintStrokeSession(this, target, new (0, _chunkPDCITYBTcjs.StrokeCoverage)(brush), apply);
|
|
@@ -6237,7 +8348,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6237
8348
|
paintStroke(init) {
|
|
6238
8349
|
if (!Array.isArray(init.points) || !init.points.length) throw new LayerOperationError("points must hold at least one { x, y } point.");
|
|
6239
8350
|
for (const p of init.points) {
|
|
6240
|
-
if (!Number.isFinite(_optionalChain([p, 'optionalAccess',
|
|
8351
|
+
if (!Number.isFinite(_optionalChain([p, 'optionalAccess', _168 => _168.x])) || !Number.isFinite(_optionalChain([p, 'optionalAccess', _169 => _169.y]))) throw new LayerOperationError("Every point needs finite x and y (document pixels).");
|
|
6241
8352
|
}
|
|
6242
8353
|
const session = this.beginStroke(init);
|
|
6243
8354
|
session.push(init.points);
|
|
@@ -6265,8 +8376,8 @@ var ImageEditorController = (_class5 = class {
|
|
|
6265
8376
|
const opacity = _nullishCoalesce(options.opacity, () => ( 1));
|
|
6266
8377
|
if (!(opacity >= 0 && opacity <= 1)) throw new LayerOperationError("opacity must be from 0 to 1.");
|
|
6267
8378
|
const blend = _nullishCoalesce(parseBlend(options.blend), () => ( "normal"));
|
|
6268
|
-
const sel = options.useSelection !== false && _optionalChain([this, 'access',
|
|
6269
|
-
const region = _nullishCoalesce(_optionalChain([sel, 'optionalAccess',
|
|
8379
|
+
const sel = options.useSelection !== false && _optionalChain([this, 'access', _170 => _170.state, 'access', _171 => _171.selection, 'optionalAccess', _172 => _172.bounds]) ? this.state.selection : null;
|
|
8380
|
+
const region = _nullishCoalesce(_optionalChain([sel, 'optionalAccess', _173 => _173.bounds]), () => ( { x: 0, y: 0, width, height }));
|
|
6270
8381
|
const coverage = new (0, _chunkPDCITYBTcjs.CoverageMap)();
|
|
6271
8382
|
const ones = new Float32Array(region.width * region.height);
|
|
6272
8383
|
if (sel) {
|
|
@@ -6384,7 +8495,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6384
8495
|
placeLayer(layers, node, where) {
|
|
6385
8496
|
if (where.aboveId) {
|
|
6386
8497
|
const loc = _chunkH543GD6Tcjs.findLayer.call(void 0, layers, where.aboveId);
|
|
6387
|
-
if (loc) return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, _nullishCoalesce(_optionalChain([loc, 'access',
|
|
8498
|
+
if (loc) return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, _nullishCoalesce(_optionalChain([loc, 'access', _174 => _174.parent, 'optionalAccess', _175 => _175.id]), () => ( null)), loc.index + 1);
|
|
6388
8499
|
}
|
|
6389
8500
|
if (where.parentId) {
|
|
6390
8501
|
const loc = _chunkH543GD6Tcjs.findLayer.call(void 0, layers, where.parentId);
|
|
@@ -6395,11 +8506,11 @@ var ImageEditorController = (_class5 = class {
|
|
|
6395
8506
|
const at = Math.max(0, Math.min(nodes.length, Math.round(where.adjustmentIndex)));
|
|
6396
8507
|
if (at < nodes.length) {
|
|
6397
8508
|
const loc = _chunkH543GD6Tcjs.findLayer.call(void 0, layers, nodes[at].id);
|
|
6398
|
-
return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, _nullishCoalesce(_optionalChain([loc, 'access',
|
|
8509
|
+
return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, _nullishCoalesce(_optionalChain([loc, 'access', _176 => _176.parent, 'optionalAccess', _177 => _177.id]), () => ( null)), loc.index);
|
|
6399
8510
|
}
|
|
6400
8511
|
if (nodes.length) {
|
|
6401
8512
|
const loc = _chunkH543GD6Tcjs.findLayer.call(void 0, layers, nodes[nodes.length - 1].id);
|
|
6402
|
-
return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, _nullishCoalesce(_optionalChain([loc, 'access',
|
|
8513
|
+
return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, _nullishCoalesce(_optionalChain([loc, 'access', _178 => _178.parent, 'optionalAccess', _179 => _179.id]), () => ( null)), loc.index + 1);
|
|
6403
8514
|
}
|
|
6404
8515
|
}
|
|
6405
8516
|
return _chunkH543GD6Tcjs.insertLayer.call(void 0, layers, node, null, this.defaultInsertIndex(layers));
|
|
@@ -6511,7 +8622,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6511
8622
|
const anchor = nodes[to];
|
|
6512
8623
|
const without = _chunkH543GD6Tcjs.mapLayer.call(void 0, layers, id, () => null);
|
|
6513
8624
|
const loc = _chunkH543GD6Tcjs.findLayer.call(void 0, without, anchor.id);
|
|
6514
|
-
return _chunkH543GD6Tcjs.insertLayer.call(void 0, without, node, _nullishCoalesce(_optionalChain([loc, 'access',
|
|
8625
|
+
return _chunkH543GD6Tcjs.insertLayer.call(void 0, without, node, _nullishCoalesce(_optionalChain([loc, 'access', _180 => _180.parent, 'optionalAccess', _181 => _181.id]), () => ( null)), to > from ? loc.index + 1 : loc.index);
|
|
6515
8626
|
}
|
|
6516
8627
|
/** Moves a layer to `toIndex` among the adjustment layers (0 = bottom) as one undo step. Returns false if nothing moved. */
|
|
6517
8628
|
moveAdjustmentLayer(id, toIndex) {
|
|
@@ -6547,7 +8658,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6547
8658
|
return _nullishCoalesce(this.state.selection, () => ( null));
|
|
6548
8659
|
}
|
|
6549
8660
|
get hasSelection() {
|
|
6550
|
-
return Boolean(_optionalChain([this, 'access',
|
|
8661
|
+
return Boolean(_optionalChain([this, 'access', _182 => _182.state, 'access', _183 => _183.selection, 'optionalAccess', _184 => _184.bounds]));
|
|
6551
8662
|
}
|
|
6552
8663
|
get naturalSize() {
|
|
6553
8664
|
return {
|
|
@@ -6637,13 +8748,13 @@ var ImageEditorController = (_class5 = class {
|
|
|
6637
8748
|
try {
|
|
6638
8749
|
const canvas = await this.renderSource();
|
|
6639
8750
|
const ctx = canvas.getContext("2d");
|
|
6640
|
-
const data2 = _optionalChain([ctx, 'optionalAccess',
|
|
8751
|
+
const data2 = _optionalChain([ctx, 'optionalAccess', _185 => _185.getImageData, 'optionalCall', _186 => _186(0, 0, width, height)]);
|
|
6641
8752
|
if (data2 && data2.data && data2.data.length >= width * height * 4) {
|
|
6642
8753
|
base = { width, height, data: data2.data };
|
|
6643
8754
|
this.samplePixels = base;
|
|
6644
8755
|
this.samplePixelsOverride = false;
|
|
6645
8756
|
}
|
|
6646
|
-
} catch (
|
|
8757
|
+
} catch (e22) {
|
|
6647
8758
|
base = null;
|
|
6648
8759
|
}
|
|
6649
8760
|
}
|
|
@@ -6652,9 +8763,18 @@ var ImageEditorController = (_class5 = class {
|
|
|
6652
8763
|
if (!this.samplePixelsOverride && !options.pixels) this.samplePixels = null;
|
|
6653
8764
|
return null;
|
|
6654
8765
|
}
|
|
6655
|
-
|
|
8766
|
+
const legacy = legacyView(this.stack(), width, height, null).exact;
|
|
8767
|
+
if (options.sample === "active-layer") {
|
|
8768
|
+
const layer = this.getActiveLayer();
|
|
8769
|
+
if (!layer || layer.type !== "pixel") {
|
|
8770
|
+
throw new LayerOperationError("Sampling the active layer needs an active pixel layer; select one, or sample the composite.");
|
|
8771
|
+
}
|
|
8772
|
+
const surface = layer.source === "document" && options.pixels ? _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, options.pixels, 4) : this.surfaceOf(layer);
|
|
8773
|
+
return { width, height, data: _chunkZOOEX3WTcjs.readRegion.call(void 0, surface, { x: -layer.offset.x, y: -layer.offset.y, width, height }) };
|
|
8774
|
+
}
|
|
8775
|
+
if (legacy && !options.sampleMerged) return base;
|
|
6656
8776
|
this.syncViews();
|
|
6657
|
-
if (
|
|
8777
|
+
if (legacy && !options.pixels) {
|
|
6658
8778
|
const copy = { width: base.width, height: base.height, data: new Uint8ClampedArray(base.data) };
|
|
6659
8779
|
applyAdjustments(copy, legacyView(this.stack(), width, height, null).adjustments);
|
|
6660
8780
|
return copy;
|
|
@@ -6666,7 +8786,9 @@ var ImageEditorController = (_class5 = class {
|
|
|
6666
8786
|
surfaceOf: (l) => l.source === "document" && pixels ? _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, pixels, 4) : this.surfaceOf(l),
|
|
6667
8787
|
version: pixels ? "pixels" : this.sourceVersion()
|
|
6668
8788
|
};
|
|
6669
|
-
const
|
|
8789
|
+
const stack = withoutAnnotations(this.state.layers);
|
|
8790
|
+
const layers = options.sampleMerged ? stack : pixelsOnly(stack);
|
|
8791
|
+
const data = new LayerCompositor().composite(layers, { x: 0, y: 0, width, height }, sources);
|
|
6670
8792
|
return { width, height, data };
|
|
6671
8793
|
}
|
|
6672
8794
|
async requirePixels(options) {
|
|
@@ -6692,7 +8814,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6692
8814
|
/** Select › Modify: grow, shrink, feather, border or smooth by `radius` pixels (one undo step). */
|
|
6693
8815
|
modifySelection(op, radius) {
|
|
6694
8816
|
const sel = this.state.selection;
|
|
6695
|
-
if (!_optionalChain([sel, 'optionalAccess',
|
|
8817
|
+
if (!_optionalChain([sel, 'optionalAccess', _187 => _187.bounds])) return false;
|
|
6696
8818
|
return this.setSelection(modifySelection(sel, op, radius));
|
|
6697
8819
|
}
|
|
6698
8820
|
/**
|
|
@@ -6701,7 +8823,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6701
8823
|
*/
|
|
6702
8824
|
async refineSelection(params, options = {}) {
|
|
6703
8825
|
const sel = this.state.selection;
|
|
6704
|
-
if (!_optionalChain([sel, 'optionalAccess',
|
|
8826
|
+
if (!_optionalChain([sel, 'optionalAccess', _188 => _188.bounds])) return false;
|
|
6705
8827
|
const pixels = (_nullishCoalesce(params.radius, () => ( 0))) > 0 ? await this.requirePixels(options) : null;
|
|
6706
8828
|
return this.setSelection(refineSelection(pixels, sel, params));
|
|
6707
8829
|
}
|
|
@@ -6718,7 +8840,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6718
8840
|
const canvas = this.renderer.createCanvas(w, h);
|
|
6719
8841
|
const ctx = canvas.getContext("2d");
|
|
6720
8842
|
if (ctx) ctx.drawImage(img, 0, 0, w, h);
|
|
6721
|
-
const data = _optionalChain([ctx, 'optionalAccess',
|
|
8843
|
+
const data = _optionalChain([ctx, 'optionalAccess', _189 => _189.getImageData, 'optionalCall', _190 => _190(0, 0, w, h)]);
|
|
6722
8844
|
if (!data) throw new Error("The mask image pixels are not available (no canvas access); pass pixels.");
|
|
6723
8845
|
pixels = { width: w, height: h, data: data.data };
|
|
6724
8846
|
} else {
|
|
@@ -6746,7 +8868,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6746
8868
|
*/
|
|
6747
8869
|
applySelectionAsLayerMask(layerId, props = {}) {
|
|
6748
8870
|
const sel = this.state.selection;
|
|
6749
|
-
if (!_optionalChain([sel, 'optionalAccess',
|
|
8871
|
+
if (!_optionalChain([sel, 'optionalAccess', _191 => _191.bounds]) || !this.getAdjustmentLayer(layerId)) return false;
|
|
6750
8872
|
return this.setLayerMask(layerId, this.maskFromSelection(sel, props));
|
|
6751
8873
|
}
|
|
6752
8874
|
setLayerMask(layerId, mask, commitToHistory = true) {
|
|
@@ -6777,7 +8899,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6777
8899
|
/** Load Selection from a layer mask (its pixels; density and feather are not applied). */
|
|
6778
8900
|
selectionFromLayerMask(layerId, mode = "replace") {
|
|
6779
8901
|
const layer = this.getLayer(layerId);
|
|
6780
|
-
if (!_optionalChain([layer, 'optionalAccess',
|
|
8902
|
+
if (!_optionalChain([layer, 'optionalAccess', _192 => _192.mask]) || layer.mask.source) return false;
|
|
6781
8903
|
const { width, height } = this.naturalSize;
|
|
6782
8904
|
const ox = layer.type === "pixel" ? layer.offset.x : 0;
|
|
6783
8905
|
const oy = layer.type === "pixel" ? layer.offset.y : 0;
|
|
@@ -6813,7 +8935,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6813
8935
|
this.state.layers = _chunkH543GD6Tcjs.mapLayer.call(void 0, this.state.layers, target.id, (l) => {
|
|
6814
8936
|
const next = { ...l };
|
|
6815
8937
|
if (isDefaultDepthMask(merged)) {
|
|
6816
|
-
if (_optionalChain([next, 'access',
|
|
8938
|
+
if (_optionalChain([next, 'access', _193 => _193.mask, 'optionalAccess', _194 => _194.source])) delete next.mask;
|
|
6817
8939
|
} else next.mask = depthRasterMask(merged);
|
|
6818
8940
|
return next;
|
|
6819
8941
|
});
|
|
@@ -6823,7 +8945,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6823
8945
|
resetDepthMask() {
|
|
6824
8946
|
this.recordHistory();
|
|
6825
8947
|
const target = this.developLayer();
|
|
6826
|
-
if (_optionalChain([target, 'optionalAccess',
|
|
8948
|
+
if (_optionalChain([target, 'optionalAccess', _195 => _195.mask, 'optionalAccess', _196 => _196.source])) {
|
|
6827
8949
|
this.state.layers = _chunkH543GD6Tcjs.mapLayer.call(void 0, this.state.layers, target.id, (l) => {
|
|
6828
8950
|
const next = { ...l };
|
|
6829
8951
|
delete next.mask;
|
|
@@ -6845,7 +8967,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6845
8967
|
const fullAnnotation = { ...annotation, id };
|
|
6846
8968
|
const layer = annotationLayerFor(fullAnnotation);
|
|
6847
8969
|
const loc = placement.aboveId ? _chunkH543GD6Tcjs.findLayer.call(void 0, this.state.layers, placement.aboveId) : null;
|
|
6848
|
-
this.state.layers = loc ? _chunkH543GD6Tcjs.insertLayer.call(void 0, this.state.layers, layer, _nullishCoalesce(_optionalChain([loc, 'access',
|
|
8970
|
+
this.state.layers = loc ? _chunkH543GD6Tcjs.insertLayer.call(void 0, this.state.layers, layer, _nullishCoalesce(_optionalChain([loc, 'access', _197 => _197.parent, 'optionalAccess', _198 => _198.id]), () => ( null)), loc.index + 1) : _chunkH543GD6Tcjs.insertLayer.call(void 0, this.state.layers, layer, null);
|
|
6849
8971
|
this.state.selectedAnnotationId = id;
|
|
6850
8972
|
this.notify();
|
|
6851
8973
|
return id;
|
|
@@ -6914,8 +9036,24 @@ var ImageEditorController = (_class5 = class {
|
|
|
6914
9036
|
this.notify();
|
|
6915
9037
|
}
|
|
6916
9038
|
// --- Rendering & Export ---
|
|
6917
|
-
|
|
9039
|
+
__init48() {this.blankSource = null}
|
|
9040
|
+
/**
|
|
9041
|
+
* What the renderer draws from: the source image, or, for a document without one (an opened
|
|
9042
|
+
* PSD, a v3 document loaded on its own), a transparent canvas of the document size, since every
|
|
9043
|
+
* pixel then comes from the layers. `null` when there is nothing to draw.
|
|
9044
|
+
*/
|
|
9045
|
+
drawSource() {
|
|
6918
9046
|
const source = this.imageElement || this.state.sourceUrl;
|
|
9047
|
+
if (source) return source;
|
|
9048
|
+
if (!this.isSourceless()) return null;
|
|
9049
|
+
const { width, height } = this.naturalSize;
|
|
9050
|
+
if (!this.blankSource || this.blankSource.width !== width || this.blankSource.height !== height) {
|
|
9051
|
+
this.blankSource = this.renderer.createCanvas(width, height);
|
|
9052
|
+
}
|
|
9053
|
+
return this.blankSource;
|
|
9054
|
+
}
|
|
9055
|
+
async render(targetCanvas, options) {
|
|
9056
|
+
const source = this.drawSource();
|
|
6919
9057
|
if (!source) return;
|
|
6920
9058
|
this.syncViews();
|
|
6921
9059
|
const dirty = this.pendingDirty;
|
|
@@ -6926,16 +9064,16 @@ var ImageEditorController = (_class5 = class {
|
|
|
6926
9064
|
dirty: dirty === "all" ? void 0 : dirty,
|
|
6927
9065
|
checkpointLayerId: this.state.activeLayerId
|
|
6928
9066
|
});
|
|
6929
|
-
} catch (
|
|
9067
|
+
} catch (e23) {
|
|
6930
9068
|
}
|
|
6931
9069
|
}
|
|
6932
9070
|
async renderExport(options) {
|
|
6933
|
-
const source = this.
|
|
9071
|
+
const source = this.drawSource();
|
|
6934
9072
|
if (!source) {
|
|
6935
9073
|
return this.renderer.createCanvas(1, 1);
|
|
6936
9074
|
}
|
|
6937
9075
|
this.syncViews();
|
|
6938
|
-
if (_optionalChain([options, 'optionalAccess',
|
|
9076
|
+
if (_optionalChain([options, 'optionalAccess', _199 => _199.layerIds])) {
|
|
6939
9077
|
const keep = new Set(options.layerIds);
|
|
6940
9078
|
const layers = _chunkH543GD6Tcjs.flattenLayers.call(void 0, this.state.layers).filter((l) => keep.has(l.id));
|
|
6941
9079
|
return this.renderer.renderExport(source, { ...this.state, layers }, options);
|
|
@@ -6949,7 +9087,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
6949
9087
|
* Returns `null` when no image is loaded.
|
|
6950
9088
|
*/
|
|
6951
9089
|
async renderSourceView(options = {}) {
|
|
6952
|
-
const source = this.
|
|
9090
|
+
const source = this.drawSource();
|
|
6953
9091
|
if (!source) return null;
|
|
6954
9092
|
this.syncViews();
|
|
6955
9093
|
const { width, height } = this.state.imageDimensions;
|
|
@@ -7021,23 +9159,270 @@ var ImageEditorController = (_class5 = class {
|
|
|
7021
9159
|
ctx.drawImage(img, 0, 0, width, height);
|
|
7022
9160
|
return canvas;
|
|
7023
9161
|
}
|
|
9162
|
+
/**
|
|
9163
|
+
* The image an AI hook should edit: the source (`toSourceDataURL`) when results replace the
|
|
9164
|
+
* Background, or the composite of the layers without annotations, in the source frame, when
|
|
9165
|
+
* they go to a new layer or mask (see `applyInpaintedImage`).
|
|
9166
|
+
*/
|
|
9167
|
+
async toAIInputDataURL(options = {}) {
|
|
9168
|
+
const target = _nullishCoalesce(options.target, () => ( this.defaultAITarget()));
|
|
9169
|
+
if (target === "replace") return this.toSourceDataURL();
|
|
9170
|
+
const canvas = await this.renderSourceView({ includeAnnotations: false });
|
|
9171
|
+
return canvas ? canvas.toDataURL("image/png") : this.toSourceDataURL();
|
|
9172
|
+
}
|
|
7024
9173
|
async toSourceDataURL(options = {}) {
|
|
7025
9174
|
const canvas = await this.renderSource();
|
|
7026
9175
|
return canvas.toDataURL(options.format || "image/png", _nullishCoalesce(options.quality, () => ( 0.92)));
|
|
7027
9176
|
}
|
|
7028
9177
|
/**
|
|
7029
|
-
*
|
|
7030
|
-
*
|
|
9178
|
+
* Whether AI results go to layers: the document has more than one pixel layer or group (adjustment
|
|
9179
|
+
* and annotation layers are edits of the image, not images of their own).
|
|
9180
|
+
*/
|
|
9181
|
+
/** `new-layer` in multi-layer documents and documents without a source image, else `replace`. */
|
|
9182
|
+
defaultAITarget() {
|
|
9183
|
+
return this.isMultiLayer || this.isSourceless() ? "new-layer" : "replace";
|
|
9184
|
+
}
|
|
9185
|
+
/** No source image, and no layer reading one (an opened PSD): the layers are the whole document. */
|
|
9186
|
+
isSourceless() {
|
|
9187
|
+
if (this.imageElement || this.state.sourceUrl || !this.state.layers.length) return false;
|
|
9188
|
+
return !_chunkH543GD6Tcjs.flattenLayers.call(void 0, this.state.layers).some((l) => l.type === "pixel" && l.source === "document");
|
|
9189
|
+
}
|
|
9190
|
+
get isMultiLayer() {
|
|
9191
|
+
return _chunkH543GD6Tcjs.flattenLayers.call(void 0, this.state.layers).filter((l) => l.type === "pixel" || l.type === "group").length > 1;
|
|
9192
|
+
}
|
|
9193
|
+
/**
|
|
9194
|
+
* Applies an inpainted result (natural image space, see `toSourceDataURL`) as ONE undoable step.
|
|
9195
|
+
* In a document with several layers (see `isMultiLayer`), or with `target: 'new-layer'`, the
|
|
9196
|
+
* result goes to a new pixel layer above the active layer, limited to the selection. Otherwise
|
|
9197
|
+
* (`target: 'replace'`, the single-layer default) it replaces the Background's pixels and clears
|
|
9198
|
+
* the mask annotations, as before. Resolves to the new layer's id in new-layer mode.
|
|
7031
9199
|
*/
|
|
7032
|
-
async applyInpaintedImage(newDataUrl) {
|
|
7033
|
-
|
|
9200
|
+
async applyInpaintedImage(newDataUrl, options = {}) {
|
|
9201
|
+
if ((_nullishCoalesce(options.target, () => ( this.defaultAITarget()))) === "replace") {
|
|
9202
|
+
await this.replaceSource(newDataUrl, true);
|
|
9203
|
+
return;
|
|
9204
|
+
}
|
|
9205
|
+
const { width, height } = this.naturalSize;
|
|
9206
|
+
let px = await this.decodeImage(newDataUrl);
|
|
9207
|
+
if (px.width !== width || px.height !== height) px = resizePixels(px, width, height);
|
|
9208
|
+
const data = new Uint8ClampedArray(px.data);
|
|
9209
|
+
const sel = _optionalChain([this, 'access', _200 => _200.state, 'access', _201 => _201.selection, 'optionalAccess', _202 => _202.bounds]) ? this.state.selection : null;
|
|
9210
|
+
if (sel) for (let p = 0, i = 3; p < width * height; p++, i += 4) data[i] = Math.round(data[i] * sel.data[p] / 255);
|
|
9211
|
+
return this.addPixelLayer({ name: "Inpaint", pixels: { width, height, data } });
|
|
7034
9212
|
}
|
|
7035
9213
|
/**
|
|
7036
|
-
*
|
|
7037
|
-
*
|
|
9214
|
+
* Applies a background-removed result as ONE undoable step. In a document with several layers
|
|
9215
|
+
* (or with `target: 'new-layer'`) the result's alpha becomes the mask of the active pixel layer
|
|
9216
|
+
* (or the Background), replacing its mask. Otherwise (`target: 'replace'`, the single-layer
|
|
9217
|
+
* default) it replaces the Background's pixels; crop and annotations are kept (rescaled if the
|
|
9218
|
+
* new image has different dimensions). Resolves to the masked layer's id in mask mode.
|
|
7038
9219
|
*/
|
|
7039
|
-
async applyBackgroundRemovedImage(newDataUrl) {
|
|
7040
|
-
|
|
9220
|
+
async applyBackgroundRemovedImage(newDataUrl, options = {}) {
|
|
9221
|
+
if ((_nullishCoalesce(options.target, () => ( this.defaultAITarget()))) === "replace") {
|
|
9222
|
+
await this.replaceSource(newDataUrl, false);
|
|
9223
|
+
return;
|
|
9224
|
+
}
|
|
9225
|
+
const target = this.developLayer();
|
|
9226
|
+
if (!target) throw new LayerOperationError("There is no pixel layer to mask.");
|
|
9227
|
+
requireUnlocked(target, "all", "mask it");
|
|
9228
|
+
const { width, height } = this.naturalSize;
|
|
9229
|
+
let px = await this.decodeImage(newDataUrl);
|
|
9230
|
+
if (px.width !== width || px.height !== height) px = resizePixels(px, width, height);
|
|
9231
|
+
const alpha = new Uint8ClampedArray(width * height);
|
|
9232
|
+
for (let p = 0; p < alpha.length; p++) alpha[p] = px.data[p * 4 + 3];
|
|
9233
|
+
let surface = _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data: alpha }, 1, 0, 0, 0);
|
|
9234
|
+
if (target.offset.x || target.offset.y) surface = _chunkZOOEX3WTcjs.translateSurface.call(void 0, surface, -target.offset.x, -target.offset.y);
|
|
9235
|
+
this.commitLayers(setLayerMask(this.state.layers, target.id, { surface, defaultValue: 0 }));
|
|
9236
|
+
return target.id;
|
|
9237
|
+
}
|
|
9238
|
+
/**
|
|
9239
|
+
* Rasterize Layer: an annotation layer becomes a pixel layer with the same id, name and
|
|
9240
|
+
* properties (needs a canvas), and a pixel layer's filters are baked into its pixels. One undo
|
|
9241
|
+
* step. Returns the layer id.
|
|
9242
|
+
*/
|
|
9243
|
+
async rasterizeLayer(id) {
|
|
9244
|
+
const layer = requireLayer(this.state.layers, id).layer;
|
|
9245
|
+
requireUnlocked(layer, "all", "rasterize it");
|
|
9246
|
+
const { width, height } = this.naturalSize;
|
|
9247
|
+
const canvas = { x: 0, y: 0, width, height };
|
|
9248
|
+
let next;
|
|
9249
|
+
if (layer.type === "annotation") {
|
|
9250
|
+
const blend = layer.blend === "normal" && layer.annotation.blend ? layer.annotation.blend : layer.blend;
|
|
9251
|
+
const content = { ...layer, visible: true, opacity: 1, blend: "normal", annotation: { ...layer.annotation, blend: void 0 } };
|
|
9252
|
+
delete content.mask;
|
|
9253
|
+
delete content.clipped;
|
|
9254
|
+
const surface = await this.compositeToSurface([content], this.paintBounds(layer));
|
|
9255
|
+
next = { type: "pixel", id: layer.id, name: layer.name, visible: layer.visible, opacity: layer.opacity, blend, surface, offset: { x: 0, y: 0 } };
|
|
9256
|
+
if (layer.clipped) next.clipped = true;
|
|
9257
|
+
if (layer.mask) next.mask = layer.mask;
|
|
9258
|
+
if (layer.locks) next.locks = layer.locks;
|
|
9259
|
+
if (this.state.selectedAnnotationId === layer.annotation.id) this.state.selectedAnnotationId = null;
|
|
9260
|
+
} else if (layer.type === "pixel") {
|
|
9261
|
+
if (!_optionalChain([layer, 'access', _203 => _203.filters, 'optionalAccess', _204 => _204.length])) throw new LayerOperationError(`Layer "${layer.name || id}" is already pixels with no filters to bake.`);
|
|
9262
|
+
requireUnlocked(layer, "pixels", "rasterize it");
|
|
9263
|
+
const spatial = layer.filters.some((f) => f.enabled && f.kind === "blur");
|
|
9264
|
+
const content = { ...layer, visible: true, opacity: 1, blend: "normal" };
|
|
9265
|
+
delete content.mask;
|
|
9266
|
+
delete content.clipped;
|
|
9267
|
+
delete content.fillOpacity;
|
|
9268
|
+
const rect = spatial ? canvas : _nullishCoalesce(this.getLayerBounds(id), () => ( canvas));
|
|
9269
|
+
const surface = await this.compositeToSurface([content], rect);
|
|
9270
|
+
next = { ...layer, surface, offset: { x: 0, y: 0 } };
|
|
9271
|
+
delete next.filters;
|
|
9272
|
+
delete next.source;
|
|
9273
|
+
if (layer.mask && (layer.offset.x || layer.offset.y)) {
|
|
9274
|
+
next.mask = { ...layer.mask, surface: _chunkZOOEX3WTcjs.translateSurface.call(void 0, layer.mask.surface, layer.offset.x, layer.offset.y) };
|
|
9275
|
+
}
|
|
9276
|
+
} else {
|
|
9277
|
+
throw new LayerOperationError(`Only annotation layers and pixel layers with filters rasterize; "${layer.name || id}" is a ${layer.type} layer. Merge it down or flatten instead.`);
|
|
9278
|
+
}
|
|
9279
|
+
this.commitLayers(_chunkH543GD6Tcjs.mapLayer.call(void 0, this.state.layers, id, () => next));
|
|
9280
|
+
return id;
|
|
9281
|
+
}
|
|
9282
|
+
// --- PSD ---
|
|
9283
|
+
/** Pixels per inch of the last opened PSD (written back by `toPsd`). */
|
|
9284
|
+
|
|
9285
|
+
/**
|
|
9286
|
+
* Opens PSD / PSB bytes as the document (one undo step): the layers replace the stack and the
|
|
9287
|
+
* document has no source image afterwards (every pixel comes from the layers). What the model
|
|
9288
|
+
* cannot hold is approximated or left out; `warnings` says what, naming the layers.
|
|
9289
|
+
* Throws `PsdError` for files that cannot be read at all.
|
|
9290
|
+
*/
|
|
9291
|
+
loadPsd(bytes) {
|
|
9292
|
+
const result = importPsd(bytes, { newId: () => newLayerId() });
|
|
9293
|
+
this.recordHistory();
|
|
9294
|
+
const s = this.state;
|
|
9295
|
+
this.imageElement = null;
|
|
9296
|
+
s.sourceUrl = null;
|
|
9297
|
+
s.imageDimensions = { width: result.width, height: result.height };
|
|
9298
|
+
if (!this.samplePixelsOverride) this.samplePixels = null;
|
|
9299
|
+
s.layers = result.layers;
|
|
9300
|
+
s.crop = null;
|
|
9301
|
+
s.transform = { ...DEFAULT_TRANSFORM_VALUES };
|
|
9302
|
+
s.outputOpacity = 1;
|
|
9303
|
+
delete s.legacyOutputBlur;
|
|
9304
|
+
s.selection = null;
|
|
9305
|
+
s.selectedAnnotationId = null;
|
|
9306
|
+
const pixels = _chunkH543GD6Tcjs.flattenLayers.call(void 0, result.layers).filter((l) => l.type === "pixel");
|
|
9307
|
+
s.activeLayerId = pixels.length ? pixels[pixels.length - 1].id : null;
|
|
9308
|
+
s.activeTarget = "pixels";
|
|
9309
|
+
this.psdResolution = result.resolution;
|
|
9310
|
+
this.lastLoadProblems = result.warnings;
|
|
9311
|
+
this.notify();
|
|
9312
|
+
return {
|
|
9313
|
+
layerIds: _chunkH543GD6Tcjs.flattenLayers.call(void 0, result.layers).map((l) => l.id),
|
|
9314
|
+
warnings: result.warnings,
|
|
9315
|
+
width: result.width,
|
|
9316
|
+
height: result.height,
|
|
9317
|
+
summary: result.summary
|
|
9318
|
+
};
|
|
9319
|
+
}
|
|
9320
|
+
/**
|
|
9321
|
+
* The document as an 8-bit RGB PSD (PSB above 30 000 px) with real layers, groups, adjustment
|
|
9322
|
+
* layers and masks, in the source frame. Layer filters and parametric (depth) masks are baked
|
|
9323
|
+
* into pixels and masks, annotation layers are rasterized (in a browser; elsewhere they are left
|
|
9324
|
+
* out), and the merged image is our composite. `warnings` lists every such change.
|
|
9325
|
+
*/
|
|
9326
|
+
async toPsd() {
|
|
9327
|
+
const { width, height } = this.naturalSize;
|
|
9328
|
+
const canvas = { x: 0, y: 0, width, height };
|
|
9329
|
+
const warnings = [];
|
|
9330
|
+
const note = /* @__PURE__ */ new Map();
|
|
9331
|
+
const add = (msg, name) => note.set(msg, [..._nullishCoalesce(note.get(msg), () => ( [])), name]);
|
|
9332
|
+
const canRasterize = this.renderer.canRasterize();
|
|
9333
|
+
await this.renderer.prepareLayerAssets(this.state.layers, width, height);
|
|
9334
|
+
const sources = this.renderer.compositorSources(width, height);
|
|
9335
|
+
const compositor = new LayerCompositor();
|
|
9336
|
+
const bakeMask = (layer) => {
|
|
9337
|
+
const mask = layer.mask;
|
|
9338
|
+
if (!_optionalChain([mask, 'optionalAccess', _205 => _205.source])) return mask;
|
|
9339
|
+
add("Parametric (depth) masks were baked into pixel masks", layer.name);
|
|
9340
|
+
const plain3 = { ...layer, mask: { ...mask, density: 1, feather: 0, enabled: true } };
|
|
9341
|
+
const ox = layer.type === "pixel" ? layer.offset.x : 0;
|
|
9342
|
+
const oy = layer.type === "pixel" ? layer.offset.y : 0;
|
|
9343
|
+
const coverage = compositor.maskCoverage(plain3, canvas, sources);
|
|
9344
|
+
const bytes = new Uint8ClampedArray(width * height);
|
|
9345
|
+
if (coverage) for (let i = 0; i < bytes.length; i++) bytes[i] = Math.round(coverage[i] * 255);
|
|
9346
|
+
else bytes.fill(255);
|
|
9347
|
+
const baked = { surface: _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data: bytes }, 1, -ox, -oy), defaultValue: 0 };
|
|
9348
|
+
if (mask.density !== void 0 && mask.density < 1) baked.density = mask.density;
|
|
9349
|
+
if (mask.feather) baked.feather = mask.feather;
|
|
9350
|
+
if (mask.enabled === false) baked.enabled = false;
|
|
9351
|
+
return baked;
|
|
9352
|
+
};
|
|
9353
|
+
const prepare = async (layer) => {
|
|
9354
|
+
if (layer.type === "group") {
|
|
9355
|
+
const children = [];
|
|
9356
|
+
for (const c of layer.children) {
|
|
9357
|
+
const p = await prepare(c);
|
|
9358
|
+
if (p) children.push(p);
|
|
9359
|
+
}
|
|
9360
|
+
return { ...layer, children, mask: bakeMask(layer) };
|
|
9361
|
+
}
|
|
9362
|
+
if (layer.type === "adjustment") return { ...layer, mask: bakeMask(layer) };
|
|
9363
|
+
if (layer.type === "annotation") {
|
|
9364
|
+
if (!canRasterize) {
|
|
9365
|
+
add("Annotation layers need a canvas (a browser) to rasterize and were left out", layer.name);
|
|
9366
|
+
return null;
|
|
9367
|
+
}
|
|
9368
|
+
add("Annotation layers were written as pixel layers", layer.name);
|
|
9369
|
+
const blend = layer.blend === "normal" && layer.annotation.blend ? layer.annotation.blend : layer.blend;
|
|
9370
|
+
const content = { ...layer, visible: true, opacity: 1, blend: "normal", annotation: { ...layer.annotation, blend: void 0 } };
|
|
9371
|
+
delete content.mask;
|
|
9372
|
+
delete content.clipped;
|
|
9373
|
+
const data = compositor.composite([content], canvas, sources);
|
|
9374
|
+
const out2 = {
|
|
9375
|
+
type: "pixel",
|
|
9376
|
+
id: layer.id,
|
|
9377
|
+
name: layer.name,
|
|
9378
|
+
visible: layer.visible,
|
|
9379
|
+
opacity: layer.opacity,
|
|
9380
|
+
blend,
|
|
9381
|
+
surface: _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data }, 4),
|
|
9382
|
+
offset: { x: 0, y: 0 }
|
|
9383
|
+
};
|
|
9384
|
+
if (layer.clipped) out2.clipped = true;
|
|
9385
|
+
if (layer.locks) out2.locks = layer.locks;
|
|
9386
|
+
const mask2 = bakeMask(layer);
|
|
9387
|
+
if (mask2) out2.mask = mask2;
|
|
9388
|
+
return out2;
|
|
9389
|
+
}
|
|
9390
|
+
let out = { ...layer };
|
|
9391
|
+
if (layer.source === "document") {
|
|
9392
|
+
out.surface = this.surfaceOf(layer);
|
|
9393
|
+
delete out.source;
|
|
9394
|
+
}
|
|
9395
|
+
const active = _nullishCoalesce(_optionalChain([layer, 'access', _206 => _206.filters, 'optionalAccess', _207 => _207.filter, 'call', _208 => _208(isActiveFilter)]), () => ( []));
|
|
9396
|
+
if (active.length) {
|
|
9397
|
+
add("Layer filters (develop, blur) were baked into the pixels", layer.name);
|
|
9398
|
+
const content = { ...out, visible: true, opacity: 1, blend: "normal" };
|
|
9399
|
+
delete content.mask;
|
|
9400
|
+
delete content.clipped;
|
|
9401
|
+
delete content.fillOpacity;
|
|
9402
|
+
const data = compositor.composite([content], canvas, sources);
|
|
9403
|
+
out = { ...out, surface: _chunkZOOEX3WTcjs.surfaceFromPixels.call(void 0, { width, height, data }, 4, -layer.offset.x, -layer.offset.y) };
|
|
9404
|
+
}
|
|
9405
|
+
if (_optionalChain([layer, 'access', _209 => _209.filters, 'optionalAccess', _210 => _210.some, 'call', _211 => _211((f) => !f.enabled)])) add("Disabled layer filters were left out", layer.name);
|
|
9406
|
+
delete out.filters;
|
|
9407
|
+
const mask = bakeMask(layer);
|
|
9408
|
+
if (mask) out.mask = mask;
|
|
9409
|
+
else delete out.mask;
|
|
9410
|
+
return out;
|
|
9411
|
+
};
|
|
9412
|
+
const prepared = [];
|
|
9413
|
+
for (const l of this.state.layers) {
|
|
9414
|
+
const p = await prepare(l);
|
|
9415
|
+
if (p) prepared.push(p);
|
|
9416
|
+
}
|
|
9417
|
+
const s = this.state;
|
|
9418
|
+
if (s.crop) warnings.push("The crop is not applied; the PSD is the uncropped document.");
|
|
9419
|
+
if (s.transform.rotate || s.transform.flipH || s.transform.flipV) warnings.push("Rotation and flips are not applied; the PSD is in the source orientation.");
|
|
9420
|
+
if (s.outputOpacity < 1) warnings.push("The document opacity is not written; layers keep their own opacity.");
|
|
9421
|
+
if (s.legacyOutputBlur) warnings.push("The document-level blur of an old document is not written.");
|
|
9422
|
+
for (const [msg, names] of note) warnings.push(`${msg} (${names.length === 1 ? "layer" : "layers"} ${names.map((n) => `"${n}"`).join(", ")}).`);
|
|
9423
|
+
const merged = compositor.composite(prepared, canvas, { ...sources, version: `psd:${Date.now()}` });
|
|
9424
|
+
const result = exportPsd({ width, height, layers: prepared, merged, resolution: this.psdResolution });
|
|
9425
|
+
return { bytes: result.bytes, warnings, psb: result.psb, width, height };
|
|
7041
9426
|
}
|
|
7042
9427
|
async replaceSource(src, clearAnnotations) {
|
|
7043
9428
|
const next = await this.resolveSource(src);
|
|
@@ -7084,17 +9469,26 @@ var ImageEditorController = (_class5 = class {
|
|
|
7084
9469
|
this.state.layers = layers;
|
|
7085
9470
|
this.notify();
|
|
7086
9471
|
}
|
|
7087
|
-
|
|
9472
|
+
toJSON(options) {
|
|
9473
|
+
const out = this.serializeState();
|
|
9474
|
+
if (_optionalChain([this, 'access', _212 => _212.state, 'access', _213 => _213.selection, 'optionalAccess', _214 => _214.bounds])) out.selection = serializeSelection(this.state.selection);
|
|
9475
|
+
if (!options || out.version !== LAYERED_SCHEMA_VERSION) return options ? Promise.resolve(out) : out;
|
|
9476
|
+
return serializeLayersExternal(this.state.layers, options.store).then(({ layers, assets }) => ({ ...out, layers, assets }));
|
|
9477
|
+
}
|
|
7088
9478
|
/**
|
|
7089
|
-
*
|
|
7090
|
-
*
|
|
7091
|
-
*
|
|
7092
|
-
* assets. `selection` is included (run-length encoded) only when something is selected.
|
|
9479
|
+
* Loads a stored state whose v3 assets may live in an asset store (references other than data
|
|
9480
|
+
* URLs are fetched with `store.get`), as one undo step. Assets that cannot be fetched are left
|
|
9481
|
+
* out and listed in `lastLoadProblems`.
|
|
7093
9482
|
*/
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
9483
|
+
async loadJSONAsync(data, options = {}) {
|
|
9484
|
+
if (data.version !== LAYERED_SCHEMA_VERSION || !data.assets) {
|
|
9485
|
+
this.loadJSON(data);
|
|
9486
|
+
return;
|
|
9487
|
+
}
|
|
9488
|
+
const problems = [];
|
|
9489
|
+
const assets = await resolveExternalAssets(data.assets, options.store, problems);
|
|
9490
|
+
this.loadJSON({ ...data, assets });
|
|
9491
|
+
this.lastLoadProblems = [...problems, ...this.lastLoadProblems];
|
|
7098
9492
|
}
|
|
7099
9493
|
/** Loads a stored state of any version (one undo step). */
|
|
7100
9494
|
loadJSON(data) {
|
|
@@ -7104,7 +9498,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
7104
9498
|
if (data.selection) {
|
|
7105
9499
|
try {
|
|
7106
9500
|
selection = normalizeSelection(deserializeSelection(data.selection));
|
|
7107
|
-
} catch (
|
|
9501
|
+
} catch (e24) {
|
|
7108
9502
|
selection = null;
|
|
7109
9503
|
}
|
|
7110
9504
|
}
|
|
@@ -7113,7 +9507,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
7113
9507
|
this.notify();
|
|
7114
9508
|
}
|
|
7115
9509
|
/** Problems found by the last `loadJSON` / `initialState` of a v3 document (unreadable layers or assets). */
|
|
7116
|
-
|
|
9510
|
+
__init49() {this.lastLoadProblems = []}
|
|
7117
9511
|
applyStored(raw) {
|
|
7118
9512
|
const s = this.state;
|
|
7119
9513
|
const data = migrateSerializedImageEditorState(raw);
|
|
@@ -7153,7 +9547,7 @@ var ImageEditorController = (_class5 = class {
|
|
|
7153
9547
|
if (view.exact) {
|
|
7154
9548
|
return {
|
|
7155
9549
|
// States without adjustment layers keep schema 1, so they round-trip unchanged.
|
|
7156
|
-
version: _optionalChain([view, 'access',
|
|
9550
|
+
version: _optionalChain([view, 'access', _215 => _215.adjustments, 'access', _216 => _216.layers, 'optionalAccess', _217 => _217.length]) ? 2 : 1,
|
|
7157
9551
|
crop: this.state.crop ? { ...this.state.crop } : null,
|
|
7158
9552
|
transform: { ...this.state.transform },
|
|
7159
9553
|
adjustments: serializeAdjustments(view.adjustments),
|
|
@@ -7179,10 +9573,10 @@ var ImageEditorController = (_class5 = class {
|
|
|
7179
9573
|
if (this.state.legacyOutputBlur !== void 0) out.legacyOutputBlur = this.state.legacyOutputBlur;
|
|
7180
9574
|
return out;
|
|
7181
9575
|
}
|
|
7182
|
-
},
|
|
9576
|
+
}, _class7);
|
|
7183
9577
|
function serializeAdjustments(adjustments) {
|
|
7184
9578
|
const out = { ...adjustments };
|
|
7185
|
-
if (_optionalChain([out, 'access',
|
|
9579
|
+
if (_optionalChain([out, 'access', _218 => _218.layers, 'optionalAccess', _219 => _219.length])) out.layers = JSON.parse(JSON.stringify(out.layers));
|
|
7186
9580
|
else delete out.layers;
|
|
7187
9581
|
if (normalizeProcessVersion(out.process) === LEGACY_PROCESS_VERSION) {
|
|
7188
9582
|
delete out.process;
|
|
@@ -7218,11 +9612,11 @@ function withDevelop(layer, partial) {
|
|
|
7218
9612
|
return { ...layer, filters };
|
|
7219
9613
|
}
|
|
7220
9614
|
function withBlur(layer, radius) {
|
|
7221
|
-
const existing = _optionalChain([layer, 'access',
|
|
9615
|
+
const existing = _optionalChain([layer, 'access', _220 => _220.filters, 'optionalAccess', _221 => _221.find, 'call', _222 => _222((f) => f.kind === "blur")]);
|
|
7222
9616
|
const filters = (_nullishCoalesce(layer.filters, () => ( []))).filter((f) => f.kind !== "blur");
|
|
7223
9617
|
if (radius > 0) {
|
|
7224
9618
|
filters.push({
|
|
7225
|
-
id: _nullishCoalesce(_optionalChain([existing, 'optionalAccess',
|
|
9619
|
+
id: _nullishCoalesce(_optionalChain([existing, 'optionalAccess', _223 => _223.id]), () => ( (layer.source === "document" ? BLUR_FILTER_ID : newLayerId("flt")))),
|
|
7226
9620
|
kind: "blur",
|
|
7227
9621
|
enabled: true,
|
|
7228
9622
|
radius
|
|
@@ -7309,6 +9703,43 @@ function collectStateTiles(layers, into) {
|
|
|
7309
9703
|
if (l.mask && !l.mask.source) _chunkZOOEX3WTcjs.collectTiles.call(void 0, l.mask.surface, into);
|
|
7310
9704
|
}
|
|
7311
9705
|
}
|
|
9706
|
+
function pixelsOnly(layers) {
|
|
9707
|
+
const out = [];
|
|
9708
|
+
for (const l of layers) {
|
|
9709
|
+
if (l.type === "adjustment") continue;
|
|
9710
|
+
if (l.type === "group") out.push({ ...l, children: pixelsOnly(l.children) });
|
|
9711
|
+
else if (l.type === "pixel" && _optionalChain([l, 'access', _224 => _224.filters, 'optionalAccess', _225 => _225.length])) {
|
|
9712
|
+
const p = { ...l };
|
|
9713
|
+
delete p.filters;
|
|
9714
|
+
out.push(p);
|
|
9715
|
+
} else out.push(l);
|
|
9716
|
+
}
|
|
9717
|
+
return out;
|
|
9718
|
+
}
|
|
9719
|
+
function resizePixels(px, width, height) {
|
|
9720
|
+
const src = px.data;
|
|
9721
|
+
const out = new Uint8ClampedArray(width * height * 4);
|
|
9722
|
+
const kx = px.width / width;
|
|
9723
|
+
const ky = px.height / height;
|
|
9724
|
+
for (let y = 0; y < height; y++) {
|
|
9725
|
+
const fy = Math.min(px.height - 1, Math.max(0, (y + 0.5) * ky - 0.5));
|
|
9726
|
+
const y0 = Math.floor(fy);
|
|
9727
|
+
const y1 = Math.min(px.height - 1, y0 + 1);
|
|
9728
|
+
const ty = fy - y0;
|
|
9729
|
+
for (let x = 0; x < width; x++) {
|
|
9730
|
+
const fx = Math.min(px.width - 1, Math.max(0, (x + 0.5) * kx - 0.5));
|
|
9731
|
+
const x0 = Math.floor(fx);
|
|
9732
|
+
const x1 = Math.min(px.width - 1, x0 + 1);
|
|
9733
|
+
const tx = fx - x0;
|
|
9734
|
+
for (let c = 0; c < 4; c++) {
|
|
9735
|
+
const a = src[(y0 * px.width + x0) * 4 + c] * (1 - tx) + src[(y0 * px.width + x1) * 4 + c] * tx;
|
|
9736
|
+
const b = src[(y1 * px.width + x0) * 4 + c] * (1 - tx) + src[(y1 * px.width + x1) * 4 + c] * tx;
|
|
9737
|
+
out[(y * width + x) * 4 + c] = a * (1 - ty) + b * ty;
|
|
9738
|
+
}
|
|
9739
|
+
}
|
|
9740
|
+
}
|
|
9741
|
+
return { width, height, data: out };
|
|
9742
|
+
}
|
|
7312
9743
|
function withoutAnnotations(layers) {
|
|
7313
9744
|
const out = [];
|
|
7314
9745
|
for (const l of layers) {
|
|
@@ -7331,11 +9762,11 @@ function parseColor(value) {
|
|
|
7331
9762
|
const n = (i) => parseInt(hex.slice(i, i + 2), 16);
|
|
7332
9763
|
return [n(0), n(2), n(4), hex.length === 8 ? n(6) : 255];
|
|
7333
9764
|
}
|
|
7334
|
-
function
|
|
9765
|
+
function toHex2(c) {
|
|
7335
9766
|
return "#" + [c[0], c[1], c[2]].map((v) => Math.round(v).toString(16).padStart(2, "0")).join("");
|
|
7336
9767
|
}
|
|
7337
9768
|
function normalizeSelection(mask) {
|
|
7338
|
-
return _optionalChain([mask, 'optionalAccess',
|
|
9769
|
+
return _optionalChain([mask, 'optionalAccess', _226 => _226.bounds]) ? mask : null;
|
|
7339
9770
|
}
|
|
7340
9771
|
function sameSelection(a, b) {
|
|
7341
9772
|
if (a.width !== b.width || a.height !== b.height) return false;
|
|
@@ -7440,7 +9871,7 @@ function loadImageEditorDocument(input) {
|
|
|
7440
9871
|
if (typeof input === "string") {
|
|
7441
9872
|
try {
|
|
7442
9873
|
parsed = JSON.parse(input);
|
|
7443
|
-
} catch (
|
|
9874
|
+
} catch (e25) {
|
|
7444
9875
|
parsed = input;
|
|
7445
9876
|
}
|
|
7446
9877
|
}
|
|
@@ -7496,7 +9927,7 @@ function loadImageEditorDocument(input) {
|
|
|
7496
9927
|
}
|
|
7497
9928
|
const state = { version: 1, ...result.value };
|
|
7498
9929
|
if (isV2) {
|
|
7499
|
-
if (_optionalChain([state, 'access',
|
|
9930
|
+
if (_optionalChain([state, 'access', _227 => _227.adjustments, 'access', _228 => _228.layers, 'optionalAccess', _229 => _229.length])) state.version = 2;
|
|
7500
9931
|
result.report.version = 2;
|
|
7501
9932
|
}
|
|
7502
9933
|
if (state.selection === void 0) delete state.selection;
|
|
@@ -7622,7 +10053,7 @@ var tone = (prefix, label) => [
|
|
|
7622
10053
|
decimals: 0,
|
|
7623
10054
|
track: { kind: "gradient", from, to }
|
|
7624
10055
|
}));
|
|
7625
|
-
var
|
|
10056
|
+
var levelsRecord2 = (ch, label) => [
|
|
7626
10057
|
{ id: `${ch}.inBlack`, label: `${label} input black`, section: "layer", min: 0, max: 253, step: 1, default: 0, decimals: 0, track: plain },
|
|
7627
10058
|
{ id: `${ch}.gamma`, label: `${label} gamma`, section: "layer", min: 0.1, max: 9.99, step: 0.01, default: 1, decimals: 2, track: plain },
|
|
7628
10059
|
{ id: `${ch}.inWhite`, label: `${label} input white`, section: "layer", min: 2, max: 255, step: 1, default: 255, decimals: 0, track: plain },
|
|
@@ -7633,10 +10064,10 @@ var RANGE_NAMES = ["Reds", "Yellows", "Greens", "Cyans", "Blues", "Magentas"];
|
|
|
7633
10064
|
var ADJUSTMENT_LAYER_CONTROLS = {
|
|
7634
10065
|
curves: [],
|
|
7635
10066
|
levels: [
|
|
7636
|
-
...
|
|
7637
|
-
...
|
|
7638
|
-
...
|
|
7639
|
-
...
|
|
10067
|
+
...levelsRecord2("master", "RGB"),
|
|
10068
|
+
...levelsRecord2("red", "Red"),
|
|
10069
|
+
...levelsRecord2("green", "Green"),
|
|
10070
|
+
...levelsRecord2("blue", "Blue")
|
|
7640
10071
|
],
|
|
7641
10072
|
hueSaturation: [
|
|
7642
10073
|
{ id: "hue", label: "Hue", section: "layer", min: -180, max: 180, step: 1, default: 0, decimals: 0, track: { kind: "rainbow" }, unit: "\xB0" },
|
|
@@ -7696,7 +10127,7 @@ function findAdjustmentControl(id) {
|
|
|
7696
10127
|
}
|
|
7697
10128
|
function findLayerControl(kind, id) {
|
|
7698
10129
|
if (id === "opacity") return ADJUSTMENT_LAYER_OPACITY_CONTROL;
|
|
7699
|
-
return _optionalChain([ADJUSTMENT_LAYER_CONTROLS, 'access',
|
|
10130
|
+
return _optionalChain([ADJUSTMENT_LAYER_CONTROLS, 'access', _230 => _230[kind], 'optionalAccess', _231 => _231.find, 'call', _232 => _232((c) => c.id === id)]);
|
|
7700
10131
|
}
|
|
7701
10132
|
function clampControlValue(spec, v) {
|
|
7702
10133
|
if (typeof v !== "number" || !Number.isFinite(v)) return spec.default;
|
|
@@ -7815,7 +10246,7 @@ function summary(controller) {
|
|
|
7815
10246
|
const area = selectionArea(sel);
|
|
7816
10247
|
return {
|
|
7817
10248
|
empty: !sel,
|
|
7818
|
-
bounds: _nullishCoalesce(_optionalChain([sel, 'optionalAccess',
|
|
10249
|
+
bounds: _nullishCoalesce(_optionalChain([sel, 'optionalAccess', _233 => _233.bounds]), () => ( null)),
|
|
7819
10250
|
/** Σ coverage in pixels. */
|
|
7820
10251
|
area: Math.round(area),
|
|
7821
10252
|
percent: Math.round(area / Math.max(1, width * height) * 1e4) / 100,
|
|
@@ -7899,13 +10330,22 @@ function createImageSelectionTools(controller) {
|
|
|
7899
10330
|
contiguous: { type: "boolean", description: "Only the connected region around (x, y) (default true)." },
|
|
7900
10331
|
fuzziness: { type: "number", minimum: 0, maximum: 200, description: "Color Range fuzziness (default 40)." },
|
|
7901
10332
|
sampleMerged: { type: "boolean", description: "Sample the adjusted image rather than the source." },
|
|
10333
|
+
sample: {
|
|
10334
|
+
type: "string",
|
|
10335
|
+
enum: ["composite", "active-layer"],
|
|
10336
|
+
description: "composite (default): the whole image; active-layer: only the active pixel layer (see set_active_layer)."
|
|
10337
|
+
},
|
|
7902
10338
|
mode: modeSchema
|
|
7903
10339
|
},
|
|
7904
10340
|
additionalProperties: false
|
|
7905
10341
|
},
|
|
7906
10342
|
annotations: writeAnnotations("Select by colour", true),
|
|
7907
|
-
handler: async ({ x, y, color, tolerance, contiguous, fuzziness, sampleMerged, mode }) => {
|
|
7908
|
-
const common = {
|
|
10343
|
+
handler: async ({ x, y, color, tolerance, contiguous, fuzziness, sampleMerged, sample, mode }) => {
|
|
10344
|
+
const common = {
|
|
10345
|
+
mode: parseSelectionMode(mode),
|
|
10346
|
+
sampleMerged: sampleMerged === true,
|
|
10347
|
+
sample: _nullishCoalesce(sample, () => ( "composite"))
|
|
10348
|
+
};
|
|
7909
10349
|
if (typeof color === "string") {
|
|
7910
10350
|
await controller.selectColorRange([{ color }], { ...common, fuzziness: num2(fuzziness, 40) });
|
|
7911
10351
|
} else if (typeof x === "number" && typeof y === "number") {
|
|
@@ -8050,7 +10490,7 @@ async function renderImageRegion(controller, request) {
|
|
|
8050
10490
|
if (request.includeOverlays) {
|
|
8051
10491
|
const s = request.scale;
|
|
8052
10492
|
const selection = state.selection;
|
|
8053
|
-
if (_optionalChain([selection, 'optionalAccess',
|
|
10493
|
+
if (_optionalChain([selection, 'optionalAccess', _234 => _234.bounds]) && selection.width === state.imageDimensions.width && selection.height === state.imageDimensions.height) {
|
|
8054
10494
|
const shade = selectionShade(selection, document);
|
|
8055
10495
|
if (shade) context.drawImage(shade, rect.x, rect.y, rect.width, rect.height, 0, 0, out.width, out.height);
|
|
8056
10496
|
}
|
|
@@ -8075,7 +10515,7 @@ function createImageCaptureSurface(controller) {
|
|
|
8075
10515
|
return {
|
|
8076
10516
|
units: "image pixels",
|
|
8077
10517
|
content: whole,
|
|
8078
|
-
selection: () => ({ rect: _nullishCoalesce(_optionalChain([controller, 'access',
|
|
10518
|
+
selection: () => ({ rect: _nullishCoalesce(_optionalChain([controller, 'access', _235 => _235.getState, 'call', _236 => _236(), 'access', _237 => _237.selection, 'optionalAccess', _238 => _238.bounds]), () => ( null)) }),
|
|
8079
10519
|
overlays: "a shade over unselected pixels and the crop box outline",
|
|
8080
10520
|
maxScale: 8,
|
|
8081
10521
|
render: (request) => renderImageRegion(controller, request)
|
|
@@ -8415,7 +10855,7 @@ function createImageLayerTools(controller) {
|
|
|
8415
10855
|
if (!loc) return null;
|
|
8416
10856
|
return {
|
|
8417
10857
|
...describeLayer(loc.layer, s.activeLayerId, (x) => controller.getLayerBounds(x.id)),
|
|
8418
|
-
parentId: _nullishCoalesce(_optionalChain([loc, 'access',
|
|
10858
|
+
parentId: _nullishCoalesce(_optionalChain([loc, 'access', _239 => _239.parent, 'optionalAccess', _240 => _240.id]), () => ( null)),
|
|
8419
10859
|
index: loc.index
|
|
8420
10860
|
};
|
|
8421
10861
|
};
|
|
@@ -8762,6 +11202,14 @@ function createImageLayerTools(controller) {
|
|
|
8762
11202
|
return { layer: describe(controller.layerViaCopy({ layerId, cut: cut === true, name })) };
|
|
8763
11203
|
}
|
|
8764
11204
|
};
|
|
11205
|
+
const rasterize = {
|
|
11206
|
+
name: "rasterize_layer",
|
|
11207
|
+
title: "Rasterize a layer",
|
|
11208
|
+
description: "Rasterize Layer: turns an annotation layer into a pixel layer (same id, name, opacity, blend and mask; needs a browser) or bakes a pixel layer's filters (develop, blur) into its pixels. One undo step. Returns the layer.",
|
|
11209
|
+
inputSchema: { type: "object", properties: { layerId: LAYER_ID2 }, required: ["layerId"], additionalProperties: false },
|
|
11210
|
+
annotations: { title: "Rasterize a layer", ...DESTRUCTIVE },
|
|
11211
|
+
handler: async ({ layerId }) => ({ layer: describe(await controller.rasterizeLayer(exists(layerId))) })
|
|
11212
|
+
};
|
|
8765
11213
|
const filterArgs = {
|
|
8766
11214
|
enabled: { type: "boolean", description: "false keeps the filter but skips it." },
|
|
8767
11215
|
radius: { type: "number", minimum: 0, maximum: 50, description: "blur: box radius in px (default 2)." },
|
|
@@ -8848,6 +11296,7 @@ function createImageLayerTools(controller) {
|
|
|
8848
11296
|
removeMask,
|
|
8849
11297
|
maskProps,
|
|
8850
11298
|
viaCopy,
|
|
11299
|
+
rasterize,
|
|
8851
11300
|
addFilter,
|
|
8852
11301
|
updateFilter,
|
|
8853
11302
|
removeFilter
|
|
@@ -8966,6 +11415,82 @@ function createImagePaintTools(controller) {
|
|
|
8966
11415
|
return [paintStroke, fill, clear];
|
|
8967
11416
|
}
|
|
8968
11417
|
|
|
11418
|
+
// src/image-editor/psd-tools.ts
|
|
11419
|
+
var READ3 = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
11420
|
+
var DESTRUCTIVE3 = { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false };
|
|
11421
|
+
var DATA = {
|
|
11422
|
+
type: "string",
|
|
11423
|
+
minLength: 1,
|
|
11424
|
+
description: "The PSD or PSB file as base64 (a `data:` URL prefix is accepted)."
|
|
11425
|
+
};
|
|
11426
|
+
function psdBytesFromBase64(data) {
|
|
11427
|
+
if (typeof data !== "string" || !data.trim()) throw new PsdError("data is required: the PSD file as base64.");
|
|
11428
|
+
const body = data.trim().replace(/^data:[^,]*;base64,/i, "");
|
|
11429
|
+
if (!/^[A-Za-z0-9+/=_\s-]+$/.test(body)) throw new PsdError("data is not base64; send the PSD file bytes base64-encoded.");
|
|
11430
|
+
const bytes = _chunkH543GD6Tcjs.base64ToBytes.call(void 0, body);
|
|
11431
|
+
if (bytes.length < 26) throw new PsdError(`data decodes to ${bytes.length} bytes, too short for a PSD (at least 26).`);
|
|
11432
|
+
return bytes;
|
|
11433
|
+
}
|
|
11434
|
+
function createImagePsdTools(controller) {
|
|
11435
|
+
const inspect = {
|
|
11436
|
+
name: "inspect_psd",
|
|
11437
|
+
title: "Inspect a PSD",
|
|
11438
|
+
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
|
+
inputSchema: { type: "object", properties: { data: DATA }, required: ["data"], additionalProperties: false },
|
|
11440
|
+
annotations: { title: "Inspect a PSD", ...READ3 },
|
|
11441
|
+
handler: ({ data }) => {
|
|
11442
|
+
const res = importPsd(psdBytesFromBase64(data), { skipPixels: true });
|
|
11443
|
+
return {
|
|
11444
|
+
width: res.width,
|
|
11445
|
+
height: res.height,
|
|
11446
|
+
...res.info,
|
|
11447
|
+
resolution: _nullishCoalesce(res.resolution, () => ( null)),
|
|
11448
|
+
layers: res.summary.map(({ id: _id, ...s }) => s),
|
|
11449
|
+
warnings: res.warnings
|
|
11450
|
+
};
|
|
11451
|
+
}
|
|
11452
|
+
};
|
|
11453
|
+
const open = {
|
|
11454
|
+
name: "import_psd",
|
|
11455
|
+
title: "Open a PSD as the document",
|
|
11456
|
+
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
|
+
inputSchema: { type: "object", properties: { data: DATA }, required: ["data"], additionalProperties: false },
|
|
11458
|
+
annotations: { title: "Open a PSD as the document", ...DESTRUCTIVE3 },
|
|
11459
|
+
handler: ({ data }) => {
|
|
11460
|
+
const res = controller.loadPsd(psdBytesFromBase64(data));
|
|
11461
|
+
const s = controller.getState();
|
|
11462
|
+
return {
|
|
11463
|
+
width: res.width,
|
|
11464
|
+
height: res.height,
|
|
11465
|
+
layerIds: res.layerIds,
|
|
11466
|
+
layers: s.layers.map((l) => describeLayer(l, s.activeLayerId, (x) => controller.getLayerBounds(x.id))),
|
|
11467
|
+
activeLayerId: s.activeLayerId,
|
|
11468
|
+
warnings: res.warnings
|
|
11469
|
+
};
|
|
11470
|
+
}
|
|
11471
|
+
};
|
|
11472
|
+
const save = {
|
|
11473
|
+
name: "export_psd",
|
|
11474
|
+
title: "Export the document as a PSD",
|
|
11475
|
+
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
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
11477
|
+
annotations: { title: "Export the document as a PSD", ...READ3 },
|
|
11478
|
+
handler: async () => {
|
|
11479
|
+
const res = await controller.toPsd();
|
|
11480
|
+
return {
|
|
11481
|
+
data: _chunkH543GD6Tcjs.bytesToBase64.call(void 0, res.bytes),
|
|
11482
|
+
mimeType: "image/vnd.adobe.photoshop",
|
|
11483
|
+
size: res.bytes.length,
|
|
11484
|
+
psb: res.psb,
|
|
11485
|
+
width: res.width,
|
|
11486
|
+
height: res.height,
|
|
11487
|
+
warnings: res.warnings
|
|
11488
|
+
};
|
|
11489
|
+
}
|
|
11490
|
+
};
|
|
11491
|
+
return [inspect, open, save];
|
|
11492
|
+
}
|
|
11493
|
+
|
|
8969
11494
|
// src/image-editor/tools.ts
|
|
8970
11495
|
var LAYER_PATH = /^layers\.([^.]+)\.(.+)$/;
|
|
8971
11496
|
function adjustmentsSummary(adjustments) {
|
|
@@ -9138,7 +11663,7 @@ function createImageEditorToolProvider(controller, options = {}) {
|
|
|
9138
11663
|
for (const ref of [aboveId, parentId]) {
|
|
9139
11664
|
if (ref !== void 0 && !controller.getLayer(ref)) throw new Error(`Unknown layer "${ref}". Call list_layers for ids.`);
|
|
9140
11665
|
}
|
|
9141
|
-
if (parentId !== void 0 && _optionalChain([controller, 'access',
|
|
11666
|
+
if (parentId !== void 0 && _optionalChain([controller, 'access', _241 => _241.getLayer, 'call', _242 => _242(parentId), 'optionalAccess', _243 => _243.type]) !== "group") throw new Error(`Layer "${parentId}" is not a group.`);
|
|
9142
11667
|
const id = controller.addAdjustmentLayer({ kind, params, opacity, blend, name, aboveId, parentId });
|
|
9143
11668
|
const layer = controller.getAdjustmentLayer(id);
|
|
9144
11669
|
return { layer: JSON.parse(JSON.stringify(layer)), index: controller.getAdjustmentLayers().findIndex((l) => l.id === id) };
|
|
@@ -9203,7 +11728,8 @@ function createImageEditorToolProvider(controller, options = {}) {
|
|
|
9203
11728
|
...createImageSelectionTools(controller),
|
|
9204
11729
|
...createImageEditTools(controller),
|
|
9205
11730
|
...createImageLayerTools(controller),
|
|
9206
|
-
...createImagePaintTools(controller)
|
|
11731
|
+
...createImagePaintTools(controller),
|
|
11732
|
+
...createImagePsdTools(controller)
|
|
9207
11733
|
]
|
|
9208
11734
|
};
|
|
9209
11735
|
}
|
|
@@ -9242,14 +11768,14 @@ function hitTestCurvePoint(points, x, y, width, height, radius = 8) {
|
|
|
9242
11768
|
}
|
|
9243
11769
|
function insertCurvePoint(points, p) {
|
|
9244
11770
|
const point = { input: clampLevel(p.input), output: clampLevel(p.output) };
|
|
9245
|
-
const out = points.filter((
|
|
9246
|
-
let index = out.findIndex((
|
|
11771
|
+
const out = points.filter((q2) => q2.input !== point.input).map((q2) => ({ ...q2 }));
|
|
11772
|
+
let index = out.findIndex((q2) => q2.input > point.input);
|
|
9247
11773
|
if (index === -1) index = out.length;
|
|
9248
11774
|
out.splice(index, 0, point);
|
|
9249
11775
|
return { points: out, index };
|
|
9250
11776
|
}
|
|
9251
11777
|
function moveCurvePoint(points, index, p) {
|
|
9252
|
-
const out = points.map((
|
|
11778
|
+
const out = points.map((q2) => ({ ...q2 }));
|
|
9253
11779
|
if (index < 0 || index >= out.length) return out;
|
|
9254
11780
|
const lo = index > 0 ? out[index - 1].input + 1 : 0;
|
|
9255
11781
|
const hi = index < out.length - 1 ? out[index + 1].input - 1 : 255;
|
|
@@ -9257,25 +11783,25 @@ function moveCurvePoint(points, index, p) {
|
|
|
9257
11783
|
return out;
|
|
9258
11784
|
}
|
|
9259
11785
|
function removeCurvePoint(points, index) {
|
|
9260
|
-
if (points.length <= 2 || index < 0 || index >= points.length) return points.map((
|
|
9261
|
-
return points.filter((_, i) => i !== index).map((
|
|
11786
|
+
if (points.length <= 2 || index < 0 || index >= points.length) return points.map((q2) => ({ ...q2 }));
|
|
11787
|
+
return points.filter((_, i) => i !== index).map((q2) => ({ ...q2 }));
|
|
9262
11788
|
}
|
|
9263
11789
|
var round22 = (v) => Math.round(v * 100) / 100;
|
|
9264
11790
|
|
|
9265
11791
|
// src/image-editor/selection/gesture.ts
|
|
9266
|
-
var SelectionGesture = (
|
|
9267
|
-
constructor(controller, getOptions) {;
|
|
11792
|
+
var SelectionGesture = (_class8 = class {
|
|
11793
|
+
constructor(controller, getOptions) {;_class8.prototype.__init50.call(this);_class8.prototype.__init51.call(this);_class8.prototype.__init52.call(this);_class8.prototype.__init53.call(this);_class8.prototype.__init54.call(this);
|
|
9268
11794
|
this.controller = controller;
|
|
9269
11795
|
this.getOptions = getOptions;
|
|
9270
11796
|
}
|
|
9271
11797
|
|
|
9272
11798
|
|
|
9273
|
-
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
|
|
11799
|
+
__init50() {this.start = null}
|
|
11800
|
+
__init51() {this.points = []}
|
|
11801
|
+
__init52() {this.current = null}
|
|
11802
|
+
__init53() {this.modifiers = {}}
|
|
9277
11803
|
/** The last error (e.g. pixels unavailable for the wand), for the UI to show. */
|
|
9278
|
-
|
|
11804
|
+
__init54() {this.error = null}
|
|
9279
11805
|
get active() {
|
|
9280
11806
|
return this.start !== null;
|
|
9281
11807
|
}
|
|
@@ -9313,6 +11839,7 @@ var SelectionGesture = (_class6 = class {
|
|
|
9313
11839
|
antiAlias: options.antiAlias,
|
|
9314
11840
|
distance: options.distance,
|
|
9315
11841
|
sampleMerged: options.sampleMerged,
|
|
11842
|
+
sample: options.sample,
|
|
9316
11843
|
mode: selectionModeFromModifiers(modifiers, options.mode)
|
|
9317
11844
|
});
|
|
9318
11845
|
} catch (err) {
|
|
@@ -9362,7 +11889,7 @@ var SelectionGesture = (_class6 = class {
|
|
|
9362
11889
|
this.current = null;
|
|
9363
11890
|
this.points = [];
|
|
9364
11891
|
}
|
|
9365
|
-
},
|
|
11892
|
+
}, _class8);
|
|
9366
11893
|
|
|
9367
11894
|
// src/image-editor/mosaic-filter.ts
|
|
9368
11895
|
function resolveMosaicRegionBounds(region, imgWidth, imgHeight) {
|
|
@@ -9557,30 +12084,31 @@ function layerMenu(controller) {
|
|
|
9557
12084
|
const siblings = loc ? loc.parent ? loc.parent.children : s.layers : [];
|
|
9558
12085
|
const below = loc ? siblings[loc.index - 1] : void 0;
|
|
9559
12086
|
const hasSel = controller.hasSelection;
|
|
9560
|
-
const isPixel = _optionalChain([active, 'optionalAccess',
|
|
12087
|
+
const isPixel = _optionalChain([active, 'optionalAccess', _244 => _244.type]) === "pixel";
|
|
9561
12088
|
return [
|
|
9562
12089
|
{ action: "new-layer", label: "New Layer", enabled: true },
|
|
9563
12090
|
{ action: "new-group", label: "New Group", enabled: true },
|
|
9564
12091
|
{ action: "duplicate", label: "Duplicate Layer", enabled: Boolean(active) },
|
|
9565
12092
|
{ action: "delete", label: "Delete Layer", enabled: Boolean(active) },
|
|
9566
12093
|
{ action: "group-selected", label: "Group Layer", enabled: Boolean(active) },
|
|
9567
|
-
{ action: "ungroup", label: "Ungroup", enabled: _optionalChain([active, 'optionalAccess',
|
|
9568
|
-
{ action: "merge-down", label: "Merge Down", enabled: Boolean(_optionalChain([active, 'optionalAccess',
|
|
12094
|
+
{ action: "ungroup", label: "Ungroup", enabled: _optionalChain([active, 'optionalAccess', _245 => _245.type]) === "group" },
|
|
12095
|
+
{ action: "merge-down", label: "Merge Down", enabled: Boolean(_optionalChain([active, 'optionalAccess', _246 => _246.visible]) && _optionalChain([below, 'optionalAccess', _247 => _247.type]) === "pixel") },
|
|
9569
12096
|
{ action: "merge-visible", label: "Merge Visible", enabled: s.layers.some((l) => l.visible) },
|
|
9570
12097
|
{ action: "flatten", label: "Flatten Image", enabled: s.layers.length > 0 },
|
|
9571
12098
|
{ action: "via-copy", label: "Layer via Copy", enabled: isPixel && hasSel },
|
|
9572
12099
|
{ action: "via-cut", label: "Layer via Cut", enabled: isPixel && hasSel },
|
|
9573
12100
|
{ action: "add-mask", label: "Add Layer Mask", enabled: Boolean(active) },
|
|
9574
12101
|
{ action: "add-mask-selection", label: "Add Mask from Selection", enabled: Boolean(active) && hasSel },
|
|
9575
|
-
{ action: "apply-mask", label: "Apply Layer Mask", enabled: isPixel && Boolean(_optionalChain([active, 'optionalAccess',
|
|
9576
|
-
{ action: "delete-mask", label: "Delete Layer Mask", enabled: Boolean(_optionalChain([active, 'optionalAccess',
|
|
9577
|
-
{ action: "toggle-mask", label: _optionalChain([active, 'optionalAccess',
|
|
9578
|
-
{ action: "
|
|
12102
|
+
{ action: "apply-mask", label: "Apply Layer Mask", enabled: isPixel && Boolean(_optionalChain([active, 'optionalAccess', _248 => _248.mask])) },
|
|
12103
|
+
{ action: "delete-mask", label: "Delete Layer Mask", enabled: Boolean(_optionalChain([active, 'optionalAccess', _249 => _249.mask])) },
|
|
12104
|
+
{ action: "toggle-mask", label: _optionalChain([active, 'optionalAccess', _250 => _250.mask, 'optionalAccess', _251 => _251.enabled]) === false ? "Enable Layer Mask" : "Disable Layer Mask", enabled: Boolean(_optionalChain([active, 'optionalAccess', _252 => _252.mask])) },
|
|
12105
|
+
{ action: "rasterize", label: "Rasterize Layer", enabled: _optionalChain([active, 'optionalAccess', _253 => _253.type]) === "annotation" || isPixel && Boolean(_optionalChain([active, 'optionalAccess', _254 => _254.type]) === "pixel" && _optionalChain([active, 'access', _255 => _255.filters, 'optionalAccess', _256 => _256.length])) },
|
|
12106
|
+
{ action: "toggle-clip", label: _optionalChain([active, 'optionalAccess', _257 => _257.clipped]) ? "Release Clipping Mask" : "Create Clipping Mask", enabled: Boolean(loc && loc.index > 0) }
|
|
9579
12107
|
];
|
|
9580
12108
|
}
|
|
9581
12109
|
async function runLayerMenuAction(controller, action) {
|
|
9582
12110
|
const active = controller.getActiveLayer();
|
|
9583
|
-
const id = _optionalChain([active, 'optionalAccess',
|
|
12111
|
+
const id = _optionalChain([active, 'optionalAccess', _258 => _258.id]);
|
|
9584
12112
|
try {
|
|
9585
12113
|
switch (action) {
|
|
9586
12114
|
case "new-layer":
|
|
@@ -9627,10 +12155,13 @@ async function runLayerMenuAction(controller, action) {
|
|
|
9627
12155
|
if (id) controller.removeLayerMask(id);
|
|
9628
12156
|
break;
|
|
9629
12157
|
case "toggle-mask":
|
|
9630
|
-
if (id && _optionalChain([active, 'optionalAccess',
|
|
12158
|
+
if (id && _optionalChain([active, 'optionalAccess', _259 => _259.mask])) controller.setLayerMaskProps(id, { enabled: active.mask.enabled === false });
|
|
12159
|
+
break;
|
|
12160
|
+
case "rasterize":
|
|
12161
|
+
if (id) await controller.rasterizeLayer(id);
|
|
9631
12162
|
break;
|
|
9632
12163
|
case "toggle-clip":
|
|
9633
|
-
if (id) controller.setLayerProperties(id, { clipped: !_optionalChain([active, 'optionalAccess',
|
|
12164
|
+
if (id) controller.setLayerProperties(id, { clipped: !_optionalChain([active, 'optionalAccess', _260 => _260.clipped]) });
|
|
9634
12165
|
break;
|
|
9635
12166
|
}
|
|
9636
12167
|
return null;
|
|
@@ -9703,15 +12234,15 @@ function pointerPressure(e) {
|
|
|
9703
12234
|
if (e.pointerType === "pen" && typeof e.pressure === "number" && e.pressure > 0) return Math.min(1, e.pressure);
|
|
9704
12235
|
return 1;
|
|
9705
12236
|
}
|
|
9706
|
-
var PaintGesture = (
|
|
9707
|
-
constructor(controller) {;
|
|
12237
|
+
var PaintGesture = (_class9 = class {
|
|
12238
|
+
constructor(controller) {;_class9.prototype.__init55.call(this);_class9.prototype.__init56.call(this);_class9.prototype.__init57.call(this);
|
|
9708
12239
|
this.controller = controller;
|
|
9709
12240
|
}
|
|
9710
12241
|
|
|
9711
|
-
|
|
9712
|
-
|
|
12242
|
+
__init55() {this.stroke = null}
|
|
12243
|
+
__init56() {this.move = null}
|
|
9713
12244
|
/** The last refusal (e.g. "layer is locked"), for the editor to show. */
|
|
9714
|
-
|
|
12245
|
+
__init57() {this.error = null}
|
|
9715
12246
|
get active() {
|
|
9716
12247
|
return Boolean(this.stroke || this.move);
|
|
9717
12248
|
}
|
|
@@ -9723,7 +12254,7 @@ var PaintGesture = (_class7 = class {
|
|
|
9723
12254
|
const layer = this.controller.getActiveLayer();
|
|
9724
12255
|
if (!layer) throw new Error("Select a layer to move in the Layers panel.");
|
|
9725
12256
|
if (layer.type !== "pixel") throw new Error(`Only pixel layers move; "${layer.name}" is a ${layer.type} layer.`);
|
|
9726
|
-
if (_optionalChain([layer, 'access',
|
|
12257
|
+
if (_optionalChain([layer, 'access', _261 => _261.locks, 'optionalAccess', _262 => _262.all]) || _optionalChain([layer, 'access', _263 => _263.locks, 'optionalAccess', _264 => _264.position])) throw new Error(`Layer "${layer.name}" has its position locked.`);
|
|
9727
12258
|
this.move = { id: layer.id, start: { x: sample.x, y: sample.y }, origin: { ...layer.offset }, moved: false };
|
|
9728
12259
|
return null;
|
|
9729
12260
|
}
|
|
@@ -9772,11 +12303,74 @@ var PaintGesture = (_class7 = class {
|
|
|
9772
12303
|
this.move = null;
|
|
9773
12304
|
}
|
|
9774
12305
|
cancel() {
|
|
9775
|
-
_optionalChain([this, 'access',
|
|
12306
|
+
_optionalChain([this, 'access', _265 => _265.stroke, 'optionalAccess', _266 => _266.cancel, 'call', _267 => _267()]);
|
|
9776
12307
|
this.stroke = null;
|
|
9777
12308
|
this.move = null;
|
|
9778
12309
|
}
|
|
9779
|
-
},
|
|
12310
|
+
}, _class9);
|
|
12311
|
+
|
|
12312
|
+
// src/image-editor/psd/ui.ts
|
|
12313
|
+
var PSD_FILE_ACCEPT = ".psd,.psb,image/vnd.adobe.photoshop,application/x-photoshop";
|
|
12314
|
+
function blobBytes(file) {
|
|
12315
|
+
if (typeof file.arrayBuffer === "function") return file.arrayBuffer().then((b) => new Uint8Array(b));
|
|
12316
|
+
return new Promise((resolve, reject) => {
|
|
12317
|
+
const reader = new FileReader();
|
|
12318
|
+
reader.onload = () => resolve(new Uint8Array(reader.result));
|
|
12319
|
+
reader.onerror = () => reject(_nullishCoalesce(reader.error, () => ( new Error("The file could not be read."))));
|
|
12320
|
+
reader.readAsArrayBuffer(file);
|
|
12321
|
+
});
|
|
12322
|
+
}
|
|
12323
|
+
async function openPsdFile(controller, file) {
|
|
12324
|
+
return controller.loadPsd(await blobBytes(file)).warnings;
|
|
12325
|
+
}
|
|
12326
|
+
function psdFileName(name, psb) {
|
|
12327
|
+
const base = name.replace(/\.[a-z0-9]{2,4}$/i, "") || "image";
|
|
12328
|
+
return `${base}.${psb ? "psb" : "psd"}`;
|
|
12329
|
+
}
|
|
12330
|
+
async function downloadPsd(controller, name = "image") {
|
|
12331
|
+
const res = await controller.toPsd();
|
|
12332
|
+
const fileName = psdFileName(name, res.psb);
|
|
12333
|
+
if (typeof document !== "undefined" && typeof URL !== "undefined" && URL.createObjectURL) {
|
|
12334
|
+
const blob = new Blob([res.bytes], { type: "image/vnd.adobe.photoshop" });
|
|
12335
|
+
const url = URL.createObjectURL(blob);
|
|
12336
|
+
const a = document.createElement("a");
|
|
12337
|
+
a.href = url;
|
|
12338
|
+
a.download = fileName;
|
|
12339
|
+
a.click();
|
|
12340
|
+
setTimeout(() => URL.revokeObjectURL(url), 0);
|
|
12341
|
+
}
|
|
12342
|
+
return { fileName, warnings: res.warnings };
|
|
12343
|
+
}
|
|
12344
|
+
|
|
12345
|
+
|
|
12346
|
+
|
|
12347
|
+
|
|
12348
|
+
|
|
12349
|
+
|
|
12350
|
+
|
|
12351
|
+
|
|
12352
|
+
|
|
12353
|
+
|
|
12354
|
+
|
|
12355
|
+
|
|
12356
|
+
|
|
12357
|
+
|
|
12358
|
+
|
|
12359
|
+
|
|
12360
|
+
|
|
12361
|
+
|
|
12362
|
+
|
|
12363
|
+
|
|
12364
|
+
|
|
12365
|
+
|
|
12366
|
+
|
|
12367
|
+
|
|
12368
|
+
|
|
12369
|
+
|
|
12370
|
+
|
|
12371
|
+
|
|
12372
|
+
|
|
12373
|
+
|
|
9780
12374
|
|
|
9781
12375
|
|
|
9782
12376
|
|
|
@@ -10143,5 +12737,5 @@ var PaintGesture = (_class7 = class {
|
|
|
10143
12737
|
|
|
10144
12738
|
|
|
10145
12739
|
|
|
10146
|
-
exports.ADJUSTMENT_KINDS = ADJUSTMENT_KINDS; exports.ADJUSTMENT_LAYER_CONTROLS = ADJUSTMENT_LAYER_CONTROLS; exports.ADJUSTMENT_LAYER_OPACITY_CONTROL = ADJUSTMENT_LAYER_OPACITY_CONTROL; exports.ADJUSTMENT_LUT_SIZE = ADJUSTMENT_LUT_SIZE; exports.AS_SHOT_KELVIN = AS_SHOT_KELVIN; exports.BACKGROUND_LAYER_ID = BACKGROUND_LAYER_ID; exports.BACKGROUND_LAYER_NAME = BACKGROUND_LAYER_NAME; exports.BLEND_MODES = _chunkZOOEX3WTcjs.BLEND_MODES; exports.BLUR_FILTER_ID = BLUR_FILTER_ID; exports.BRUSH_OPTION_CONTROLS = BRUSH_OPTION_CONTROLS; exports.CoverageMap = _chunkPDCITYBTcjs.CoverageMap; exports.D65 = D65; exports.DEFAULT_ADJUSTMENTS = DEFAULT_ADJUSTMENTS; exports.DEFAULT_BRUSH = _chunkPDCITYBTcjs.DEFAULT_BRUSH; exports.DEFAULT_DEPTH_MASK = DEFAULT_DEPTH_MASK; exports.DEFAULT_REFINE_EDGE_PARAMS = DEFAULT_REFINE_EDGE_PARAMS; exports.DEFAULT_SELECTION_TOOL_OPTIONS = DEFAULT_SELECTION_TOOL_OPTIONS; exports.DEFAULT_TRANSFORM = DEFAULT_TRANSFORM; exports.DEVELOP_FILTER_ID = DEVELOP_FILTER_ID; exports.DIRECT_GAUSSIAN_MAX_SIGMA = _chunkH543GD6Tcjs.DIRECT_GAUSSIAN_MAX_SIGMA; exports.DabWalker = _chunkPDCITYBTcjs.DabWalker; exports.EMPTY_DISTANCE = EMPTY_DISTANCE; exports.GUIDED_FILTER_EPS = GUIDED_FILTER_EPS; exports.HISTOGRAM_BINS = HISTOGRAM_BINS; exports.HUE_RANGE_LABELS = HUE_RANGE_LABELS; exports.IDENTITY_MATRIX3 = IDENTITY_MATRIX3; exports.IMAGE_ADJUSTMENT_CONTROLS = IMAGE_ADJUSTMENT_CONTROLS; exports.IMAGE_EDITOR_SCHEMA_VERSION = IMAGE_EDITOR_SCHEMA_VERSION; exports.IMAGE_EDITOR_STATE_VERSION = IMAGE_EDITOR_STATE_VERSION; exports.ImageEditorController = ImageEditorController; exports.ImageEditorRenderer = ImageEditorRenderer; exports.LATEST_PROCESS_VERSION = LATEST_PROCESS_VERSION; exports.LAYERED_SCHEMA_VERSION = LAYERED_SCHEMA_VERSION; exports.LEGACY_PROCESS_VERSION = LEGACY_PROCESS_VERSION; exports.LUMA_709 = LUMA_709; exports.LayerCompositor = LayerCompositor; exports.LayerOperationError = LayerOperationError; exports.MAX_BRUSH_SIZE = _chunkPDCITYBTcjs.MAX_BRUSH_SIZE; exports.MAX_KELVIN = MAX_KELVIN; exports.MIN_KELVIN = MIN_KELVIN; exports.MIRED_PER_TEMPERATURE_UNIT = MIRED_PER_TEMPERATURE_UNIT; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PaintGesture = PaintGesture; exports.PaintStrokeSession = PaintStrokeSession; exports.REFINE_EDGE_CONTROLS = REFINE_EDGE_CONTROLS; exports.SELECTION_MODES = SELECTION_MODES; exports.SELECTION_MODE_LABELS = SELECTION_MODE_LABELS; exports.SELECTION_MODIFY_OPS = SELECTION_MODIFY_OPS; exports.SELECTION_TOOLS = SELECTION_TOOLS; exports.SelectionGesture = SelectionGesture; exports.StrokeCoverage = _chunkPDCITYBTcjs.StrokeCoverage; exports.SurfaceDraft = _chunkZOOEX3WTcjs.SurfaceDraft; exports.TILE = _chunkZOOEX3WTcjs.TILE; exports.TILE_SHIFT = _chunkZOOEX3WTcjs.TILE_SHIFT; exports.TINT_SCALE = TINT_SCALE; exports.TONE_LUT_SIZE = TONE_LUT_SIZE; exports.TONE_RANGE_PRESETS = TONE_RANGE_PRESETS; exports.TiledSurface = _chunkZOOEX3WTcjs.TiledSurface; exports.VIBRANCE_GREY = VIBRANCE_GREY; exports.ZlibError = _chunkH543GD6Tcjs.ZlibError; exports.activeAdjustmentLayers = activeAdjustmentLayers; exports.addLayerFilter = addLayerFilter; exports.addToHistogram = addToHistogram; exports.adjustmentKindLabel = adjustmentKindLabel; exports.adjustmentLayersKey = adjustmentLayersKey; exports.adjustmentNodeAsLayer = adjustmentNodeAsLayer; exports.adjustmentNodeFromLegacy = adjustmentNodeFromLegacy; exports.adler32 = _chunkH543GD6Tcjs.adler32; exports.annotationLayerFor = annotationLayerFor; exports.annotationLayerName = annotationLayerName; exports.applyAdjustmentLayers = applyAdjustmentLayers; exports.applyAdjustments = applyAdjustments; exports.applyBoxBlur = applyBoxBlur; exports.applyDepthMask = applyDepthMask; exports.applyImageProjectionToContext = applyImageProjectionToContext; exports.applyLegacyAdjustments = applyLegacyAdjustments; exports.applyMatrix3 = applyMatrix3; exports.applyOutputStage = applyOutputStage; exports.applyProcess2Adjustments = applyProcess2Adjustments; exports.applyRegionBlur = applyRegionBlur; exports.applyRegionMosaic = applyRegionMosaic; exports.applyStrokeToTile = _chunkPDCITYBTcjs.applyStrokeToTile; exports.backgroundLayer = backgroundLayer; exports.base64ToBytes = _chunkH543GD6Tcjs.base64ToBytes; exports.baseProjection = baseProjection; exports.blackWhiteGray = blackWhiteGray; exports.blendChannel = _chunkZOOEX3WTcjs.blendChannel; exports.blendImageData = _chunkZOOEX3WTcjs.blendImageData; exports.blendLum = _chunkZOOEX3WTcjs.blendLum; exports.blendPixel = _chunkZOOEX3WTcjs.blendPixel; exports.blendRgb = _chunkZOOEX3WTcjs.blendRgb; exports.blendTile = _chunkH543GD6Tcjs.blendTile; exports.blurFilter = blurFilter; exports.borderCoverage = borderCoverage; exports.boxMean = boxMean; exports.boxToCurvePoint = boxToCurvePoint; exports.bradfordAdaptation = bradfordAdaptation; exports.buildLayerMaskPlanes = buildLayerMaskPlanes; exports.buildToneLut = buildToneLut; exports.bytesToBase64 = _chunkH543GD6Tcjs.bytesToBase64; exports.calculateCropDrag = calculateCropDrag; exports.canvasCompositeOperation = _chunkZOOEX3WTcjs.canvasCompositeOperation; exports.canvasToImagePoint = canvasToImagePoint; exports.changedTiles = _chunkH543GD6Tcjs.changedTiles; exports.clampControlValue = clampControlValue; exports.clampCropToImage = clampCropToImage; exports.collectTiles = _chunkZOOEX3WTcjs.collectTiles; exports.colorBalanceChannel = colorBalanceChannel; exports.colorRange = colorRange; exports.combineSelections = combineSelections; exports.compileAdjustmentLayer = compileAdjustmentLayer; exports.computeHistogram = computeHistogram; exports.computeSelectionBounds = computeSelectionBounds; exports.contentBounds = _chunkZOOEX3WTcjs.contentBounds; exports.contractCoverage = contractCoverage; exports.controlPosition = controlPosition; exports.controlTrackBackground = controlTrackBackground; exports.coverageTileCoord = _chunkPDCITYBTcjs.coverageTileCoord; exports.coverageToByte = coverageToByte; exports.coveringRect = coveringRect; exports.createAdjustmentLayer = createAdjustmentLayer; exports.createImageCaptureSurface = createImageCaptureSurface; exports.createImageEditTools = createImageEditTools; exports.createImageEditorToolProvider = createImageEditorToolProvider; exports.createImageLayerTools = createImageLayerTools; exports.createImagePaintTools = createImagePaintTools; exports.createImageSelectionTools = createImageSelectionTools; exports.createSelectionMask = createSelectionMask; exports.curveLut = curveLut; exports.curveLutFromLevels = curveLutFromLevels; exports.curvePointToBox = curvePointToBox; exports.curveSvgPath = curveSvgPath; exports.dabCoverage = _chunkPDCITYBTcjs.dabCoverage; exports.dabRect = _chunkPDCITYBTcjs.dabRect; exports.decodeLayerMask = decodeLayerMask; exports.decodePng = _chunkH543GD6Tcjs.decodePng; exports.decodePngDataUrl = decodePngDataUrl; exports.decodeSelectionRle = decodeSelectionRle; exports.defaultAdjustmentParams = defaultAdjustmentParams; exports.deflate = _chunkH543GD6Tcjs.deflate; exports.deflateRaw = _chunkH543GD6Tcjs.deflateRaw; exports.depthMaskAlpha = depthMaskAlpha; exports.depthRasterMask = depthRasterMask; exports.describeLayer = describeLayer; exports.describeSelection = describeSelection; exports.deserializeLayer = deserializeLayer; exports.deserializeLayers = deserializeLayers; exports.deserializeSelection = deserializeSelection; exports.developFilter = developFilter; exports.developFromAdjustments = developFromAdjustments; exports.developTarget = developTarget; exports.distanceTransform = distanceTransform; exports.dropPlacement = dropPlacement; exports.dropZone = dropZone; exports.duplicateLayer = duplicateLayer; exports.edgeWidth = edgeWidth; exports.ellipsePoints = ellipsePoints; exports.ellipseSelection = ellipseSelection; exports.emptyHistogram = emptyHistogram; exports.emptySurface = _chunkZOOEX3WTcjs.emptySurface; exports.encodePng = _chunkH543GD6Tcjs.encodePng; exports.encodeSelectionRle = encodeSelectionRle; exports.encodeSurface = encodeSurface; exports.evaluateAdjustmentLayers = evaluateAdjustmentLayers; exports.expandCoverage = expandCoverage; exports.featherCoverage = featherCoverage; exports.fillRect = _chunkZOOEX3WTcjs.fillRect; exports.findAdjustmentControl = findAdjustmentControl; exports.findLayer = _chunkH543GD6Tcjs.findLayer; exports.findLayerControl = findLayerControl; exports.finishTile = _chunkZOOEX3WTcjs.finishTile; exports.flattenLayers = _chunkH543GD6Tcjs.flattenLayers; exports.formatControlValue = formatControlValue; exports.fullSelection = fullSelection; exports.gaussianBlur = _chunkH543GD6Tcjs.gaussianBlur; exports.getAnnotationBounds = getAnnotationBounds; exports.getControlPath = getControlPath; exports.getCropCursor = getCropCursor; exports.getRotatedSize = getRotatedSize; exports.getViewportMetrics = getViewportMetrics; exports.getViewportProjection = getViewportProjection; exports.globalImageCache = globalImageCache; exports.greyMorphology = greyMorphology; exports.groupLayers = groupLayers; exports.guidePlanes = guidePlanes; exports.guidedFilterColor = guidedFilterColor; exports.handlePaintShortcut = handlePaintShortcut; exports.hasResampledLegacyMask = hasResampledLegacyMask; exports.hashMaskContent = hashMaskContent; exports.hexToRgb = hexToRgb; exports.histogramPath = histogramPath; exports.hitTestAnnotation = hitTestAnnotation; exports.hitTestCrop = hitTestCrop; exports.hitTestCurvePoint = hitTestCurvePoint; exports.hslToRgb = hslToRgb; exports.hueRange = hueRange; exports.hueRangeTables = hueRangeTables; exports.hueRangeWeight = hueRangeWeight; exports.hueSaturation = hueSaturation; exports.identityCurve = identityCurve; exports.identityLevels = identityLevels; exports.imageEditorStateMigrations = imageEditorStateMigrations; exports.imageToCanvasPoint = imageToCanvasPoint; exports.inflate = _chunkH543GD6Tcjs.inflate; exports.inflateRaw = _chunkH543GD6Tcjs.inflateRaw; exports.insertCurvePoint = insertCurvePoint; exports.insertLayer = _chunkH543GD6Tcjs.insertLayer; exports.invertMatrix3 = invertMatrix3; exports.invertSelection = invertSelection; exports.isActiveFilter = isActiveFilter; exports.isAdjustmentKind = isAdjustmentKind; exports.isBlendMode = _chunkZOOEX3WTcjs.isBlendMode; exports.isDefaultDepthMask = isDefaultDepthMask; exports.isLayerLocked = _chunkH543GD6Tcjs.isLayerLocked; exports.isLegacyShape = isLegacyShape; exports.isPaintTool = isPaintTool; exports.isPng = _chunkH543GD6Tcjs.isPng; exports.isQuarterTurn = isQuarterTurn; exports.isQuarterTurnSwapped = isQuarterTurnSwapped; exports.isSelectionEmpty = isSelectionEmpty; exports.isSelectionMode = isSelectionMode; exports.isSeparableBlendMode = _chunkZOOEX3WTcjs.isSeparableBlendMode; exports.isSpatialFilter = isSpatialFilter; exports.kelvinToTemperature = kelvinToTemperature; exports.layerBadge = layerBadge; exports.layerLabel = layerLabel; exports.layerMaskCoverage = layerMaskCoverage; exports.layerMaskFromSelection = layerMaskFromSelection; exports.layerMaskKey = layerMaskKey; exports.layerMenu = layerMenu; exports.layerPanelRows = layerPanelRows; exports.layerTypeLabel = layerTypeLabel; exports.layersFromLegacy = layersFromLegacy; exports.legacyAdjustmentLayer = legacyAdjustmentLayer; exports.legacyMaskOf = legacyMaskOf; exports.legacyView = legacyView; exports.levelsValue = levelsValue; exports.linearSrgbToXy = linearSrgbToXy; exports.linearToSrgb = linearToSrgb; exports.loadImageEditorDocument = loadImageEditorDocument; exports.magicWand = magicWand; exports.mapCropHandle = mapCropHandle; exports.mapLayer = _chunkH543GD6Tcjs.mapLayer; exports.maskSummary = maskSummary; exports.migrateSerializedImageEditorState = migrateSerializedImageEditorState; exports.migrateToLayeredState = migrateToLayeredState; exports.modifySelection = modifySelection; exports.moveCurvePoint = moveCurvePoint; exports.moveLayer = moveLayer; exports.mulMatrix3 = mulMatrix3; exports.needsLegacyBase = needsLegacyBase; exports.neutralHueRange = neutralHueRange; exports.newLayerId = newLayerId; exports.normalizeAdjustmentLayer = normalizeAdjustmentLayer; exports.normalizeAdjustmentLayers = normalizeAdjustmentLayers; exports.normalizeAngle = normalizeAngle; exports.normalizeBlendMode = _chunkZOOEX3WTcjs.normalizeBlendMode; exports.normalizeBrush = _chunkPDCITYBTcjs.normalizeBrush; exports.normalizeFilter = normalizeFilter; exports.normalizeLayerMask = normalizeLayerMask; exports.normalizeProcessVersion = normalizeProcessVersion; exports.normalizeRect = normalizeRect; exports.normalizeRefineEdgeParams = normalizeRefineEdgeParams; exports.normalizeStoredAdjustments = normalizeStoredAdjustments; exports.offsetLayer = offsetLayer; exports.packRgba = _chunkZOOEX3WTcjs.packRgba; exports.parseBlend = parseBlend; exports.parseColor = parseColor; exports.parseDataUrl = _chunkH543GD6Tcjs.parseDataUrl; exports.parseSelectionMode = parseSelectionMode; exports.photoFilterMatrix = photoFilterMatrix; exports.pixelLayerBounds = pixelLayerBounds; exports.pixelLayers = pixelLayers; exports.placeLayer = placeLayer; exports.pngDataUrl = _chunkH543GD6Tcjs.pngDataUrl; exports.pointerPressure = pointerPressure; exports.polygonCoverage = polygonCoverage; exports.polygonSelection = polygonSelection; exports.posterizeValue = posterizeValue; exports.projectImagePoint = projectImagePoint; exports.projectImageRect = projectImageRect; exports.projectMaskCoverage = projectMaskCoverage; exports.projectQuarterTurn = projectQuarterTurn; exports.quickMaskPixels = quickMaskPixels; exports.rangeLightness = rangeLightness; exports.rasterMaskFromLegacy = rasterMaskFromLegacy; exports.rasterizeDab = _chunkPDCITYBTcjs.rasterizeDab; exports.readAdjustmentControls = readAdjustmentControls; exports.readPixel = _chunkZOOEX3WTcjs.readPixel; exports.readRegion = _chunkZOOEX3WTcjs.readRegion; exports.rectSelection = rectSelection; exports.refineCoverage = refineCoverage; exports.refineEdgeHalo = refineEdgeHalo; exports.refineSelection = refineSelection; exports.removeAlpha = removeAlpha; exports.removeCurvePoint = removeCurvePoint; exports.removeLayer = removeLayer; exports.removeLayerFilter = removeLayerFilter; exports.renderLayeredBase = renderLayeredBase; exports.requireLayer = requireLayer; exports.requireUnlocked = requireUnlocked; exports.resizeSelection = resizeSelection; exports.resolveMosaicRegionBounds = resolveMosaicRegionBounds; exports.rgbToGray = rgbToGray; exports.rgbToHsl = rgbToHsl; exports.runLayerMenuAction = runLayerMenuAction; exports.sampleLut = sampleLut; exports.sampleToneLut = sampleToneLut; exports.selectionArea = selectionArea; exports.selectionFromCoverage = selectionFromCoverage; exports.selectionFromPixels = selectionFromPixels; exports.selectionModeFromModifiers = selectionModeFromModifiers; exports.selectionOutline = selectionOutline; exports.selectionToCoverage = selectionToCoverage; exports.selectionToPixels = selectionToPixels; exports.selectionValueAt = selectionValueAt; exports.serializeLayer = serializeLayer; exports.serializeLayers = serializeLayers; exports.serializeSelection = serializeSelection; exports.setControlPath = setControlPath; exports.setLayerMask = setLayerMask; exports.setLayerProperties = setLayerProperties; exports.setLum = _chunkZOOEX3WTcjs.setLum; exports.shiftCoverage = shiftCoverage; exports.smoothCoverage = smoothCoverage; exports.smoothPoints = _chunkPDCITYBTcjs.smoothPoints; exports.solidSurface = _chunkZOOEX3WTcjs.solidSurface; exports.splitOverlayAnnotations = splitOverlayAnnotations; exports.srgb8ToLab = srgb8ToLab; exports.srgbToLinear = srgbToLinear; exports.sumHistograms = sumHistograms; exports.surfaceBytes = _chunkZOOEX3WTcjs.surfaceBytes; exports.surfaceFromPixels = _chunkZOOEX3WTcjs.surfaceFromPixels; exports.surfacesEqual = _chunkZOOEX3WTcjs.surfacesEqual; exports.tempTintToXy = tempTintToXy; exports.temperatureToKelvin = temperatureToKelvin; exports.tileCoord = _chunkZOOEX3WTcjs.tileCoord; exports.tileKey = _chunkZOOEX3WTcjs.tileKey; exports.tileRect = _chunkZOOEX3WTcjs.tileRect; exports.tilesInRect = _chunkZOOEX3WTcjs.tilesInRect; exports.tipFalloff = _chunkPDCITYBTcjs.tipFalloff; exports.tipReach = _chunkPDCITYBTcjs.tipReach; exports.tipShape = _chunkPDCITYBTcjs.tipShape; exports.toHex = toHex; exports.toneCurve = toneCurve; exports.toneLuts = toneLuts; exports.toneRange = toneRange; exports.translateSurface = _chunkZOOEX3WTcjs.translateSurface; exports.ungroupLayer = ungroupLayer; exports.uniformTile = _chunkZOOEX3WTcjs.uniformTile; exports.unionRect = unionRect; exports.unprojectCanvasPoint = unprojectCanvasPoint; exports.updateLayerFilter = updateLayerFilter; exports.updateLayerMaskProps = updateLayerMaskProps; exports.uvToXy = uvToXy; exports.vibranceLinear = vibranceLinear; exports.vibrancePixel = vibrancePixel; exports.walkDabs = _chunkPDCITYBTcjs.walkDabs; exports.wbMatrix = wbMatrix; exports.whiteBalanceFromSample = whiteBalanceFromSample; exports.whiteBalanceMatrix = whiteBalanceMatrix; exports.withNewIds = withNewIds; exports.writeRegion = _chunkZOOEX3WTcjs.writeRegion; exports.xyToTempTint = xyToTempTint; exports.xyToUv = xyToUv;
|
|
12740
|
+
exports.ADJUSTMENT_KEYS = ADJUSTMENT_KEYS; exports.ADJUSTMENT_KINDS = ADJUSTMENT_KINDS; exports.ADJUSTMENT_LAYER_CONTROLS = ADJUSTMENT_LAYER_CONTROLS; exports.ADJUSTMENT_LAYER_OPACITY_CONTROL = ADJUSTMENT_LAYER_OPACITY_CONTROL; exports.ADJUSTMENT_LUT_SIZE = ADJUSTMENT_LUT_SIZE; exports.AS_SHOT_KELVIN = AS_SHOT_KELVIN; exports.BACKGROUND_LAYER_ID = BACKGROUND_LAYER_ID; exports.BACKGROUND_LAYER_NAME = BACKGROUND_LAYER_NAME; exports.BLEND_MODES = _chunkZOOEX3WTcjs.BLEND_MODES; exports.BLUR_FILTER_ID = BLUR_FILTER_ID; exports.BRUSH_OPTION_CONTROLS = BRUSH_OPTION_CONTROLS; exports.CoverageMap = _chunkPDCITYBTcjs.CoverageMap; exports.D50 = D50; exports.D65 = D65; exports.DEFAULT_ADJUSTMENTS = DEFAULT_ADJUSTMENTS; exports.DEFAULT_BRUSH = _chunkPDCITYBTcjs.DEFAULT_BRUSH; exports.DEFAULT_DEPTH_MASK = DEFAULT_DEPTH_MASK; exports.DEFAULT_REFINE_EDGE_PARAMS = DEFAULT_REFINE_EDGE_PARAMS; exports.DEFAULT_SELECTION_TOOL_OPTIONS = DEFAULT_SELECTION_TOOL_OPTIONS; exports.DEFAULT_TRANSFORM = DEFAULT_TRANSFORM; exports.DEVELOP_FILTER_ID = DEVELOP_FILTER_ID; exports.DIRECT_GAUSSIAN_MAX_SIGMA = _chunkH543GD6Tcjs.DIRECT_GAUSSIAN_MAX_SIGMA; exports.DabWalker = _chunkPDCITYBTcjs.DabWalker; exports.EMPTY_DISTANCE = EMPTY_DISTANCE; exports.GUIDED_FILTER_EPS = GUIDED_FILTER_EPS; exports.HISTOGRAM_BINS = HISTOGRAM_BINS; exports.HUE_RANGE_LABELS = HUE_RANGE_LABELS; exports.IDENTITY_MATRIX3 = IDENTITY_MATRIX3; exports.IMAGE_ADJUSTMENT_CONTROLS = IMAGE_ADJUSTMENT_CONTROLS; exports.IMAGE_EDITOR_SCHEMA_VERSION = IMAGE_EDITOR_SCHEMA_VERSION; exports.IMAGE_EDITOR_STATE_VERSION = IMAGE_EDITOR_STATE_VERSION; exports.ImageEditorController = ImageEditorController; exports.ImageEditorRenderer = ImageEditorRenderer; exports.LATEST_PROCESS_VERSION = LATEST_PROCESS_VERSION; exports.LAYERED_SCHEMA_VERSION = LAYERED_SCHEMA_VERSION; exports.LEGACY_PROCESS_VERSION = LEGACY_PROCESS_VERSION; exports.LUMA_709 = LUMA_709; exports.LayerCompositor = LayerCompositor; exports.LayerOperationError = LayerOperationError; exports.MAX_BRUSH_SIZE = _chunkPDCITYBTcjs.MAX_BRUSH_SIZE; exports.MAX_KELVIN = MAX_KELVIN; exports.MIN_KELVIN = MIN_KELVIN; exports.MIRED_PER_TEMPERATURE_UNIT = MIRED_PER_TEMPERATURE_UNIT; exports.PAINT_TOOLS = PAINT_TOOLS; exports.PSD_BLEND_KEYS = PSD_BLEND_KEYS; exports.PSD_FILE_ACCEPT = PSD_FILE_ACCEPT; exports.PaintGesture = PaintGesture; exports.PaintStrokeSession = PaintStrokeSession; exports.PsdError = PsdError; exports.REFINE_EDGE_CONTROLS = REFINE_EDGE_CONTROLS; exports.SELECTION_MODES = SELECTION_MODES; exports.SELECTION_MODE_LABELS = SELECTION_MODE_LABELS; exports.SELECTION_MODIFY_OPS = SELECTION_MODIFY_OPS; exports.SELECTION_TOOLS = SELECTION_TOOLS; exports.SUPPORTED_ADJUSTMENT_KEYS = SUPPORTED_ADJUSTMENT_KEYS; exports.SelectionGesture = SelectionGesture; exports.StrokeCoverage = _chunkPDCITYBTcjs.StrokeCoverage; exports.SurfaceDraft = _chunkZOOEX3WTcjs.SurfaceDraft; exports.TILE = _chunkZOOEX3WTcjs.TILE; exports.TILE_SHIFT = _chunkZOOEX3WTcjs.TILE_SHIFT; exports.TINT_SCALE = TINT_SCALE; exports.TONE_LUT_SIZE = TONE_LUT_SIZE; exports.TONE_RANGE_PRESETS = TONE_RANGE_PRESETS; exports.TiledSurface = _chunkZOOEX3WTcjs.TiledSurface; exports.VIBRANCE_GREY = VIBRANCE_GREY; exports.XYZ_D50_TO_SRGB = XYZ_D50_TO_SRGB; exports.ZlibError = _chunkH543GD6Tcjs.ZlibError; exports.activeAdjustmentLayers = activeAdjustmentLayers; exports.addLayerFilter = addLayerFilter; exports.addToHistogram = addToHistogram; exports.adjustmentKindLabel = adjustmentKindLabel; exports.adjustmentLayersKey = adjustmentLayersKey; exports.adjustmentNodeAsLayer = adjustmentNodeAsLayer; exports.adjustmentNodeFromLegacy = adjustmentNodeFromLegacy; exports.adler32 = _chunkH543GD6Tcjs.adler32; exports.annotationLayerFor = annotationLayerFor; exports.annotationLayerName = annotationLayerName; exports.applyAdjustmentLayers = applyAdjustmentLayers; exports.applyAdjustments = applyAdjustments; exports.applyBoxBlur = applyBoxBlur; exports.applyDepthMask = applyDepthMask; exports.applyImageProjectionToContext = applyImageProjectionToContext; exports.applyLegacyAdjustments = applyLegacyAdjustments; exports.applyMatrix3 = applyMatrix3; exports.applyOutputStage = applyOutputStage; exports.applyProcess2Adjustments = applyProcess2Adjustments; exports.applyRegionBlur = applyRegionBlur; exports.applyRegionMosaic = applyRegionMosaic; exports.applyStrokeToTile = _chunkPDCITYBTcjs.applyStrokeToTile; exports.backgroundLayer = backgroundLayer; exports.base64ToBytes = _chunkH543GD6Tcjs.base64ToBytes; exports.baseProjection = baseProjection; exports.blackWhiteGray = blackWhiteGray; exports.blendChannel = _chunkZOOEX3WTcjs.blendChannel; exports.blendImageData = _chunkZOOEX3WTcjs.blendImageData; exports.blendLum = _chunkZOOEX3WTcjs.blendLum; exports.blendPixel = _chunkZOOEX3WTcjs.blendPixel; exports.blendRgb = _chunkZOOEX3WTcjs.blendRgb; exports.blendTile = _chunkH543GD6Tcjs.blendTile; exports.blurFilter = blurFilter; exports.borderCoverage = borderCoverage; exports.boxMean = boxMean; exports.boxToCurvePoint = boxToCurvePoint; exports.bradfordAdaptation = bradfordAdaptation; exports.buildLayerMaskPlanes = buildLayerMaskPlanes; exports.buildToneLut = buildToneLut; exports.bytesToBase64 = _chunkH543GD6Tcjs.bytesToBase64; exports.calculateCropDrag = calculateCropDrag; exports.canvasCompositeOperation = _chunkZOOEX3WTcjs.canvasCompositeOperation; exports.canvasToImagePoint = canvasToImagePoint; exports.changedTiles = _chunkH543GD6Tcjs.changedTiles; exports.clampControlValue = clampControlValue; exports.clampCropToImage = clampCropToImage; exports.collectTiles = _chunkZOOEX3WTcjs.collectTiles; exports.colorBalanceChannel = colorBalanceChannel; exports.colorRange = colorRange; exports.combineSelections = combineSelections; exports.compileAdjustmentLayer = compileAdjustmentLayer; exports.computeHistogram = computeHistogram; exports.computeSelectionBounds = computeSelectionBounds; exports.contentBounds = _chunkZOOEX3WTcjs.contentBounds; exports.contractCoverage = contractCoverage; exports.controlPosition = controlPosition; exports.controlTrackBackground = controlTrackBackground; exports.coverageTileCoord = _chunkPDCITYBTcjs.coverageTileCoord; exports.coverageToByte = coverageToByte; exports.coveringRect = coveringRect; exports.createAdjustmentLayer = createAdjustmentLayer; exports.createImageCaptureSurface = createImageCaptureSurface; exports.createImageEditTools = createImageEditTools; exports.createImageEditorToolProvider = createImageEditorToolProvider; exports.createImageLayerTools = createImageLayerTools; exports.createImagePaintTools = createImagePaintTools; exports.createImagePsdTools = createImagePsdTools; exports.createImageSelectionTools = createImageSelectionTools; exports.createSelectionMask = createSelectionMask; exports.curveLut = curveLut; exports.curveLutFromLevels = curveLutFromLevels; exports.curvePointToBox = curvePointToBox; exports.curveSvgPath = curveSvgPath; exports.dabCoverage = _chunkPDCITYBTcjs.dabCoverage; exports.dabRect = _chunkPDCITYBTcjs.dabRect; exports.decodeLayerChannel = decodeLayerChannel; exports.decodeLayerMask = decodeLayerMask; exports.decodeMergedImage = decodeMergedImage; exports.decodePlanes = decodePlanes; exports.decodePng = _chunkH543GD6Tcjs.decodePng; exports.decodePngDataUrl = decodePngDataUrl; exports.decodeSelectionRle = decodeSelectionRle; exports.defaultAdjustmentParams = defaultAdjustmentParams; exports.deflate = _chunkH543GD6Tcjs.deflate; exports.deflateRaw = _chunkH543GD6Tcjs.deflateRaw; exports.depthMaskAlpha = depthMaskAlpha; exports.depthRasterMask = depthRasterMask; exports.describeLayer = describeLayer; exports.describeSelection = describeSelection; exports.deserializeLayer = deserializeLayer; exports.deserializeLayers = deserializeLayers; exports.deserializeSelection = deserializeSelection; exports.developFilter = developFilter; exports.developFromAdjustments = developFromAdjustments; exports.developTarget = developTarget; exports.distanceTransform = distanceTransform; exports.downloadPsd = downloadPsd; exports.dropPlacement = dropPlacement; exports.dropZone = dropZone; exports.duplicateLayer = duplicateLayer; exports.edgeWidth = edgeWidth; exports.ellipsePoints = ellipsePoints; exports.ellipseSelection = ellipseSelection; exports.emptyHistogram = emptyHistogram; exports.emptySurface = _chunkZOOEX3WTcjs.emptySurface; exports.encodePng = _chunkH543GD6Tcjs.encodePng; exports.encodeRle = encodeRle; exports.encodeSelectionRle = encodeSelectionRle; exports.encodeSurface = encodeSurface; exports.evaluateAdjustmentLayers = evaluateAdjustmentLayers; exports.expandCoverage = expandCoverage; exports.exportPsd = exportPsd; exports.featherCoverage = featherCoverage; exports.fillRect = _chunkZOOEX3WTcjs.fillRect; exports.findAdjustmentControl = findAdjustmentControl; exports.findLayer = _chunkH543GD6Tcjs.findLayer; exports.findLayerControl = findLayerControl; exports.finishTile = _chunkZOOEX3WTcjs.finishTile; exports.flattenLayers = _chunkH543GD6Tcjs.flattenLayers; exports.formatControlValue = formatControlValue; exports.fullSelection = fullSelection; exports.gaussianBlur = _chunkH543GD6Tcjs.gaussianBlur; exports.getAnnotationBounds = getAnnotationBounds; exports.getControlPath = getControlPath; exports.getCropCursor = getCropCursor; exports.getRotatedSize = getRotatedSize; exports.getViewportMetrics = getViewportMetrics; exports.getViewportProjection = getViewportProjection; exports.globalImageCache = globalImageCache; exports.greyMorphology = greyMorphology; exports.groupLayers = groupLayers; exports.guidePlanes = guidePlanes; exports.guidedFilterColor = guidedFilterColor; exports.handlePaintShortcut = handlePaintShortcut; exports.hasResampledLegacyMask = hasResampledLegacyMask; exports.hashMaskContent = hashMaskContent; exports.hexToRgb = hexToRgb; exports.histogramPath = histogramPath; exports.hitTestAnnotation = hitTestAnnotation; exports.hitTestCrop = hitTestCrop; exports.hitTestCurvePoint = hitTestCurvePoint; exports.hslToRgb = hslToRgb; exports.hueRange = hueRange; exports.hueRangeTables = hueRangeTables; exports.hueRangeWeight = hueRangeWeight; exports.hueSaturation = hueSaturation; exports.identityCurve = identityCurve; exports.identityLevels = identityLevels; exports.imageEditorStateMigrations = imageEditorStateMigrations; exports.imageToCanvasPoint = imageToCanvasPoint; exports.importPsd = importPsd; exports.inflate = _chunkH543GD6Tcjs.inflate; exports.inflateRaw = _chunkH543GD6Tcjs.inflateRaw; exports.insertCurvePoint = insertCurvePoint; exports.insertLayer = _chunkH543GD6Tcjs.insertLayer; exports.invertMatrix3 = invertMatrix3; exports.invertSelection = invertSelection; exports.isActiveFilter = isActiveFilter; exports.isAdjustmentKind = isAdjustmentKind; exports.isBlendMode = _chunkZOOEX3WTcjs.isBlendMode; exports.isDefaultDepthMask = isDefaultDepthMask; exports.isLayerLocked = _chunkH543GD6Tcjs.isLayerLocked; exports.isLegacyShape = isLegacyShape; exports.isPaintTool = isPaintTool; exports.isPng = _chunkH543GD6Tcjs.isPng; exports.isQuarterTurn = isQuarterTurn; exports.isQuarterTurnSwapped = isQuarterTurnSwapped; exports.isSelectionEmpty = isSelectionEmpty; exports.isSelectionMode = isSelectionMode; exports.isSeparableBlendMode = _chunkZOOEX3WTcjs.isSeparableBlendMode; exports.isSpatialFilter = isSpatialFilter; exports.kelvinToTemperature = kelvinToTemperature; exports.layerBadge = layerBadge; exports.layerLabel = layerLabel; exports.layerMaskCoverage = layerMaskCoverage; exports.layerMaskFromSelection = layerMaskFromSelection; exports.layerMaskKey = layerMaskKey; exports.layerMenu = layerMenu; exports.layerName = layerName; exports.layerPanelRows = layerPanelRows; exports.layerTree = layerTree; exports.layerTypeLabel = layerTypeLabel; exports.layersFromLegacy = layersFromLegacy; exports.legacyAdjustmentLayer = legacyAdjustmentLayer; exports.legacyMaskOf = legacyMaskOf; exports.legacyView = legacyView; exports.levelsValue = levelsValue; exports.linearSrgbToXy = linearSrgbToXy; exports.linearToSrgb = linearToSrgb; exports.loadImageEditorDocument = loadImageEditorDocument; exports.magicWand = magicWand; exports.mapCropHandle = mapCropHandle; exports.mapLayer = _chunkH543GD6Tcjs.mapLayer; exports.maskSummary = maskSummary; exports.migrateSerializedImageEditorState = migrateSerializedImageEditorState; exports.migrateToLayeredState = migrateToLayeredState; exports.modifySelection = modifySelection; exports.moveCurvePoint = moveCurvePoint; exports.moveLayer = moveLayer; exports.mulMatrix3 = mulMatrix3; exports.needsLegacyBase = needsLegacyBase; exports.neutralHueRange = neutralHueRange; exports.newLayerId = newLayerId; exports.normalizeAdjustmentLayer = normalizeAdjustmentLayer; exports.normalizeAdjustmentLayers = normalizeAdjustmentLayers; exports.normalizeAngle = normalizeAngle; exports.normalizeBlendMode = _chunkZOOEX3WTcjs.normalizeBlendMode; exports.normalizeBrush = _chunkPDCITYBTcjs.normalizeBrush; exports.normalizeFilter = normalizeFilter; exports.normalizeLayerMask = normalizeLayerMask; exports.normalizeProcessVersion = normalizeProcessVersion; exports.normalizeRect = normalizeRect; exports.normalizeRefineEdgeParams = normalizeRefineEdgeParams; exports.normalizeStoredAdjustments = normalizeStoredAdjustments; exports.offsetLayer = offsetLayer; exports.openPsdFile = openPsdFile; exports.packRgba = _chunkZOOEX3WTcjs.packRgba; exports.parseAdjustmentBlock = parseAdjustmentBlock; exports.parseBlend = parseBlend; exports.parseColor = parseColor; exports.parseDataUrl = _chunkH543GD6Tcjs.parseDataUrl; exports.parseSelectionMode = parseSelectionMode; exports.parseVersionedDescriptor = parseVersionedDescriptor; exports.photoFilterMatrix = photoFilterMatrix; exports.pixelLayerBounds = pixelLayerBounds; exports.pixelLayers = pixelLayers; exports.placeLayer = placeLayer; exports.pngDataUrl = _chunkH543GD6Tcjs.pngDataUrl; exports.pointerPressure = pointerPressure; exports.polygonCoverage = polygonCoverage; exports.polygonSelection = polygonSelection; exports.posterizeValue = posterizeValue; exports.projectImagePoint = projectImagePoint; exports.projectImageRect = projectImageRect; exports.projectMaskCoverage = projectMaskCoverage; exports.projectQuarterTurn = projectQuarterTurn; exports.psdBytesFromBase64 = psdBytesFromBase64; exports.psdFileName = psdFileName; exports.psdToLayers = psdToLayers; exports.quickMaskPixels = quickMaskPixels; exports.rangeLightness = rangeLightness; exports.rasterMaskFromLegacy = rasterMaskFromLegacy; exports.rasterizeDab = _chunkPDCITYBTcjs.rasterizeDab; exports.readAdjustmentControls = readAdjustmentControls; exports.readPixel = _chunkZOOEX3WTcjs.readPixel; exports.readPsd = readPsd; exports.readRegion = _chunkZOOEX3WTcjs.readRegion; exports.rectSelection = rectSelection; exports.refineCoverage = refineCoverage; exports.refineEdgeHalo = refineEdgeHalo; exports.refineSelection = refineSelection; exports.removeAlpha = removeAlpha; exports.removeCurvePoint = removeCurvePoint; exports.removeLayer = removeLayer; exports.removeLayerFilter = removeLayerFilter; exports.renderLayeredBase = renderLayeredBase; exports.requireLayer = requireLayer; exports.requireUnlocked = requireUnlocked; exports.resizePixels = resizePixels; exports.resizeSelection = resizeSelection; exports.resolveExternalAssets = resolveExternalAssets; exports.resolveMosaicRegionBounds = resolveMosaicRegionBounds; exports.rgbToGray = rgbToGray; exports.rgbToHsl = rgbToHsl; exports.runLayerMenuAction = runLayerMenuAction; exports.sampleLut = sampleLut; exports.sampleToneLut = sampleToneLut; exports.selectionArea = selectionArea; exports.selectionFromCoverage = selectionFromCoverage; exports.selectionFromPixels = selectionFromPixels; exports.selectionModeFromModifiers = selectionModeFromModifiers; exports.selectionOutline = selectionOutline; exports.selectionToCoverage = selectionToCoverage; exports.selectionToPixels = selectionToPixels; exports.selectionValueAt = selectionValueAt; exports.serializeLayer = serializeLayer; exports.serializeLayers = serializeLayers; exports.serializeLayersExternal = serializeLayersExternal; exports.serializeSelection = serializeSelection; exports.setControlPath = setControlPath; exports.setLayerMask = setLayerMask; exports.setLayerProperties = setLayerProperties; exports.setLum = _chunkZOOEX3WTcjs.setLum; exports.shiftCoverage = shiftCoverage; exports.smoothCoverage = smoothCoverage; exports.smoothPoints = _chunkPDCITYBTcjs.smoothPoints; exports.solidSurface = _chunkZOOEX3WTcjs.solidSurface; exports.splitOverlayAnnotations = splitOverlayAnnotations; exports.srgb8ToLab = srgb8ToLab; exports.srgbToLinear = srgbToLinear; exports.sumHistograms = sumHistograms; exports.surfaceBytes = _chunkZOOEX3WTcjs.surfaceBytes; exports.surfaceFromPixels = _chunkZOOEX3WTcjs.surfaceFromPixels; exports.surfacesEqual = _chunkZOOEX3WTcjs.surfacesEqual; exports.tempTintToXy = tempTintToXy; exports.temperatureToKelvin = temperatureToKelvin; exports.tileCoord = _chunkZOOEX3WTcjs.tileCoord; exports.tileKey = _chunkZOOEX3WTcjs.tileKey; exports.tileRect = _chunkZOOEX3WTcjs.tileRect; exports.tilesInRect = _chunkZOOEX3WTcjs.tilesInRect; exports.tipFalloff = _chunkPDCITYBTcjs.tipFalloff; exports.tipReach = _chunkPDCITYBTcjs.tipReach; exports.tipShape = _chunkPDCITYBTcjs.tipShape; exports.toHex = toHex2; exports.toneCurve = toneCurve; exports.toneLuts = toneLuts; exports.toneRange = toneRange; exports.translateSurface = _chunkZOOEX3WTcjs.translateSurface; exports.ungroupLayer = ungroupLayer; exports.uniformTile = _chunkZOOEX3WTcjs.uniformTile; exports.unionRect = unionRect; exports.unprojectCanvasPoint = unprojectCanvasPoint; exports.updateLayerFilter = updateLayerFilter; exports.updateLayerMaskProps = updateLayerMaskProps; exports.uvToXy = uvToXy; exports.versionedDescriptorBytes = versionedDescriptorBytes; exports.vibranceLinear = vibranceLinear; exports.vibrancePixel = vibrancePixel; exports.walkDabs = _chunkPDCITYBTcjs.walkDabs; exports.wbMatrix = wbMatrix; exports.whiteBalanceFromSample = whiteBalanceFromSample; exports.whiteBalanceMatrix = whiteBalanceMatrix; exports.withNewIds = withNewIds; exports.writeAdjustmentBlock = writeAdjustmentBlock; exports.writePsd = writePsd; exports.writeRegion = _chunkZOOEX3WTcjs.writeRegion; exports.xyToTempTint = xyToTempTint; exports.xyToUv = xyToUv;
|
|
10147
12741
|
//# sourceMappingURL=index.cjs.map
|