@pixerate/editor 0.89.0 → 0.91.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.
@@ -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 clamp2 = (v) => Math.max(-100, Math.min(100, v));
275
- return { temperature: clamp2(kelvinToTemperature(kelvin)), tint: clamp2(tint) };
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 q = 0; q < width; q++) {
1005
- const dq = vertical[row + q];
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 * (q - p)) + (q + p) * 0.5;
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] = q;
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 q = quantum;
1555
- const vq = Math.round(v * q) / q;
1556
- u = Math.floor(clamp01((vq - ch.inBlack) / range) * q + 0.5 + 1e-3) / q;
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 q = l < 0.5 ? l * (1 + s) : l + s - l * s;
1591
- const p = 2 * l - q;
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 + (q - p) * 6 * t;
1595
- if (t < 0.5) return q;
1596
- if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
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, q, r0, ra, rt] = VIBRANCE_BOOST;
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, q) * Math.exp((r0 + ra * a + rt * (1 - t)) * Math.max(0, 1 - mx));
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, q) => p.top - q.top);
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 q = guidedFilterColor(guide, m, w, h, r);
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, q[i]));
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', _93 => _93.tiles, 'access', _94 => _94.get, 'call', _95 => _95(key), 'optionalAccess', _96 => _96.data]), () => ( defaultTile(base)));
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 = (_class4 = class {
5004
- constructor(controller, target, stroke, apply) {;_class4.prototype.__init24.call(this);_class4.prototype.__init25.call(this);_class4.prototype.__init26.call(this);
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
- __init24() {this.touched = /* @__PURE__ */ new Set()}
5021
- __init25() {this.last = null}
5022
- __init26() {this.closed = false}
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', _97 => _97.base, 'access', _98 => _98.tiles, 'access', _99 => _99.get, 'call', _100 => _100(key), 'optionalAccess', _101 => _101.data]), () => ( defaultTile(this.base)));
5045
- const prev = this.touched.has(key) ? _optionalChain([this, 'access', _102 => _102.live, 'access', _103 => _103.get, 'call', _104 => _104(key), 'optionalAccess', _105 => _105.data]) : void 0;
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
- }, _class4);
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', _106 => _106.layers, 'optionalAccess', _107 => _107.length]) ? 2 : 1,
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', _108 => _108.depthMask, 'optionalAccess', _109 => _109.depthRange]), () => ( DEFAULT_DEPTH_MASK.depthRange))]
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 = (_class5 = class {
7263
+ var ImageEditorController = (_class7 = class {
5153
7264
 
5154
7265
 
5155
- __init27() {this.imageElement = null}
5156
- __init28() {this.listeners = /* @__PURE__ */ new Set()}
5157
- __init29() {this.histogramListeners = /* @__PURE__ */ new Set()}
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
- __init30() {this.undoStack = []}
5161
- __init31() {this.redoStack = []}
7271
+ __init34() {this.undoStack = []}
7272
+ __init35() {this.redoStack = []}
5162
7273
 
5163
7274
 
5164
- __init32() {this.isApplyingHistory = false}
7275
+ __init36() {this.isApplyingHistory = false}
5165
7276
 
5166
7277
  /** Pixels the selection tools sample (host-provided or read back from the source). */
5167
- __init33() {this.samplePixels = null}
5168
- __init34() {this.samplePixelsOverride = false}
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
- __init35() {this.sourceSurfaces = /* @__PURE__ */ new WeakMap()}
5171
- __init36() {this.viewKey = []}
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
- __init37() {this.compositor = new LayerCompositor()}
5174
- constructor(options = {}) {;_class5.prototype.__init27.call(this);_class5.prototype.__init28.call(this);_class5.prototype.__init29.call(this);_class5.prototype.__init30.call(this);_class5.prototype.__init31.call(this);_class5.prototype.__init32.call(this);_class5.prototype.__init33.call(this);_class5.prototype.__init34.call(this);_class5.prototype.__init35.call(this);_class5.prototype.__init36.call(this);_class5.prototype.__init37.call(this);_class5.prototype.__init38.call(this);_class5.prototype.__init39.call(this);_class5.prototype.__init40.call(this);_class5.prototype.__init41.call(this);_class5.prototype.__init42.call(this);_class5.prototype.__init43.call(this);_class5.prototype.__init44.call(this);
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', _110 => _110.initialState, 'optionalAccess', _111 => _111.selection])) {
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 (e12) {
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 (e13) {
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
- __init38() {this.pendingDirty = "all"}
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', _112 => _112.onStateChange, 'optionalCall', _113 => _113(currentState)]);
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', _114 => _114.layer]);
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', _115 => _115.mask]) ? "mask" : "pixels";
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
- __init39() {this.boundsCache = /* @__PURE__ */ new WeakMap()}
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
- __init40() {this.sourceIds = /* @__PURE__ */ new WeakMap()}
5575
- __init41() {this.nextSourceId = 1}
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
- __init42() {this.opaqueCache = /* @__PURE__ */ new WeakMap()}
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', _116 => _116.data]) || data.data.length < width * height * 4) return null;
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 (e14) {
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', _117 => _117()]);
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', _118 => _118.name, 'optionalAccess', _119 => _119.trim, 'call', _120 => _120()]) || this.nextLayerName(),
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', _121 => _121.bytes]), () => ( null));
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 (e15) {
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 (e16) {
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 (e17) {
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', _122 => _122.parent, 'optionalAccess', _123 => _123.id]), () => ( null)), index: loc.index };
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', _124 => _124.parent, 'optionalAccess', _125 => _125.id]), () => ( null)), index: loc.index };
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', _126 => _126.name, 'optionalAccess', _127 => _127.trim, 'call', _128 => _128()]) || "Group",
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', _129 => _129.bounds])) throw new LayerOperationError("Nothing is selected; select first, or use reveal-all / hide-all.");
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', _130 => _130.bounds])) throw new LayerOperationError("Nothing is selected; select the pixels to copy first.");
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', _131 => _131.name, 'optionalAccess', _132 => _132.trim, 'call', _133 => _133()]) || `${layer.name || "Layer"} ${options.cut ? "cut" : "copy"}`,
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', _134 => _134.parent, 'optionalAccess', _135 => _135.id]), () => ( null)), loc.index + 1);
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
- __init43() {this.thumbCache = /* @__PURE__ */ new WeakMap()}
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', _136 => _136.get, 'call', _137 => _137(key)]);
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 ? toHex(parseColor(options.foreground)) : cur.foreground,
6141
- background: options.background !== void 0 ? toHex(parseColor(options.background)) : cur.background
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', _138 => _138.locks, 'optionalAccess', _139 => _139.transparency]));
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', _140 => _140.state, 'access', _141 => _141.selection, 'optionalAccess', _142 => _142.bounds]) ? this.state.selection : null,
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', _143 => _143.x])) || !Number.isFinite(_optionalChain([p, 'optionalAccess', _144 => _144.y]))) throw new LayerOperationError("Every point needs finite x and y (document pixels).");
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', _145 => _145.state, 'access', _146 => _146.selection, 'optionalAccess', _147 => _147.bounds]) ? this.state.selection : null;
6269
- const region = _nullishCoalesce(_optionalChain([sel, 'optionalAccess', _148 => _148.bounds]), () => ( { x: 0, y: 0, width, height }));
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', _149 => _149.parent, 'optionalAccess', _150 => _150.id]), () => ( null)), loc.index + 1);
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', _151 => _151.parent, 'optionalAccess', _152 => _152.id]), () => ( null)), loc.index);
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', _153 => _153.parent, 'optionalAccess', _154 => _154.id]), () => ( null)), loc.index + 1);
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', _155 => _155.parent, 'optionalAccess', _156 => _156.id]), () => ( null)), to > from ? loc.index + 1 : loc.index);
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', _157 => _157.state, 'access', _158 => _158.selection, 'optionalAccess', _159 => _159.bounds]));
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', _160 => _160.getImageData, 'optionalCall', _161 => _161(0, 0, width, height)]);
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 (e18) {
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
- if (!options.sampleMerged) return base;
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 (legacyView(this.stack(), width, height, null).exact) {
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 data = new LayerCompositor().composite(withoutAnnotations(this.state.layers), { x: 0, y: 0, width, height }, sources);
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', _162 => _162.bounds])) return false;
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', _163 => _163.bounds])) return false;
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', _164 => _164.getImageData, 'optionalCall', _165 => _165(0, 0, w, h)]);
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', _166 => _166.bounds]) || !this.getAdjustmentLayer(layerId)) return false;
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', _167 => _167.mask]) || layer.mask.source) return false;
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', _168 => _168.mask, 'optionalAccess', _169 => _169.source])) delete next.mask;
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', _170 => _170.mask, 'optionalAccess', _171 => _171.source])) {
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', _172 => _172.parent, 'optionalAccess', _173 => _173.id]), () => ( null)), loc.index + 1) : _chunkH543GD6Tcjs.insertLayer.call(void 0, this.state.layers, layer, null);
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
- async render(targetCanvas, options) {
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 (e19) {
9067
+ } catch (e23) {
6930
9068
  }
6931
9069
  }
6932
9070
  async renderExport(options) {
6933
- const source = this.imageElement || this.state.sourceUrl;
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', _174 => _174.layerIds])) {
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.imageElement || this.state.sourceUrl;
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
- * Replaces the source image with an inpainted result (natural image space, see
7030
- * `toSourceDataURL`) and clears the mask annotations, as ONE undoable step.
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
- await this.replaceSource(newDataUrl, true);
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
- * Replaces the source image with a background-removed result as ONE undoable step.
7037
- * Crop and annotations are kept (rescaled if the new image has different dimensions).
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
- await this.replaceSource(newDataUrl, false);
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
- // --- Serialization ---
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
- * The serializable state. A document whose layers still have the v1 / v2 shape (the
7090
- * Background with its sliders and depth mask, adjustment layers, annotations) is written as
7091
- * v1 / v2 exactly as before; anything else is written as v3 with the layer pixels as PNG
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
- toJSON() {
7095
- const out = this.serializeState();
7096
- if (_optionalChain([this, 'access', _175 => _175.state, 'access', _176 => _176.selection, 'optionalAccess', _177 => _177.bounds])) out.selection = serializeSelection(this.state.selection);
7097
- return out;
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 (e20) {
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
- __init44() {this.lastLoadProblems = []}
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', _178 => _178.adjustments, 'access', _179 => _179.layers, 'optionalAccess', _180 => _180.length]) ? 2 : 1,
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
- }, _class5);
9576
+ }, _class7);
7183
9577
  function serializeAdjustments(adjustments) {
7184
9578
  const out = { ...adjustments };
7185
- if (_optionalChain([out, 'access', _181 => _181.layers, 'optionalAccess', _182 => _182.length])) out.layers = JSON.parse(JSON.stringify(out.layers));
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', _183 => _183.filters, 'optionalAccess', _184 => _184.find, 'call', _185 => _185((f) => f.kind === "blur")]);
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', _186 => _186.id]), () => ( (layer.source === "document" ? BLUR_FILTER_ID : newLayerId("flt")))),
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 toHex(c) {
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', _187 => _187.bounds]) ? mask : null;
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 (e21) {
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', _188 => _188.adjustments, 'access', _189 => _189.layers, 'optionalAccess', _190 => _190.length])) state.version = 2;
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 levelsRecord = (ch, label) => [
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
- ...levelsRecord("master", "RGB"),
7637
- ...levelsRecord("red", "Red"),
7638
- ...levelsRecord("green", "Green"),
7639
- ...levelsRecord("blue", "Blue")
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', _191 => _191[kind], 'optionalAccess', _192 => _192.find, 'call', _193 => _193((c) => c.id === id)]);
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', _194 => _194.bounds]), () => ( null)),
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 = { mode: parseSelectionMode(mode), sampleMerged: sampleMerged === true };
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', _195 => _195.bounds]) && selection.width === state.imageDimensions.width && selection.height === state.imageDimensions.height) {
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', _196 => _196.getState, 'call', _197 => _197(), 'access', _198 => _198.selection, 'optionalAccess', _199 => _199.bounds]), () => ( null)) }),
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', _200 => _200.parent, 'optionalAccess', _201 => _201.id]), () => ( null)),
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', _202 => _202.getLayer, 'call', _203 => _203(parentId), 'optionalAccess', _204 => _204.type]) !== "group") throw new Error(`Layer "${parentId}" is not a group.`);
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((q) => q.input !== point.input).map((q) => ({ ...q }));
9246
- let index = out.findIndex((q) => q.input > point.input);
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((q) => ({ ...q }));
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((q) => ({ ...q }));
9261
- return points.filter((_, i) => i !== index).map((q) => ({ ...q }));
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 = (_class6 = class {
9267
- constructor(controller, getOptions) {;_class6.prototype.__init45.call(this);_class6.prototype.__init46.call(this);_class6.prototype.__init47.call(this);_class6.prototype.__init48.call(this);_class6.prototype.__init49.call(this);
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
- __init45() {this.start = null}
9274
- __init46() {this.points = []}
9275
- __init47() {this.current = null}
9276
- __init48() {this.modifiers = {}}
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
- __init49() {this.error = null}
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
- }, _class6);
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', _205 => _205.type]) === "pixel";
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', _206 => _206.type]) === "group" },
9568
- { action: "merge-down", label: "Merge Down", enabled: Boolean(_optionalChain([active, 'optionalAccess', _207 => _207.visible]) && _optionalChain([below, 'optionalAccess', _208 => _208.type]) === "pixel") },
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', _209 => _209.mask])) },
9576
- { action: "delete-mask", label: "Delete Layer Mask", enabled: Boolean(_optionalChain([active, 'optionalAccess', _210 => _210.mask])) },
9577
- { action: "toggle-mask", label: _optionalChain([active, 'optionalAccess', _211 => _211.mask, 'optionalAccess', _212 => _212.enabled]) === false ? "Enable Layer Mask" : "Disable Layer Mask", enabled: Boolean(_optionalChain([active, 'optionalAccess', _213 => _213.mask])) },
9578
- { action: "toggle-clip", label: _optionalChain([active, 'optionalAccess', _214 => _214.clipped]) ? "Release Clipping Mask" : "Create Clipping Mask", enabled: Boolean(loc && loc.index > 0) }
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', _215 => _215.id]);
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', _216 => _216.mask])) controller.setLayerMaskProps(id, { enabled: active.mask.enabled === false });
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', _217 => _217.clipped]) });
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 = (_class7 = class {
9707
- constructor(controller) {;_class7.prototype.__init50.call(this);_class7.prototype.__init51.call(this);_class7.prototype.__init52.call(this);
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
- __init50() {this.stroke = null}
9712
- __init51() {this.move = null}
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
- __init52() {this.error = null}
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', _218 => _218.locks, 'optionalAccess', _219 => _219.all]) || _optionalChain([layer, 'access', _220 => _220.locks, 'optionalAccess', _221 => _221.position])) throw new Error(`Layer "${layer.name}" has its position locked.`);
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', _222 => _222.stroke, 'optionalAccess', _223 => _223.cancel, 'call', _224 => _224()]);
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
- }, _class7);
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