@pixerate/editor 0.185.0 → 0.186.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.
Files changed (37) hide show
  1. package/dist/{chunk-GYYSPMVU.js → chunk-FW7N64XK.js} +295 -188
  2. package/dist/{chunk-C6TRAAG4.cjs → chunk-X2KQQZBT.cjs} +355 -248
  3. package/dist/image-editor/controller.d.cts +56 -0
  4. package/dist/image-editor/controller.d.ts +56 -0
  5. package/dist/image-editor/index.cjs +1461 -1030
  6. package/dist/image-editor/index.js +447 -16
  7. package/dist/image-editor/layers/model.d.cts +5 -1
  8. package/dist/image-editor/layers/model.d.ts +5 -1
  9. package/dist/image-editor/layers/paint-ui.d.cts +2 -1
  10. package/dist/image-editor/layers/paint-ui.d.ts +2 -1
  11. package/dist/image-editor/layers/serialize.d.cts +3 -0
  12. package/dist/image-editor/layers/serialize.d.ts +3 -0
  13. package/dist/image-editor/psd/channels.d.cts +24 -0
  14. package/dist/image-editor/psd/channels.d.ts +24 -0
  15. package/dist/image-editor/psd/export.d.cts +3 -0
  16. package/dist/image-editor/psd/export.d.ts +3 -0
  17. package/dist/image-editor/psd/import.d.cts +10 -0
  18. package/dist/image-editor/psd/import.d.ts +10 -0
  19. package/dist/image-editor/renderer.d.cts +6 -0
  20. package/dist/image-editor/renderer.d.ts +6 -0
  21. package/dist/image-editor/selection/channels.d.cts +52 -0
  22. package/dist/image-editor/selection/channels.d.ts +52 -0
  23. package/dist/image-editor/selection/gesture.d.cts +7 -0
  24. package/dist/image-editor/selection/gesture.d.ts +7 -0
  25. package/dist/image-editor/selection/index.d.cts +1 -0
  26. package/dist/image-editor/selection/index.d.ts +1 -0
  27. package/dist/image-editor/selection/overlay.d.cts +2 -0
  28. package/dist/image-editor/selection/overlay.d.ts +2 -0
  29. package/dist/image-editor/tools.d.cts +3 -1
  30. package/dist/image-editor/tools.d.ts +3 -1
  31. package/dist/image-editor/types.d.cts +10 -0
  32. package/dist/image-editor/types.d.ts +10 -0
  33. package/dist/paint-editor/index.cjs +6 -6
  34. package/dist/paint-editor/index.js +1 -1
  35. package/package.json +1 -1
  36. package/skills/pixerate-image-editor/SKILL.md +7 -0
  37. package/skills/pixerate-image-selection-masking/SKILL.md +13 -1
@@ -6346,6 +6346,192 @@ function encodeLegacyName(s) {
6346
6346
  return Uint8Array.from(out);
6347
6347
  }
6348
6348
 
6349
+ // src/image-editor/psd/compression.ts
6350
+ var MAX_DECODED_BYTES = 2 ** 31;
6351
+ function rowBytes(width, depth) {
6352
+ return depth === 1 ? Math.ceil(width / 8) : width * Math.max(1, depth >> 3);
6353
+ }
6354
+ function decodedLength(l) {
6355
+ const total = l.planes * l.height * rowBytes(l.width, l.depth);
6356
+ if (total > MAX_DECODED_BYTES) throw new PsdError(`Decoded channel data of ${total} bytes is larger than the ${MAX_DECODED_BYTES}-byte limit.`);
6357
+ return total;
6358
+ }
6359
+ function packbitsBound(n) {
6360
+ return n + Math.ceil(n / 128);
6361
+ }
6362
+ function packbitsEncode(src, out, at) {
6363
+ const n = src.length;
6364
+ let i = 0;
6365
+ while (i < n) {
6366
+ let run = 1;
6367
+ while (i + run < n && run < 128 && src[i + run] === src[i]) run++;
6368
+ if (run >= 2) {
6369
+ out[at++] = 257 - run & 255;
6370
+ out[at++] = src[i];
6371
+ i += run;
6372
+ continue;
6373
+ }
6374
+ const start = i;
6375
+ let len = 0;
6376
+ while (i < n && len < 128) {
6377
+ if (i + 2 < n && src[i] === src[i + 1] && src[i] === src[i + 2]) break;
6378
+ i++;
6379
+ len++;
6380
+ }
6381
+ out[at++] = len - 1;
6382
+ out.set(src.subarray(start, start + len), at);
6383
+ at += len;
6384
+ }
6385
+ return at;
6386
+ }
6387
+ function packbitsDecodeInto(src, expected, out, at) {
6388
+ const target = at + expected;
6389
+ let i = 0;
6390
+ while (at < target) {
6391
+ if (i >= src.length) throw new PsdError("PackBits row ended early.");
6392
+ const h = src[i++];
6393
+ if (h < 128) {
6394
+ const len = h + 1;
6395
+ if (i + len > src.length) throw new PsdError("PackBits literal is truncated.");
6396
+ if (at + len > target) throw new PsdError("PackBits literal overflows its row.");
6397
+ out.set(src.subarray(i, i + len), at);
6398
+ at += len;
6399
+ i += len;
6400
+ } else if (h !== 128) {
6401
+ const len = 257 - h;
6402
+ if (i >= src.length) throw new PsdError("PackBits run is truncated.");
6403
+ const b = src[i++];
6404
+ if (at + len > target) throw new PsdError("PackBits run overflows its row.");
6405
+ out.fill(b, at, at + len);
6406
+ at += len;
6407
+ }
6408
+ }
6409
+ return at;
6410
+ }
6411
+ function inflateChecked(data, expected) {
6412
+ let out;
6413
+ try {
6414
+ out = inflate(data, { maxOutput: expected + (1 << 20), sizeHint: expected, verify: false });
6415
+ } catch (e) {
6416
+ throw new PsdError(`ZIP channel data: ${e instanceof ZlibError || e instanceof Error ? e.message : String(e)}`);
6417
+ }
6418
+ if (out.length < expected) throw new PsdError(`ZIP stream produced ${out.length} of ${expected} bytes.`);
6419
+ return out.length === expected ? out : out.subarray(0, expected);
6420
+ }
6421
+ function unpredict(buf, l) {
6422
+ const rb = rowBytes(l.width, l.depth);
6423
+ if (rb === 0) return;
6424
+ const w = l.width;
6425
+ const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
6426
+ for (let o = 0; o + rb <= buf.length; o += rb) {
6427
+ if (l.depth === 1 || l.depth === 8) {
6428
+ for (let i = 1; i < rb; i++) buf[o + i] = buf[o + i] + buf[o + i - 1] & 255;
6429
+ } else if (l.depth === 16) {
6430
+ for (let i = 1; i < w; i++) {
6431
+ const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
6432
+ const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
6433
+ const v = a + b & 65535;
6434
+ buf[o + 2 * i] = v >> 8;
6435
+ buf[o + 2 * i + 1] = v & 255;
6436
+ }
6437
+ } else if (l.depth === 32) {
6438
+ for (let i = 1; i < rb; i++) buf[o + i] = buf[o + i] + buf[o + i - 1] & 255;
6439
+ scratch.set(buf.subarray(o, o + rb));
6440
+ for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + 4 * i + k] = scratch[k * w + i];
6441
+ } else {
6442
+ throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
6443
+ }
6444
+ }
6445
+ }
6446
+ function decodeRle(r, l, total) {
6447
+ const rows = l.planes * l.height;
6448
+ const rb = rowBytes(l.width, l.depth);
6449
+ r.checkCount(rows, l.psb ? 4 : 2, "RLE row counts");
6450
+ const counts = new Array(rows);
6451
+ for (let i = 0; i < rows; i++) counts[i] = l.psb ? r.u32() : r.u16();
6452
+ if (total > r.remaining * 130) throw new PsdError("RLE data is too short for its declared size.");
6453
+ const out = new Uint8Array(total);
6454
+ let at = 0;
6455
+ for (const c of counts) at = packbitsDecodeInto(r.bytes(c), rb, out, at);
6456
+ return out;
6457
+ }
6458
+ function decodePlanes(compression, data, l) {
6459
+ const total = decodedLength(l);
6460
+ switch (compression) {
6461
+ case 0:
6462
+ if (data.length < total) throw new PsdError(`Raw channel data has ${data.length} of ${total} bytes.`);
6463
+ return data.slice(0, total);
6464
+ case 1:
6465
+ return decodeRle(new PsdReader(data), l, total);
6466
+ case 2:
6467
+ return inflateChecked(data, total).slice();
6468
+ case 3: {
6469
+ const v = inflateChecked(data, total).slice();
6470
+ unpredict(v, l);
6471
+ return v;
6472
+ }
6473
+ default:
6474
+ throw new PsdError(`Unsupported compression method ${compression}.`);
6475
+ }
6476
+ }
6477
+ function encodeRle(decoded2, l) {
6478
+ const rows = l.planes * l.height;
6479
+ const rb = rowBytes(l.width, l.depth);
6480
+ const cs = l.psb ? 4 : 2;
6481
+ const packed = new Uint8Array(rows * packbitsBound(rb));
6482
+ let at = 0;
6483
+ const counts = new Uint8Array(rows * cs);
6484
+ for (let row = 0; row < rows; row++) {
6485
+ const start = at;
6486
+ at = packbitsEncode(decoded2.subarray(row * rb, (row + 1) * rb), packed, at);
6487
+ const n = at - start;
6488
+ if (cs === 2) {
6489
+ if (n > 65535) throw new PsdError("An RLE row is longer than 65535 bytes; write a PSB instead.");
6490
+ counts[row * 2] = n >> 8;
6491
+ counts[row * 2 + 1] = n & 255;
6492
+ } else {
6493
+ counts[row * 4] = n >>> 24;
6494
+ counts[row * 4 + 1] = n >>> 16 & 255;
6495
+ counts[row * 4 + 2] = n >>> 8 & 255;
6496
+ counts[row * 4 + 3] = n & 255;
6497
+ }
6498
+ }
6499
+ const out = new Uint8Array(counts.length + at);
6500
+ out.set(counts);
6501
+ out.set(packed.subarray(0, at), counts.length);
6502
+ return out;
6503
+ }
6504
+ function predict(buf, l) {
6505
+ const rb = rowBytes(l.width, l.depth);
6506
+ if (rb === 0) return;
6507
+ const w = l.width;
6508
+ const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
6509
+ for (let o = 0; o + rb <= buf.length; o += rb) {
6510
+ if (l.depth === 1 || l.depth === 8) {
6511
+ for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
6512
+ } else if (l.depth === 16) {
6513
+ for (let i = w - 1; i > 0; i--) {
6514
+ const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
6515
+ const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
6516
+ const v = a - b & 65535;
6517
+ buf[o + 2 * i] = v >> 8;
6518
+ buf[o + 2 * i + 1] = v & 255;
6519
+ }
6520
+ } else if (l.depth === 32) {
6521
+ scratch.set(buf.subarray(o, o + rb));
6522
+ for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + k * w + i] = scratch[4 * i + k];
6523
+ for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
6524
+ } else {
6525
+ throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
6526
+ }
6527
+ }
6528
+ }
6529
+ function encodeZipPredicted(decoded2, l) {
6530
+ const buf = decoded2.slice();
6531
+ predict(buf, l);
6532
+ return deflate(buf);
6533
+ }
6534
+
6349
6535
  // src/image-editor/psd/descriptor.ts
6350
6536
  var MAX_DEPTH = 64;
6351
6537
  var STRING_IDS = /* @__PURE__ */ new Set(["warp", "list", "time"]);
@@ -6945,6 +7131,97 @@ function writeAdjustmentBlock(kind, params) {
6945
7131
  throw new Error(`Unknown adjustment kind "${kind}".`);
6946
7132
  }
6947
7133
 
7134
+ // src/image-editor/psd/channels.ts
7135
+ var hexToRgb2 = (hex) => {
7136
+ const v = parseInt(/^#?([0-9a-f]{6})$/i.exec(hex)?.[1] ?? "ff0000", 16);
7137
+ return [v >> 16 & 255, v >> 8 & 255, v & 255];
7138
+ };
7139
+ var rgbToHex = (r, g, b) => `#${[r, g, b].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
7140
+ function alphaChannelResources(channels) {
7141
+ if (!channels.length) return [];
7142
+ const names = new PsdWriter();
7143
+ for (const c of channels) names.pascal(encodeLegacyName(c.name), 1);
7144
+ const unicode = new PsdWriter();
7145
+ for (const c of channels) unicode.unicode(c.name);
7146
+ const display = new PsdWriter();
7147
+ display.u32(1);
7148
+ for (const c of channels) {
7149
+ const [r, g, b] = hexToRgb2(c.color);
7150
+ display.u16(0);
7151
+ for (const v of [r, g, b, 0]) display.u16(v * 257);
7152
+ display.u16(Math.round(Math.min(1, Math.max(0, c.opacity)) * 100));
7153
+ display.u8(c.indicates === "selected" ? 0 : 1);
7154
+ display.u8(0);
7155
+ }
7156
+ return [
7157
+ { id: 1006, name: "", data: names.result() },
7158
+ { id: 1045, name: "", data: unicode.result() },
7159
+ { id: 1077, name: "", data: display.result() }
7160
+ ];
7161
+ }
7162
+ function planeTo8(plane, n, depth) {
7163
+ if (depth === 8) return plane.slice(0, n);
7164
+ const out = new Uint8Array(n);
7165
+ const view = new DataView(plane.buffer, plane.byteOffset, plane.byteLength);
7166
+ for (let i = 0; i < n; i++) {
7167
+ if (depth === 16) out[i] = plane[2 * i];
7168
+ else out[i] = Math.round(Math.min(1, Math.max(0, view.getFloat32(4 * i, false))) * 255);
7169
+ }
7170
+ return out;
7171
+ }
7172
+ function readAlphaChannels(planes, header, first, resource2, warn) {
7173
+ const count = header.channels - first;
7174
+ if (count <= 0 || header.depth === 1) return [];
7175
+ const size = rowBytes(header.width, header.depth) * header.height;
7176
+ const n = header.width * header.height;
7177
+ const names = [];
7178
+ const unicode = resource2(1045);
7179
+ if (unicode) {
7180
+ const r = new PsdReader(unicode);
7181
+ while (r.remaining >= 4 && names.length < count) names.push(r.unicode().replace(/\0+$/, ""));
7182
+ } else {
7183
+ const legacy = resource2(1006);
7184
+ if (legacy) {
7185
+ const r = new PsdReader(legacy);
7186
+ while (r.remaining >= 1 && names.length < count) names.push(new TextDecoder("latin1").decode(r.pascal(1)));
7187
+ }
7188
+ }
7189
+ const display = [];
7190
+ const info = resource2(1077);
7191
+ if (info && info.length >= 4) {
7192
+ const r = new PsdReader(info);
7193
+ r.u32();
7194
+ while (r.remaining >= 14 && display.length < count) {
7195
+ r.u16();
7196
+ const [cr, cg, cb] = [r.u16(), r.u16(), r.u16()];
7197
+ r.u16();
7198
+ const opacity = r.u16();
7199
+ const kind = r.u8();
7200
+ r.u8();
7201
+ display.push({ color: rgbToHex(cr >> 8, cg >> 8, cb >> 8), opacity: Math.min(100, opacity) / 100, kind });
7202
+ }
7203
+ }
7204
+ const out = [];
7205
+ for (let i = 0; i < count; i++) {
7206
+ const start = (first + i) * size;
7207
+ if (start + size > planes.length) break;
7208
+ const d = display[i];
7209
+ const name = names[i] || `Alpha ${i + 1}`;
7210
+ if (d?.kind === 2) {
7211
+ warn(`Spot colour channel "${name}" is not supported and was left out.`);
7212
+ continue;
7213
+ }
7214
+ out.push({
7215
+ name,
7216
+ data: planeTo8(planes.subarray(start, start + size), n, header.depth),
7217
+ color: d?.color ?? "#ff0000",
7218
+ opacity: d?.opacity ?? 0.5,
7219
+ indicates: d?.kind === 0 ? "selected" : "masked"
7220
+ });
7221
+ }
7222
+ return out;
7223
+ }
7224
+
6948
7225
  // src/image-editor/psd/paths.ts
6949
7226
  var RECORD = 26;
6950
7227
  var fixed = (v) => v / 16777216;
@@ -8129,192 +8406,6 @@ function tyShForLayer(layer) {
8129
8406
  return writeTySh({ transform: textMatrix(layer), text: text3, warp, tail: new Uint8Array(16) });
8130
8407
  }
8131
8408
 
8132
- // src/image-editor/psd/compression.ts
8133
- var MAX_DECODED_BYTES = 2 ** 31;
8134
- function rowBytes(width, depth) {
8135
- return depth === 1 ? Math.ceil(width / 8) : width * Math.max(1, depth >> 3);
8136
- }
8137
- function decodedLength(l) {
8138
- const total = l.planes * l.height * rowBytes(l.width, l.depth);
8139
- if (total > MAX_DECODED_BYTES) throw new PsdError(`Decoded channel data of ${total} bytes is larger than the ${MAX_DECODED_BYTES}-byte limit.`);
8140
- return total;
8141
- }
8142
- function packbitsBound(n) {
8143
- return n + Math.ceil(n / 128);
8144
- }
8145
- function packbitsEncode(src, out, at) {
8146
- const n = src.length;
8147
- let i = 0;
8148
- while (i < n) {
8149
- let run = 1;
8150
- while (i + run < n && run < 128 && src[i + run] === src[i]) run++;
8151
- if (run >= 2) {
8152
- out[at++] = 257 - run & 255;
8153
- out[at++] = src[i];
8154
- i += run;
8155
- continue;
8156
- }
8157
- const start = i;
8158
- let len = 0;
8159
- while (i < n && len < 128) {
8160
- if (i + 2 < n && src[i] === src[i + 1] && src[i] === src[i + 2]) break;
8161
- i++;
8162
- len++;
8163
- }
8164
- out[at++] = len - 1;
8165
- out.set(src.subarray(start, start + len), at);
8166
- at += len;
8167
- }
8168
- return at;
8169
- }
8170
- function packbitsDecodeInto(src, expected, out, at) {
8171
- const target = at + expected;
8172
- let i = 0;
8173
- while (at < target) {
8174
- if (i >= src.length) throw new PsdError("PackBits row ended early.");
8175
- const h = src[i++];
8176
- if (h < 128) {
8177
- const len = h + 1;
8178
- if (i + len > src.length) throw new PsdError("PackBits literal is truncated.");
8179
- if (at + len > target) throw new PsdError("PackBits literal overflows its row.");
8180
- out.set(src.subarray(i, i + len), at);
8181
- at += len;
8182
- i += len;
8183
- } else if (h !== 128) {
8184
- const len = 257 - h;
8185
- if (i >= src.length) throw new PsdError("PackBits run is truncated.");
8186
- const b = src[i++];
8187
- if (at + len > target) throw new PsdError("PackBits run overflows its row.");
8188
- out.fill(b, at, at + len);
8189
- at += len;
8190
- }
8191
- }
8192
- return at;
8193
- }
8194
- function inflateChecked(data, expected) {
8195
- let out;
8196
- try {
8197
- out = inflate(data, { maxOutput: expected + (1 << 20), sizeHint: expected, verify: false });
8198
- } catch (e) {
8199
- throw new PsdError(`ZIP channel data: ${e instanceof ZlibError || e instanceof Error ? e.message : String(e)}`);
8200
- }
8201
- if (out.length < expected) throw new PsdError(`ZIP stream produced ${out.length} of ${expected} bytes.`);
8202
- return out.length === expected ? out : out.subarray(0, expected);
8203
- }
8204
- function unpredict(buf, l) {
8205
- const rb = rowBytes(l.width, l.depth);
8206
- if (rb === 0) return;
8207
- const w = l.width;
8208
- const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
8209
- for (let o = 0; o + rb <= buf.length; o += rb) {
8210
- if (l.depth === 1 || l.depth === 8) {
8211
- for (let i = 1; i < rb; i++) buf[o + i] = buf[o + i] + buf[o + i - 1] & 255;
8212
- } else if (l.depth === 16) {
8213
- for (let i = 1; i < w; i++) {
8214
- const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
8215
- const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
8216
- const v = a + b & 65535;
8217
- buf[o + 2 * i] = v >> 8;
8218
- buf[o + 2 * i + 1] = v & 255;
8219
- }
8220
- } else if (l.depth === 32) {
8221
- for (let i = 1; i < rb; i++) buf[o + i] = buf[o + i] + buf[o + i - 1] & 255;
8222
- scratch.set(buf.subarray(o, o + rb));
8223
- for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + 4 * i + k] = scratch[k * w + i];
8224
- } else {
8225
- throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
8226
- }
8227
- }
8228
- }
8229
- function decodeRle(r, l, total) {
8230
- const rows = l.planes * l.height;
8231
- const rb = rowBytes(l.width, l.depth);
8232
- r.checkCount(rows, l.psb ? 4 : 2, "RLE row counts");
8233
- const counts = new Array(rows);
8234
- for (let i = 0; i < rows; i++) counts[i] = l.psb ? r.u32() : r.u16();
8235
- if (total > r.remaining * 130) throw new PsdError("RLE data is too short for its declared size.");
8236
- const out = new Uint8Array(total);
8237
- let at = 0;
8238
- for (const c of counts) at = packbitsDecodeInto(r.bytes(c), rb, out, at);
8239
- return out;
8240
- }
8241
- function decodePlanes(compression, data, l) {
8242
- const total = decodedLength(l);
8243
- switch (compression) {
8244
- case 0:
8245
- if (data.length < total) throw new PsdError(`Raw channel data has ${data.length} of ${total} bytes.`);
8246
- return data.slice(0, total);
8247
- case 1:
8248
- return decodeRle(new PsdReader(data), l, total);
8249
- case 2:
8250
- return inflateChecked(data, total).slice();
8251
- case 3: {
8252
- const v = inflateChecked(data, total).slice();
8253
- unpredict(v, l);
8254
- return v;
8255
- }
8256
- default:
8257
- throw new PsdError(`Unsupported compression method ${compression}.`);
8258
- }
8259
- }
8260
- function encodeRle(decoded2, l) {
8261
- const rows = l.planes * l.height;
8262
- const rb = rowBytes(l.width, l.depth);
8263
- const cs = l.psb ? 4 : 2;
8264
- const packed = new Uint8Array(rows * packbitsBound(rb));
8265
- let at = 0;
8266
- const counts = new Uint8Array(rows * cs);
8267
- for (let row = 0; row < rows; row++) {
8268
- const start = at;
8269
- at = packbitsEncode(decoded2.subarray(row * rb, (row + 1) * rb), packed, at);
8270
- const n = at - start;
8271
- if (cs === 2) {
8272
- if (n > 65535) throw new PsdError("An RLE row is longer than 65535 bytes; write a PSB instead.");
8273
- counts[row * 2] = n >> 8;
8274
- counts[row * 2 + 1] = n & 255;
8275
- } else {
8276
- counts[row * 4] = n >>> 24;
8277
- counts[row * 4 + 1] = n >>> 16 & 255;
8278
- counts[row * 4 + 2] = n >>> 8 & 255;
8279
- counts[row * 4 + 3] = n & 255;
8280
- }
8281
- }
8282
- const out = new Uint8Array(counts.length + at);
8283
- out.set(counts);
8284
- out.set(packed.subarray(0, at), counts.length);
8285
- return out;
8286
- }
8287
- function predict(buf, l) {
8288
- const rb = rowBytes(l.width, l.depth);
8289
- if (rb === 0) return;
8290
- const w = l.width;
8291
- const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
8292
- for (let o = 0; o + rb <= buf.length; o += rb) {
8293
- if (l.depth === 1 || l.depth === 8) {
8294
- for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
8295
- } else if (l.depth === 16) {
8296
- for (let i = w - 1; i > 0; i--) {
8297
- const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
8298
- const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
8299
- const v = a - b & 65535;
8300
- buf[o + 2 * i] = v >> 8;
8301
- buf[o + 2 * i + 1] = v & 255;
8302
- }
8303
- } else if (l.depth === 32) {
8304
- scratch.set(buf.subarray(o, o + rb));
8305
- for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + k * w + i] = scratch[4 * i + k];
8306
- for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
8307
- } else {
8308
- throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
8309
- }
8310
- }
8311
- }
8312
- function encodeZipPredicted(decoded2, l) {
8313
- const buf = decoded2.slice();
8314
- predict(buf, l);
8315
- return deflate(buf);
8316
- }
8317
-
8318
8409
  // src/image-editor/psd/smart.ts
8319
8410
  var dbl2 = (value) => ({ type: "doub", value });
8320
8411
  var unit2 = (u, value) => ({ type: "UntF", unit: u, value });
@@ -10361,6 +10452,16 @@ function psdToLayers(file, options = {}) {
10361
10452
  const bg = mergedLayer(ctx);
10362
10453
  if (bg) layers = [bg];
10363
10454
  }
10455
+ let alphaChannels = [];
10456
+ const hasTransparency = header.channels > ctx.colorCount && (file.layers.length === 0 || file.mergedAlpha);
10457
+ const firstAlpha = ctx.colorCount + (hasTransparency ? 1 : 0);
10458
+ if (!ctx.skipPixels && header.channels > firstAlpha) {
10459
+ try {
10460
+ alphaChannels = readAlphaChannels(decodeMergedImage(file), header, firstAlpha, (id) => resource(file, id), (m) => warn.extra.push(m));
10461
+ } catch (e) {
10462
+ warn.extra.push(`The alpha channels could not be read (${e instanceof Error ? e.message : String(e)}).`);
10463
+ }
10464
+ }
10364
10465
  const i32 = (b) => b && b.length >= 4 ? new DataView(b.buffer, b.byteOffset, 4).getInt32(0) : void 0;
10365
10466
  const angle = i32(resource(file, 1037));
10366
10467
  const altitude = i32(resource(file, 1049));
@@ -10374,6 +10475,7 @@ function psdToLayers(file, options = {}) {
10374
10475
  patterns: [...ctx.patterns.values()],
10375
10476
  ...angle !== void 0 || altitude !== void 0 ? { globalLight: { angle: Math.max(-360, Math.min(360, angle ?? 120)), altitude: Math.max(0, Math.min(90, altitude ?? 30)) } } : {},
10376
10477
  info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels },
10478
+ ...alphaChannels.length ? { alphaChannels } : {},
10377
10479
  ...cmykProfile ? { sourceMode: { mode: "cmyk", profile: cmykProfile } } : header.colorMode === MODE_LAB ? { sourceMode: { mode: "lab" } } : {},
10378
10480
  ...resource(file, 1039) ? { iccProfile: resource(file, 1039).slice() } : {},
10379
10481
  bitDepth: (header.depth === 16 || header.depth === 32) && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP ? header.depth : 8
@@ -11411,6 +11513,10 @@ function exportPsd(input) {
11411
11513
  planes = transparent ? dp : dp.slice(0, 3);
11412
11514
  }
11413
11515
  }
11516
+ for (const ch of input.alphaChannels ?? []) {
11517
+ if (ch.data.length !== n) throw new PsdError(`Alpha channel "${ch.name}" has ${ch.data.length} values, expected ${n}.`);
11518
+ planes.push(planeAtDepth(ch.data, depth));
11519
+ }
11414
11520
  const planeBytes = n * (depth >> 3);
11415
11521
  const merged2 = new Uint8Array(planeBytes * planes.length);
11416
11522
  planes.forEach((p, i) => merged2.set(p, i * planeBytes));
@@ -11432,6 +11538,7 @@ function exportPsd(input) {
11432
11538
  { id: 1057, name: "", data: version.result() }
11433
11539
  ];
11434
11540
  if (input.iccProfile?.length) resources.push({ id: 1039, name: "", data: input.iccProfile });
11541
+ resources.push(...alphaChannelResources(input.alphaChannels ?? []));
11435
11542
  if (input.globalLight) {
11436
11543
  const i32 = (v) => {
11437
11544
  const w = new PsdWriter();
@@ -11820,6 +11927,8 @@ export {
11820
11927
  deserializeLayer,
11821
11928
  deserializeLayers,
11822
11929
  PsdError,
11930
+ decodePlanes,
11931
+ encodeRle,
11823
11932
  parseVersionedDescriptor,
11824
11933
  versionedDescriptorBytes,
11825
11934
  ADJUSTMENT_KEYS,
@@ -11829,8 +11938,6 @@ export {
11829
11938
  parseLfx2,
11830
11939
  writeLfx2,
11831
11940
  parseLrfx,
11832
- decodePlanes,
11833
- encodeRle,
11834
11941
  BROWSER_IMAGE_TYPES,
11835
11942
  readPsd,
11836
11943
  layerName,