@pixerate/editor 0.113.0 → 0.115.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 (125) hide show
  1. package/THIRD_PARTY_NOTICES.md +8 -0
  2. package/dist/animation-editor/index.cjs +60 -54
  3. package/dist/animation-editor/index.cjs.map +1 -1
  4. package/dist/animation-editor/index.d.cts +3 -3
  5. package/dist/animation-editor/index.d.ts +3 -3
  6. package/dist/animation-editor/index.js +14 -8
  7. package/dist/animation-editor/index.js.map +1 -1
  8. package/dist/builtin-CY97ppKM.d.cts +354 -0
  9. package/dist/builtin-CY97ppKM.d.ts +354 -0
  10. package/dist/canvas/index.cjs +3 -3
  11. package/dist/canvas/index.cjs.map +1 -1
  12. package/dist/canvas/index.js +9 -9
  13. package/dist/chunk-26PGXHY7.cjs +753 -0
  14. package/dist/chunk-26PGXHY7.cjs.map +1 -0
  15. package/dist/chunk-2OJACTPR.cjs +929 -0
  16. package/dist/chunk-2OJACTPR.cjs.map +1 -0
  17. package/dist/chunk-3UFGNHSP.js +929 -0
  18. package/dist/chunk-3UFGNHSP.js.map +1 -0
  19. package/dist/chunk-643B2HKC.cjs +534 -0
  20. package/dist/chunk-643B2HKC.cjs.map +1 -0
  21. package/dist/chunk-6FCKOS2B.js +534 -0
  22. package/dist/chunk-6FCKOS2B.js.map +1 -0
  23. package/dist/chunk-BRLYOPLT.js +2574 -0
  24. package/dist/chunk-BRLYOPLT.js.map +1 -0
  25. package/dist/{chunk-LQEEDHOP.js → chunk-C6C5PDKU.js} +759 -761
  26. package/dist/chunk-C6C5PDKU.js.map +1 -0
  27. package/dist/{chunk-4KLT7ZYS.cjs → chunk-DFQEX3AM.cjs} +29 -29
  28. package/dist/{chunk-4KLT7ZYS.cjs.map → chunk-DFQEX3AM.cjs.map} +1 -1
  29. package/dist/chunk-G5NMLUVF.cjs +2574 -0
  30. package/dist/chunk-G5NMLUVF.cjs.map +1 -0
  31. package/dist/{chunk-YGIMK4NX.cjs → chunk-I7FQBWMQ.cjs} +813 -842
  32. package/dist/chunk-I7FQBWMQ.cjs.map +1 -0
  33. package/dist/{chunk-LPYOIVLA.js → chunk-LKCYANMW.js} +3 -3
  34. package/dist/{chunk-W3GXSUSQ.cjs → chunk-LPLCWZTM.cjs} +5087 -1283
  35. package/dist/chunk-LPLCWZTM.cjs.map +1 -0
  36. package/dist/chunk-MMVHBKMM.js +753 -0
  37. package/dist/chunk-MMVHBKMM.js.map +1 -0
  38. package/dist/{chunk-POGBUYWE.cjs → chunk-ST7E3NEE.cjs} +857 -859
  39. package/dist/chunk-ST7E3NEE.cjs.map +1 -0
  40. package/dist/{chunk-7VOHOPLW.cjs → chunk-TCKIXI46.cjs} +59 -59
  41. package/dist/{chunk-7VOHOPLW.cjs.map → chunk-TCKIXI46.cjs.map} +1 -1
  42. package/dist/{chunk-XIOMMGPD.cjs → chunk-TFOPHZ3U.cjs} +1 -1
  43. package/dist/chunk-TFOPHZ3U.cjs.map +1 -0
  44. package/dist/{chunk-Z4BC6M74.js → chunk-UBIXVXPR.js} +2 -2
  45. package/dist/{chunk-BLWCAQCW.js → chunk-VXR7XWMF.js} +4574 -770
  46. package/dist/chunk-VXR7XWMF.js.map +1 -0
  47. package/dist/{chunk-CZOXTEMN.js → chunk-XICA4PVO.js} +392 -421
  48. package/dist/chunk-XICA4PVO.js.map +1 -0
  49. package/dist/{chunk-HNS7UHCM.js → chunk-XK5LZKBD.js} +1 -1
  50. package/dist/chunk-XK5LZKBD.js.map +1 -0
  51. package/dist/cms/index.cjs +146 -0
  52. package/dist/cms/index.cjs.map +1 -0
  53. package/dist/cms/index.d.cts +51 -0
  54. package/dist/cms/index.d.ts +51 -0
  55. package/dist/cms/index.js +146 -0
  56. package/dist/cms/index.js.map +1 -0
  57. package/dist/{export-CEXEzqBf.d.cts → export-BJE8T0YA.d.cts} +279 -191
  58. package/dist/{export-DIkoK8-r.d.ts → export-Con3UKkm.d.ts} +279 -191
  59. package/dist/image-editor/index.cjs +1848 -1218
  60. package/dist/image-editor/index.cjs.map +1 -1
  61. package/dist/image-editor/index.d.cts +85 -93
  62. package/dist/image-editor/index.d.ts +85 -93
  63. package/dist/image-editor/index.js +871 -241
  64. package/dist/image-editor/index.js.map +1 -1
  65. package/dist/opentype-BZEOSOX3.d.ts +188 -0
  66. package/dist/opentype-Dpe75vL5.d.cts +188 -0
  67. package/dist/paint/index.cjs +4 -4
  68. package/dist/paint/index.d.cts +2 -2
  69. package/dist/paint/index.d.ts +2 -2
  70. package/dist/paint/index.js +3 -3
  71. package/dist/paint-editor/index.cjs +147 -145
  72. package/dist/paint-editor/index.cjs.map +1 -1
  73. package/dist/paint-editor/index.d.cts +9 -8
  74. package/dist/paint-editor/index.d.ts +9 -8
  75. package/dist/paint-editor/index.js +7 -5
  76. package/dist/paint-editor/index.js.map +1 -1
  77. package/dist/raster/index.cjs +53 -3
  78. package/dist/raster/index.cjs.map +1 -1
  79. package/dist/raster/index.d.cts +62 -91
  80. package/dist/raster/index.d.ts +62 -91
  81. package/dist/raster/index.js +59 -9
  82. package/dist/{render-BEriFuqK.d.cts → render-B1K_OoLy.d.cts} +87 -2
  83. package/dist/{render-tjzKaik-.d.ts → render-CrmHOgpo.d.ts} +87 -2
  84. package/dist/{retouch-CEIKR22W.d.cts → retouch-Bxkuc0KH.d.cts} +1 -1
  85. package/dist/{retouch-BXmeSCaB.d.ts → retouch-Do6tBs2H.d.ts} +1 -1
  86. package/dist/{surface-C8RRg_Bh.d.cts → surface-Cn30xIV6.d.cts} +6 -1
  87. package/dist/{surface-C8RRg_Bh.d.ts → surface-Cn30xIV6.d.ts} +6 -1
  88. package/dist/{svg-D_cfkhlB.d.cts → svg-BnRj0q8i.d.cts} +16 -4
  89. package/dist/{svg-wIaKLrU0.d.ts → svg-CmmBFfGT.d.ts} +16 -4
  90. package/dist/{types-DtL_qLFz.d.ts → types-1SUQKDAw.d.ts} +273 -4
  91. package/dist/{types-DyQq-WPY.d.cts → types-yINF17Ta.d.cts} +273 -4
  92. package/dist/vector/index.cjs +12170 -7343
  93. package/dist/vector/index.cjs.map +1 -1
  94. package/dist/vector/index.d.cts +1579 -16
  95. package/dist/vector/index.d.ts +1579 -16
  96. package/dist/vector/index.js +6303 -1476
  97. package/dist/vector/index.js.map +1 -1
  98. package/dist/warp-B39VsOtd.d.cts +348 -0
  99. package/dist/warp-DMN30aY6.d.ts +348 -0
  100. package/dist/zlib-dxQdgHyN.d.cts +95 -0
  101. package/dist/zlib-dxQdgHyN.d.ts +95 -0
  102. package/package.json +9 -2
  103. package/skills/pixerate-image-editor/SKILL.md +13 -36
  104. package/skills/pixerate-image-editor/references/color-management.md +42 -0
  105. package/skills/pixerate-image-editor/references/photoshop-files.md +41 -0
  106. package/skills/pixerate-paint-editor/SKILL.md +136 -4
  107. package/skills/pixerate-vector/SKILL.md +72 -2
  108. package/dist/chunk-BLWCAQCW.js.map +0 -1
  109. package/dist/chunk-CZOXTEMN.js.map +0 -1
  110. package/dist/chunk-HNS7UHCM.js.map +0 -1
  111. package/dist/chunk-JLYX4V57.cjs +0 -2001
  112. package/dist/chunk-JLYX4V57.cjs.map +0 -1
  113. package/dist/chunk-KB2YBCVS.js +0 -2001
  114. package/dist/chunk-KB2YBCVS.js.map +0 -1
  115. package/dist/chunk-LQEEDHOP.js.map +0 -1
  116. package/dist/chunk-POGBUYWE.cjs.map +0 -1
  117. package/dist/chunk-W3GXSUSQ.cjs.map +0 -1
  118. package/dist/chunk-XIOMMGPD.cjs.map +0 -1
  119. package/dist/chunk-YGIMK4NX.cjs.map +0 -1
  120. package/dist/homography-CZ-tFjay.d.cts +0 -50
  121. package/dist/homography-Ctfjoc1b.d.ts +0 -50
  122. package/dist/warp-CWHZzE3x.d.ts +0 -118
  123. package/dist/warp-D5jz_tN7.d.cts +0 -118
  124. /package/dist/{chunk-LPYOIVLA.js.map → chunk-LKCYANMW.js.map} +0 -0
  125. /package/dist/{chunk-Z4BC6M74.js.map → chunk-UBIXVXPR.js.map} +0 -0
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  DEFAULT_GLOBAL_LIGHT,
3
+ DeepCompositor,
3
4
  LAYER_EFFECT_KINDS,
4
5
  LayerEffectError,
5
6
  MAX_EFFECT_REACH,
6
7
  PatternTile,
7
8
  RasterCompositor,
8
9
  TransformTooLargeError,
9
- ZlibError,
10
10
  base64ToBytes,
11
11
  blendTile,
12
12
  builtinPattern,
@@ -23,7 +23,6 @@ import {
23
23
  findLayer,
24
24
  flattenLayers,
25
25
  gaussianBlur,
26
- inflate,
27
26
  insertLayer,
28
27
  isInterpolation,
29
28
  isLayerEffectKind,
@@ -35,13 +34,17 @@ import {
35
34
  parseDataUrl,
36
35
  parseEffectColor,
37
36
  pngDataUrl,
37
+ readDeepRegion,
38
38
  reduceSurface,
39
39
  scaleLayerEffect,
40
+ surfaceDepth,
41
+ surfaceFromDeepPixels,
40
42
  transformSurface,
41
43
  validateEffectGradient,
42
44
  validateLayerEffects,
43
- warpSurface
44
- } from "./chunk-LQEEDHOP.js";
45
+ warpSurface,
46
+ writeDeepRegion
47
+ } from "./chunk-C6C5PDKU.js";
45
48
  import {
46
49
  affineFromHomography,
47
50
  applyHomography,
@@ -68,8 +71,21 @@ import {
68
71
  tileKey,
69
72
  tilesInRect,
70
73
  translateSurface
71
- } from "./chunk-HNS7UHCM.js";
74
+ } from "./chunk-XK5LZKBD.js";
75
+ import {
76
+ Transform,
77
+ builtinProfile,
78
+ parseProfile,
79
+ srgbProfile
80
+ } from "./chunk-BRLYOPLT.js";
81
+ import {
82
+ ZlibError,
83
+ deflate,
84
+ inflate
85
+ } from "./chunk-6FCKOS2B.js";
72
86
  import {
87
+ DEFAULT_AUTO_LEADING,
88
+ DEFAULT_TEXT_STYLE,
73
89
  IDENTITY_MATRIX,
74
90
  WARP_STYLES,
75
91
  applyMatrix,
@@ -77,11 +93,15 @@ import {
77
93
  ellipseSubpath,
78
94
  evalWarpMesh,
79
95
  expandVectorCorners,
96
+ fitParagraphRuns,
97
+ fitRuns,
80
98
  fitWarpMesh,
81
99
  identityWarpMesh,
82
100
  invertMatrix,
83
101
  isIdentityMatrix,
102
+ isTextSpace,
84
103
  isValidWarpMesh,
104
+ layoutText,
85
105
  mapWarpMeshPoints,
86
106
  matrixAbout,
87
107
  multiplyMatrices,
@@ -89,11 +109,16 @@ import {
89
109
  rectSubpath,
90
110
  rotateMatrix,
91
111
  setAnchorCorner,
112
+ spliceRuns,
92
113
  starSubpath,
114
+ styleAt,
93
115
  subpathsToBezier,
116
+ textDecorations,
117
+ textFragmentOutline,
118
+ textRectPath,
94
119
  translateMatrix,
95
120
  warpPresetMesh
96
- } from "./chunk-BLWCAQCW.js";
121
+ } from "./chunk-VXR7XWMF.js";
97
122
  import {
98
123
  bezierPathBounds,
99
124
  outlineStroke,
@@ -1742,7 +1767,7 @@ function lutOp(luts) {
1742
1767
  var isIdentityCurve = (pts) => pts.length === 2 && pts[0].input === 0 && pts[0].output === 0 && pts[1].input === 255 && pts[1].output === 255;
1743
1768
  var isIdentityLevels = (c) => c.inBlack === 0 && c.inWhite === 255 && c.gamma === 1 && c.outBlack === 0 && c.outWhite === 255;
1744
1769
  var LEVELS_QUANTUM = 255;
1745
- function toneLuts(layer) {
1770
+ function toneLuts(layer, quantum = LEVELS_QUANTUM) {
1746
1771
  const n = ADJUSTMENT_LUT_SIZE;
1747
1772
  if (layer.kind === "curves") {
1748
1773
  const m = curveLutFromLevels(layer.params.master);
@@ -1757,13 +1782,14 @@ function toneLuts(layer) {
1757
1782
  return [layer.params.red, layer.params.green, layer.params.blue].map((rec) => {
1758
1783
  const c = toUnitLevels(rec);
1759
1784
  const out = new Float32Array(n);
1760
- for (let k = 0; k < n; k++) out[k] = levelsValue(m, levelsValue(c, k / (n - 1), LEVELS_QUANTUM), LEVELS_QUANTUM);
1785
+ const q2 = quantum ?? void 0;
1786
+ for (let k = 0; k < n; k++) out[k] = levelsValue(m, levelsValue(c, k / (n - 1), q2), q2);
1761
1787
  return out;
1762
1788
  });
1763
1789
  }
1764
1790
  return null;
1765
1791
  }
1766
- function compileAdjustmentLayer(layer) {
1792
+ function compileAdjustmentLayer(layer, options = {}) {
1767
1793
  switch (layer.kind) {
1768
1794
  case "curves": {
1769
1795
  const p = layer.params;
@@ -1773,7 +1799,7 @@ function compileAdjustmentLayer(layer) {
1773
1799
  case "levels": {
1774
1800
  const p = layer.params;
1775
1801
  if ([p.master, p.red, p.green, p.blue].every(isIdentityLevels)) return null;
1776
- return lutOp(toneLuts(layer));
1802
+ return lutOp(toneLuts(layer, options.deep ? null : LEVELS_QUANTUM));
1777
1803
  }
1778
1804
  case "hueSaturation": {
1779
1805
  const p = layer.params;
@@ -1878,15 +1904,15 @@ function compileAdjustmentLayer(layer) {
1878
1904
  }
1879
1905
  var COMPILE_CACHE_LIMIT = 64;
1880
1906
  var compileCache = /* @__PURE__ */ new Map();
1881
- function compiledFor(layer) {
1882
- const key = `${layer.kind}:${JSON.stringify(layer.params)}`;
1907
+ function compiledFor(layer, deep = false) {
1908
+ const key = `${deep ? "deep:" : ""}${layer.kind}:${JSON.stringify(layer.params)}`;
1883
1909
  if (compileCache.has(key)) {
1884
1910
  const op2 = compileCache.get(key);
1885
1911
  compileCache.delete(key);
1886
1912
  compileCache.set(key, op2);
1887
1913
  return op2;
1888
1914
  }
1889
- const op = compileAdjustmentLayer(layer);
1915
+ const op = compileAdjustmentLayer(layer, { deep });
1890
1916
  compileCache.set(key, op);
1891
1917
  if (compileCache.size > COMPILE_CACHE_LIMIT) compileCache.delete(compileCache.keys().next().value);
1892
1918
  return op;
@@ -1947,6 +1973,29 @@ function applyAdjustmentLayers(imageData, layers, masks) {
1947
1973
  data[i + 2] = Math.round(clamp01(c[2]) * 255);
1948
1974
  }
1949
1975
  }
1976
+ function applyAdjustmentLayersFloat(data, layers, masks) {
1977
+ const active = activeAdjustmentLayers(layers);
1978
+ if (!active.length) return;
1979
+ const ops = active.map((l) => compiledFor(l, true));
1980
+ const planes = active.map((l) => masks?.get(l.id));
1981
+ const c = [0, 0, 0];
1982
+ for (let i = 0; i < data.length; i += 4) {
1983
+ if (!(data[i + 3] > 0)) continue;
1984
+ c[0] = data[i];
1985
+ c[1] = data[i + 1];
1986
+ c[2] = data[i + 2];
1987
+ for (let k = 0; k < active.length; k++) {
1988
+ const plane = planes[k];
1989
+ if (plane) {
1990
+ const cov = plane[i >> 2];
1991
+ if (cov > 0) applyLayer(c, active[k], ops[k], cov >= 1 ? 1 : cov);
1992
+ } else applyLayer(c, active[k], ops[k]);
1993
+ }
1994
+ data[i] = c[0];
1995
+ data[i + 1] = c[1];
1996
+ data[i + 2] = c[2];
1997
+ }
1998
+ }
1950
1999
  function adjustmentLayersKey(layers) {
1951
2000
  if (!layers?.length) return "";
1952
2001
  return JSON.stringify(
@@ -2222,10 +2271,12 @@ function removeAlpha(imageData) {
2222
2271
  }
2223
2272
  }
2224
2273
 
2274
+ // src/text/types.ts
2275
+ var TEXT_ALIGNS = ["left", "center", "right", "justify"];
2276
+
2225
2277
  // src/image-editor/layers/model.ts
2226
2278
  var SHAPE_OPERATIONS = ["combine", "subtract", "intersect", "exclude"];
2227
2279
  var LIVE_SHAPE_KINDS = ["rect", "ellipse", "polygon", "star", "line"];
2228
- var TEXT_ALIGNS = ["left", "center", "right", "justify"];
2229
2280
  var idCounter = 0;
2230
2281
  function newLayerId(prefix = "layer") {
2231
2282
  return `${prefix}_${Date.now().toString(36)}_${(++idCounter).toString(36)}`;
@@ -2376,6 +2427,12 @@ var LayerCompositor = class extends RasterCompositor {
2376
2427
  super(PHOTO_PROFILE, options);
2377
2428
  }
2378
2429
  };
2430
+ function compositeDeep(layers, rect, sources, depth) {
2431
+ const deep = new DeepCompositor(new LayerCompositor(), PHOTO_PROFILE, {
2432
+ applyFilterRunDeep: (run, acc, _r, masks) => applyAdjustmentLayersFloat(acc, run.map(adjustmentNodeAsLayer), masks)
2433
+ }, depth);
2434
+ return deep.composite(layers, rect, sources);
2435
+ }
2379
2436
 
2380
2437
  // src/image-editor/layers/vector-raster.ts
2381
2438
  var FLATNESS = 0.01;
@@ -3901,300 +3958,6 @@ function annotationOfShape(layer) {
3901
3958
  var fail3 = (message) => {
3902
3959
  throw new LayerOperationError(message);
3903
3960
  };
3904
- var DEFAULT_TEXT_STYLE = { fontFamily: "sans-serif", fontWeight: 400, fontSize: 24, color: "#000000" };
3905
- var DEFAULT_AUTO_LEADING = 1.2;
3906
- var sameStyle = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3907
- function compact(runs) {
3908
- const out = [];
3909
- for (const r of runs) {
3910
- if (r.length <= 0) continue;
3911
- const last = out[out.length - 1];
3912
- if (last && sameStyle(last.style, r.style)) out[out.length - 1] = { ...last, length: last.length + r.length };
3913
- else out.push({ ...r });
3914
- }
3915
- return out;
3916
- }
3917
- function fitRuns(runs, length, fallback) {
3918
- const out = [];
3919
- let left = length;
3920
- for (const r of runs) {
3921
- if (left <= 0) break;
3922
- const n = Math.min(Math.max(0, Math.floor(r.length)), left);
3923
- if (n > 0) out.push({ ...r, length: n });
3924
- left -= n;
3925
- }
3926
- if (left > 0) {
3927
- if (out.length) out[out.length - 1] = { ...out[out.length - 1], length: out[out.length - 1].length + left };
3928
- else out.push({ length: left, style: runs[runs.length - 1]?.style ?? fallback });
3929
- }
3930
- return compact(out);
3931
- }
3932
- function styleAt(runs, index, fallback) {
3933
- let at = 0;
3934
- for (const r of runs) {
3935
- if (index < at + r.length) return r.style;
3936
- at += r.length;
3937
- }
3938
- return runs[runs.length - 1]?.style ?? fallback;
3939
- }
3940
- function restyleRange(runs, start, end, patch) {
3941
- const out = [];
3942
- let at = 0;
3943
- for (const r of runs) {
3944
- const a = at;
3945
- const b = at + r.length;
3946
- at = b;
3947
- const lo = Math.max(a, start);
3948
- const hi = Math.min(b, end);
3949
- if (hi <= lo) {
3950
- out.push({ ...r });
3951
- continue;
3952
- }
3953
- if (lo > a) out.push({ length: lo - a, style: r.style });
3954
- out.push({ length: hi - lo, style: patch(r.style) });
3955
- if (b > hi) out.push({ length: b - hi, style: r.style });
3956
- }
3957
- return compact(out);
3958
- }
3959
- function spliceRuns(runs, start, end, inserted, style) {
3960
- const out = [];
3961
- let at = 0;
3962
- let placed = false;
3963
- for (const r of runs) {
3964
- const a = at;
3965
- const b = at + r.length;
3966
- at = b;
3967
- if (b <= start) {
3968
- out.push({ ...r });
3969
- continue;
3970
- }
3971
- if (a < start) out.push({ length: start - a, style: r.style });
3972
- if (!placed) {
3973
- out.push({ length: inserted, style });
3974
- placed = true;
3975
- }
3976
- if (b > end) out.push({ length: b - Math.max(end, a), style: r.style });
3977
- }
3978
- if (!placed) out.push({ length: inserted, style });
3979
- return compact(out);
3980
- }
3981
- function paragraphRanges(text3) {
3982
- const out = [];
3983
- let start = 0;
3984
- for (let i = 0; i < text3.length; i++) {
3985
- if (text3[i] === "\n") {
3986
- out.push({ start, end: i + 1, content: i });
3987
- start = i + 1;
3988
- }
3989
- }
3990
- out.push({ start, end: text3.length, content: text3.length });
3991
- return out;
3992
- }
3993
- function fitParagraphRuns(runs, text3) {
3994
- const fallback = runs[0]?.style ?? {};
3995
- const out = compact(paragraphRanges(text3).map((p) => ({ length: p.end - p.start, style: styleAt(runs, p.start, fallback) })));
3996
- return out.length ? out : [{ length: 0, style: fallback }];
3997
- }
3998
- function fontOf(style) {
3999
- const f = { family: style.fontFamily, weight: style.fontWeight, italic: Boolean(style.italic), size: style.fontSize };
4000
- if (style.postScriptName) f.postScriptName = style.postScriptName;
4001
- return f;
4002
- }
4003
- var isBreakAfter = (c) => c === " " || c === " " || c === "-" || c === "\u2010" || c === "\u200B";
4004
- var isSpace = (c) => c === " " || c === " ";
4005
- var isWide = (code) => code >= 11904 && code <= 40959 || code >= 44032 && code <= 55215 || code >= 63744 && code <= 64255 || code >= 65280 && code <= 65519;
4006
- var layoutCache = /* @__PURE__ */ new WeakMap();
4007
- function layoutText(layer, shaper) {
4008
- let byShaper = layoutCache.get(layer);
4009
- const hit = byShaper?.get(shaper.id);
4010
- if (hit) return hit;
4011
- const out = computeLayout(layer, shaper);
4012
- if (!byShaper) {
4013
- byShaper = /* @__PURE__ */ new Map();
4014
- layoutCache.set(layer, byShaper);
4015
- }
4016
- byShaper.set(shaper.id, out);
4017
- return out;
4018
- }
4019
- function computeLayout(layer, shaper) {
4020
- const { text: text3, frame } = layer;
4021
- const runs = fitRuns(layer.runs, text3.length, DEFAULT_TEXT_STYLE);
4022
- const missing = /* @__PURE__ */ new Set();
4023
- const resolved = /* @__PURE__ */ new Map();
4024
- const familyOf = (font) => {
4025
- const key = `${font.family}|${font.weight}|${font.italic}|${font.postScriptName ?? ""}`;
4026
- let fam = resolved.get(key);
4027
- if (fam === void 0) {
4028
- const r = shaper.resolve(font);
4029
- fam = r.family;
4030
- if (!r.available) missing.add(font.family);
4031
- resolved.set(key, fam);
4032
- }
4033
- return fam;
4034
- };
4035
- const resolvedFont = (style) => ({ ...fontOf(style), family: familyOf(fontOf(style)) });
4036
- const box2 = frame.kind === "box" ? frame : null;
4037
- const lines = [];
4038
- let y = 0;
4039
- let first = true;
4040
- const paragraphs = paragraphRanges(text3);
4041
- paragraphs.forEach((para, pi) => {
4042
- const pstyle = styleAt(layer.paragraphs, para.start, {});
4043
- const autoLeading = pstyle.autoLeading ?? DEFAULT_AUTO_LEADING;
4044
- if (pi > 0) y += pstyle.spaceBefore ?? 0;
4045
- const chars = [];
4046
- let i = para.start;
4047
- while (i < para.content) {
4048
- const style = styleAt(runs, i, DEFAULT_TEXT_STYLE);
4049
- let j = i + 1;
4050
- while (j < para.content && styleAt(runs, j, DEFAULT_TEXT_STYLE) === style) j++;
4051
- const seg = text3.slice(i, j);
4052
- const carets = shaper.measure(seg, resolvedFont(style));
4053
- const track = (style.tracking ?? 0) / 1e3 * style.fontSize;
4054
- for (let k = 0; k < seg.length; k++) chars.push({ index: i + k, ch: seg[k], advance: (carets[k + 1] ?? 0) - (carets[k] ?? 0) + track, style });
4055
- i = j;
4056
- }
4057
- const startIndent = pstyle.startIndent ?? 0;
4058
- const endIndent = pstyle.endIndent ?? 0;
4059
- const firstIndent = pstyle.firstLineIndent ?? 0;
4060
- const breaks = [];
4061
- if (!box2 || !chars.length) breaks.push([0, chars.length]);
4062
- else {
4063
- let s = 0;
4064
- while (s < chars.length) {
4065
- const avail = box2.width - startIndent - endIndent - (breaks.length === 0 ? firstIndent : 0);
4066
- let w = 0;
4067
- let e = s;
4068
- let lastBreak = -1;
4069
- while (e < chars.length) {
4070
- const c = chars[e];
4071
- if (!isSpace(c.ch) && w + c.advance > avail && e > s) break;
4072
- w += c.advance;
4073
- if (isBreakAfter(c.ch) || isWide(c.ch.charCodeAt(0)) || e + 1 < chars.length && isWide(chars[e + 1].ch.charCodeAt(0))) lastBreak = e + 1;
4074
- e++;
4075
- }
4076
- if (e < chars.length && lastBreak > s) e = lastBreak;
4077
- while (e < chars.length && isSpace(chars[e].ch)) e++;
4078
- breaks.push([s, e]);
4079
- s = e;
4080
- }
4081
- }
4082
- const align = pstyle.align ?? "left";
4083
- breaks.forEach(([s, e], li) => {
4084
- const lineChars = chars.slice(s, e);
4085
- let visibleEnd = lineChars.length;
4086
- while (visibleEnd > 0 && isSpace(lineChars[visibleEnd - 1].ch)) visibleEnd--;
4087
- const styles = lineChars.length ? [...new Set(lineChars.map((c) => c.style))] : [styleAt(runs, Math.min(para.start, Math.max(0, text3.length - 1)), DEFAULT_TEXT_STYLE)];
4088
- let ascent = 0;
4089
- let descent = 0;
4090
- let leading = 0;
4091
- for (const st of styles) {
4092
- const m = shaper.metrics(resolvedFont(st));
4093
- ascent = Math.max(ascent, m.ascent);
4094
- descent = Math.max(descent, m.descent);
4095
- leading = Math.max(leading, st.leading ?? autoLeading * st.fontSize);
4096
- }
4097
- if (first) {
4098
- y = frame.kind === "box" || frame.kind === "point" && frame.origin === "top" ? ascent : 0;
4099
- first = false;
4100
- } else y += leading;
4101
- const indent = startIndent + (li === 0 ? firstIndent : 0);
4102
- let width = 0;
4103
- for (let k2 = 0; k2 < visibleEnd; k2++) width += lineChars[k2].advance;
4104
- const lastLine = li === breaks.length - 1;
4105
- let extraPerSpace = 0;
4106
- if (box2 && align === "justify" && !lastLine) {
4107
- const spaces = lineChars.slice(0, visibleEnd).filter((c) => isSpace(c.ch)).length;
4108
- const avail = box2.width - startIndent - endIndent - (li === 0 ? firstIndent : 0);
4109
- if (spaces > 0 && avail > width) extraPerSpace = (avail - width) / spaces;
4110
- }
4111
- let x0;
4112
- const fullWidth = width + extraPerSpace * lineChars.slice(0, visibleEnd).filter((c) => isSpace(c.ch)).length;
4113
- if (box2) {
4114
- const avail = box2.width - startIndent - endIndent - (li === 0 ? firstIndent : 0);
4115
- x0 = indent + (align === "center" ? (avail - fullWidth) / 2 : align === "right" ? avail - fullWidth : 0);
4116
- } else x0 = indent + (align === "center" ? -fullWidth / 2 : align === "right" ? -fullWidth : 0);
4117
- const laid = [];
4118
- let x = x0;
4119
- for (const c of lineChars) {
4120
- const adv = c.advance + (isSpace(c.ch) ? extraPerSpace : 0);
4121
- laid.push({ index: c.index, x, advance: adv });
4122
- x += adv;
4123
- }
4124
- const fragments = [];
4125
- let k = 0;
4126
- while (k < lineChars.length) {
4127
- const st = lineChars[k].style;
4128
- let m = k + 1;
4129
- while (m < lineChars.length && lineChars[m].style === st) m++;
4130
- const font = resolvedFont(st);
4131
- const fx = laid[k].x;
4132
- const carets = [0];
4133
- for (let q2 = k; q2 < m; q2++) carets.push(laid[q2].x + laid[q2].advance - fx);
4134
- fragments.push({
4135
- start: lineChars[k].index,
4136
- end: lineChars[m - 1].index + 1,
4137
- style: st,
4138
- font,
4139
- family: font.family,
4140
- x: fx,
4141
- y: y - (st.baselineShift ?? 0),
4142
- carets,
4143
- spaced: Boolean(st.tracking) || extraPerSpace > 0
4144
- });
4145
- k = m;
4146
- }
4147
- const lineStart = lineChars.length ? lineChars[0].index : para.start;
4148
- lines.push({ start: lineStart, end: lineChars.length ? lineChars[lineChars.length - 1].index + 1 : para.start, baseline: y, ascent, descent, x: x0, width, chars: laid, fragments });
4149
- });
4150
- y += pstyle.spaceAfter ?? 0;
4151
- });
4152
- let bounds;
4153
- if (box2) bounds = { x: 0, y: 0, width: box2.width, height: box2.height };
4154
- else {
4155
- let x0 = Infinity;
4156
- let x1 = -Infinity;
4157
- for (const l of lines) {
4158
- x0 = Math.min(x0, l.x);
4159
- x1 = Math.max(x1, l.x + l.width);
4160
- }
4161
- if (!Number.isFinite(x0)) x0 = x1 = 0;
4162
- const top = lines.length ? lines[0].baseline - lines[0].ascent : 0;
4163
- const last = lines[lines.length - 1];
4164
- const bottom = last ? last.baseline + last.descent : 0;
4165
- bounds = { x: x0, y: top, width: Math.max(0, x1 - x0), height: Math.max(0, bottom - top) };
4166
- }
4167
- return { lines, bounds, missingFonts: [...missing] };
4168
- }
4169
- function textIndexAt(layout, p) {
4170
- if (!layout.lines.length) return 0;
4171
- let line = layout.lines[layout.lines.length - 1];
4172
- for (const l of layout.lines) {
4173
- if (p.y <= l.baseline + l.descent) {
4174
- line = l;
4175
- break;
4176
- }
4177
- }
4178
- if (!line.chars.length) return line.start;
4179
- for (const c of line.chars) if (p.x < c.x + c.advance / 2) return c.index;
4180
- const lastChar = line.chars[line.chars.length - 1];
4181
- return lastChar.index + 1;
4182
- }
4183
- function caretAt(layout, index) {
4184
- const lines = layout.lines;
4185
- if (!lines.length) return { x: 0, top: 0, bottom: 0, line: 0 };
4186
- for (let li = 0; li < lines.length; li++) {
4187
- const l2 = lines[li];
4188
- const next = lines[li + 1];
4189
- if (next && index >= next.start && (next.chars.length || index > l2.end || next.start > l2.end)) continue;
4190
- const c = l2.chars.find((ch) => ch.index === index);
4191
- const prev = l2.chars.find((ch) => ch.index === index - 1);
4192
- const x = c ? c.x : prev ? prev.x + prev.advance : l2.x;
4193
- return { x, top: l2.baseline - l2.ascent, bottom: l2.baseline + l2.descent, line: li };
4194
- }
4195
- const l = lines[lines.length - 1];
4196
- return { x: l.x + l.width, top: l.baseline - l.ascent, bottom: l.baseline + l.descent, line: lines.length - 1 };
4197
- }
4198
3961
  var TEXT_RENDER_MARGIN = MAX_EFFECT_REACH;
4199
3962
  function textMatrix(layer) {
4200
3963
  return layer.transform ?? IDENTITY_MATRIX;
@@ -4239,31 +4002,6 @@ function inkBounds(layout) {
4239
4002
  }
4240
4003
  return b;
4241
4004
  }
4242
- function decorations(f, l) {
4243
- const out = [];
4244
- const t = Math.max(1, f.style.fontSize / 15);
4245
- const w = f.carets[f.carets.length - 1];
4246
- if (f.style.underline) out.push({ x: f.x, y: f.y + Math.max(t, l.descent * 0.35), width: w, height: t });
4247
- if (f.style.strikethrough) out.push({ x: f.x, y: f.y - l.ascent * 0.3 - t / 2, width: w, height: t });
4248
- return out;
4249
- }
4250
- var rectPath = (r) => [
4251
- { type: "M", x: r.x, y: r.y },
4252
- { type: "L", x: r.x + r.width, y: r.y },
4253
- { type: "L", x: r.x + r.width, y: r.y + r.height },
4254
- { type: "L", x: r.x, y: r.y + r.height },
4255
- { type: "Z" }
4256
- ];
4257
- function fragmentOutline(shaper, text3, f) {
4258
- const s = text3.slice(f.start, f.end);
4259
- if (!f.spaced) return shaper.outline(s, f.font, f.x, f.y);
4260
- const out = [];
4261
- for (let k = 0; k < s.length; k++) {
4262
- if (isSpace(s[k])) continue;
4263
- out.push(...shaper.outline(s[k], f.font, f.x + f.carets[k], f.y));
4264
- }
4265
- return out;
4266
- }
4267
4005
  function textOutlines(layer, shaper) {
4268
4006
  if (!shaper.outline) fail3(`The text shaper "${shaper.id}" cannot give glyph outlines; plug in an outline shaper (createOutlineTextShaper) to convert text to shapes.`);
4269
4007
  const layout = layoutText(layer, shaper);
@@ -4271,8 +4009,8 @@ function textOutlines(layer, shaper) {
4271
4009
  const out = [];
4272
4010
  for (const l of layout.lines) {
4273
4011
  for (const f of l.fragments) {
4274
- let path = fragmentOutline(shaper, layer.text, f);
4275
- for (const r of decorations(f, l)) path = [...path, ...rectPath(r)];
4012
+ let path = textFragmentOutline(shaper, layer.text, f);
4013
+ for (const r of textDecorations(f, l)) path = [...path, ...textRectPath(r)];
4276
4014
  out.push({ fragment: f, path: isIdentityMatrix(m) ? path : transformBezierPath(path, m) });
4277
4015
  }
4278
4016
  }
@@ -4341,8 +4079,8 @@ function renderOnCanvas(layer, shaper, region, env) {
4341
4079
  ctx.globalAlpha = f.style.opacity ?? 1;
4342
4080
  const s = layer.text.slice(f.start, f.end);
4343
4081
  if (!f.spaced) shaper.draw(ctx, s, f.font, f.x, f.y);
4344
- else for (let k = 0; k < s.length; k++) if (!isSpace(s[k])) shaper.draw(ctx, s[k], f.font, f.x + f.carets[k], f.y);
4345
- for (const d of decorations(f, l)) ctx.fillRect(d.x, d.y, d.width, d.height);
4082
+ else for (let k = 0; k < s.length; k++) if (!isTextSpace(s[k])) shaper.draw(ctx, s[k], f.font, f.x + f.carets[k], f.y);
4083
+ for (const d of textDecorations(f, l)) ctx.fillRect(d.x, d.y, d.width, d.height);
4346
4084
  }
4347
4085
  }
4348
4086
  ctx.globalAlpha = 1;
@@ -5679,6 +5417,42 @@ function encodeSurface(surface) {
5679
5417
  encodedCache.set(surface, out);
5680
5418
  return out;
5681
5419
  }
5420
+ var deepCache = /* @__PURE__ */ new WeakMap();
5421
+ function encodeDeepSurface(surface) {
5422
+ if (deepCache.has(surface)) return deepCache.get(surface);
5423
+ let out = null;
5424
+ const depth = surfaceDepth(surface);
5425
+ const b = depth === 8 ? null : contentBounds(surface);
5426
+ if (depth !== 8 && b) {
5427
+ const samples = readDeepRegion(surface, b, depth);
5428
+ const bytes = new Uint8Array(samples.byteLength);
5429
+ const view = new DataView(bytes.buffer);
5430
+ if (samples instanceof Uint16Array) for (let i = 0; i < samples.length; i++) view.setUint16(2 * i, samples[i], true);
5431
+ else for (let i = 0; i < samples.length; i++) view.setFloat32(4 * i, samples[i], true);
5432
+ out = { depth, x: b.x, y: b.y, width: b.width, height: b.height, data: bytesToBase64(deflate(bytes)) };
5433
+ }
5434
+ deepCache.set(surface, out);
5435
+ return out;
5436
+ }
5437
+ function decodeDeepSurface(surface, raw, problems, label) {
5438
+ const d = raw;
5439
+ if (!d || typeof d !== "object") return surface;
5440
+ try {
5441
+ if (d.depth !== 16 && d.depth !== 32 || !(d.width > 0 && d.height > 0) || !Number.isInteger(d.x) || !Number.isInteger(d.y) || typeof d.data !== "string") throw new Error("malformed");
5442
+ const n = d.width * d.height * 4;
5443
+ const size = d.depth === 16 ? 2 : 4;
5444
+ const bytes = inflate(base64ToBytes(d.data), { maxOutput: n * size });
5445
+ if (bytes.length !== n * size) throw new Error("wrong length");
5446
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
5447
+ const samples = d.depth === 16 ? new Uint16Array(n) : new Float32Array(n);
5448
+ if (samples instanceof Uint16Array) for (let i = 0; i < n; i++) samples[i] = view.getUint16(2 * i, true);
5449
+ else for (let i = 0; i < n; i++) samples[i] = view.getFloat32(4 * i, true);
5450
+ return writeDeepRegion(surface, { x: d.x, y: d.y, width: d.width, height: d.height }, samples);
5451
+ } catch {
5452
+ problems.push(`${label}: its ${d.depth}-bit samples could not be read, so it was opened at 8 bits`);
5453
+ return surface;
5454
+ }
5455
+ }
5682
5456
  function baseFields(layer, ctx) {
5683
5457
  const out = {
5684
5458
  id: layer.id,
@@ -5747,6 +5521,10 @@ function serializeLayer(layer, ctx) {
5747
5521
  }
5748
5522
  if (layer.fillOpacity !== void 0 && layer.fillOpacity !== 1) out.fillOpacity = layer.fillOpacity;
5749
5523
  if (layer.filters?.length) out.filters = JSON.parse(JSON.stringify(layer.filters));
5524
+ if (layer.source !== "document") {
5525
+ const deep = encodeDeepSurface(layer.surface);
5526
+ if (deep) out.deep = deep;
5527
+ }
5750
5528
  return out;
5751
5529
  }
5752
5530
  case "adjustment":
@@ -6128,6 +5906,7 @@ function deserializeLayer(raw, ctx) {
6128
5906
  offset: { x: Math.round(num2(r.offset?.x, -1e7, 1e7, 0)), y: Math.round(num2(r.offset?.y, -1e7, 1e7, 0)) }
6129
5907
  };
6130
5908
  if (r.source === "document") layer.source = "document";
5909
+ else if (r.deep) layer.surface = decodeDeepSurface(layer.surface, r.deep, ctx.problems, `Layer "${base.name || id}"`);
6131
5910
  if (typeof r.fillOpacity === "number" && r.fillOpacity !== 1) layer.fillOpacity = num2(r.fillOpacity, 0, 1, 1);
6132
5911
  const filters = readFilters(r.filters);
6133
5912
  if (filters) layer.filters = filters;
@@ -8465,6 +8244,36 @@ function encodeRle(decoded2, l) {
8465
8244
  out.set(packed.subarray(0, at), counts.length);
8466
8245
  return out;
8467
8246
  }
8247
+ function predict(buf, l) {
8248
+ const rb = rowBytes(l.width, l.depth);
8249
+ if (rb === 0) return;
8250
+ const w = l.width;
8251
+ const scratch = l.depth === 32 ? new Uint8Array(rb) : null;
8252
+ for (let o = 0; o + rb <= buf.length; o += rb) {
8253
+ if (l.depth === 1 || l.depth === 8) {
8254
+ for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
8255
+ } else if (l.depth === 16) {
8256
+ for (let i = w - 1; i > 0; i--) {
8257
+ const a = buf[o + 2 * i] << 8 | buf[o + 2 * i + 1];
8258
+ const b = buf[o + 2 * i - 2] << 8 | buf[o + 2 * i - 1];
8259
+ const v = a - b & 65535;
8260
+ buf[o + 2 * i] = v >> 8;
8261
+ buf[o + 2 * i + 1] = v & 255;
8262
+ }
8263
+ } else if (l.depth === 32) {
8264
+ scratch.set(buf.subarray(o, o + rb));
8265
+ for (let i = 0; i < w; i++) for (let k = 0; k < 4; k++) buf[o + k * w + i] = scratch[4 * i + k];
8266
+ for (let i = rb - 1; i > 0; i--) buf[o + i] = buf[o + i] - buf[o + i - 1] & 255;
8267
+ } else {
8268
+ throw new PsdError(`ZIP prediction is not defined for depth ${l.depth}.`);
8269
+ }
8270
+ }
8271
+ }
8272
+ function encodeZipPredicted(decoded2, l) {
8273
+ const buf = decoded2.slice();
8274
+ predict(buf, l);
8275
+ return deflate(buf);
8276
+ }
8468
8277
 
8469
8278
  // src/image-editor/psd/smart.ts
8470
8279
  var dbl2 = (value) => ({ type: "doub", value });
@@ -9405,23 +9214,31 @@ function writePsd(file, encodeName) {
9405
9214
  w.endLen(res);
9406
9215
  const lm = w.beginLen(psb);
9407
9216
  if (file.layers.length || file.globalBlocks.length) {
9408
- const li = w.beginLen(psb);
9409
- if (file.layers.length) {
9410
- const start = w.length;
9411
- w.i16(file.mergedAlpha ? -file.layers.length : file.layers.length);
9412
- for (const rec of file.layers) writeLayerRecord(w, rec, psb, encodeName(rec.legacyName));
9217
+ const writeLayerInfo = (out) => {
9218
+ const start = out.length;
9219
+ out.i16(file.mergedAlpha ? -file.layers.length : file.layers.length);
9220
+ for (const rec of file.layers) writeLayerRecord(out, rec, psb, encodeName(rec.legacyName));
9413
9221
  for (const rec of file.layers) {
9414
9222
  for (const c of rec.channels) {
9415
9223
  if (c.compression === null) continue;
9416
- w.u16(c.compression);
9417
- w.bytes(c.data);
9224
+ out.u16(c.compression);
9225
+ out.bytes(c.data);
9418
9226
  }
9419
9227
  }
9420
- if ((w.length - start) % 2) w.u8(0);
9421
- }
9228
+ if ((out.length - start) % 2) out.u8(0);
9229
+ };
9230
+ const deepKey = header.depth === 16 ? "Lr16" : header.depth === 32 ? "Lr32" : null;
9231
+ let blocks = file.globalBlocks;
9232
+ const li = w.beginLen(psb);
9233
+ if (file.layers.length && !deepKey) writeLayerInfo(w);
9422
9234
  w.endLen(li);
9235
+ if (file.layers.length && deepKey) {
9236
+ const lw = new PsdWriter();
9237
+ writeLayerInfo(lw);
9238
+ blocks = [{ key: deepKey, data: lw.result() }, ...blocks];
9239
+ }
9423
9240
  w.u32(0);
9424
- writeBlocks(w, file.globalBlocks, psb, 4);
9241
+ writeBlocks(w, blocks, psb, 4);
9425
9242
  }
9426
9243
  w.endLen(lm);
9427
9244
  w.u16(file.imageCompression);
@@ -9430,6 +9247,7 @@ function writePsd(file, encodeName) {
9430
9247
  }
9431
9248
 
9432
9249
  // src/image-editor/psd/pixels.ts
9250
+ var MODE_BITMAP = 0;
9433
9251
  var MODE_INDEXED = 2;
9434
9252
  var MODE_RGB = 3;
9435
9253
  var MODE_CMYK = 4;
@@ -9509,6 +9327,15 @@ function toRgba8(set) {
9509
9327
  }
9510
9328
  return out;
9511
9329
  }
9330
+ if (mode === MODE_CMYK && set.cmykToRgb) {
9331
+ const ink = new Uint8Array(n * 4);
9332
+ for (let i = 0, o = 0; i < n; i++, o += 4) {
9333
+ for (let c = 0; c < 4; c++) ink[o + c] = Math.round((1 - (planes[c] ? planes[c](i) : 1)) * 255);
9334
+ out[o + 3] = Math.round(alpha(i) * 255);
9335
+ }
9336
+ set.cmykToRgb(ink, out);
9337
+ return out;
9338
+ }
9512
9339
  const palette = set.palette;
9513
9340
  for (let i = 0, o = 0; i < n; i++, o += 4) {
9514
9341
  let r;
@@ -9553,6 +9380,99 @@ function toRgba8(set) {
9553
9380
  }
9554
9381
  return out;
9555
9382
  }
9383
+ function toRgbaDeep(set) {
9384
+ const { width, height, depth, mode } = set;
9385
+ if (depth !== 16 && depth !== 32 || mode === MODE_INDEXED || mode === MODE_BITMAP) return null;
9386
+ const n = width * height;
9387
+ const isLab = mode === MODE_LAB;
9388
+ const cmyk = mode === MODE_CMYK;
9389
+ const raw = (plane, fill) => {
9390
+ if (!plane) return () => fill;
9391
+ if (depth === 16) return (i) => (plane[2 * i] << 8 | plane[2 * i + 1]) / 65535;
9392
+ const view = new DataView(plane.buffer, plane.byteOffset, plane.byteLength);
9393
+ return (i) => view.getFloat32(4 * i, false) || 0;
9394
+ };
9395
+ const planes = set.color.map((p) => raw(p, cmyk ? 1 : 0));
9396
+ const alpha = raw(set.alpha, 1);
9397
+ if (depth === 16) {
9398
+ const out2 = new Uint16Array(n * 4);
9399
+ const q2 = (v) => Math.round(clamp012(v) * 65535);
9400
+ for (let i = 0, o = 0; i < n; i++, o += 4) {
9401
+ let r;
9402
+ let g;
9403
+ let b;
9404
+ if (mode === MODE_CMYK) {
9405
+ const k = planes[3] ? planes[3](i) : 1;
9406
+ r = planes[0](i) * k;
9407
+ g = planes[1](i) * k;
9408
+ b = planes[2](i) * k;
9409
+ } else if (isLab) {
9410
+ [r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128);
9411
+ } else if (mode === MODE_RGB || mode === MODE_MULTICHANNEL) {
9412
+ r = planes[0](i);
9413
+ g = planes[1] ? planes[1](i) : r;
9414
+ b = planes[2] ? planes[2](i) : r;
9415
+ } else r = g = b = planes[0](i);
9416
+ out2[o] = q2(r);
9417
+ out2[o + 1] = q2(g);
9418
+ out2[o + 2] = q2(b);
9419
+ out2[o + 3] = q2(alpha(i));
9420
+ }
9421
+ return out2;
9422
+ }
9423
+ const out = new Float32Array(n * 4);
9424
+ for (let i = 0, o = 0; i < n; i++, o += 4) {
9425
+ let r;
9426
+ let g;
9427
+ let b;
9428
+ if (isLab) {
9429
+ [r, g, b] = labToSrgb(planes[0](i) * 100, planes[1](i) * 255 - 128, planes[2](i) * 255 - 128).map(srgbToLinear);
9430
+ } else if (cmyk) {
9431
+ const k = planes[3] ? planes[3](i) : 1;
9432
+ r = planes[0](i) * k;
9433
+ g = planes[1](i) * k;
9434
+ b = planes[2](i) * k;
9435
+ } else if (mode === MODE_RGB || mode === MODE_MULTICHANNEL) {
9436
+ r = planes[0](i);
9437
+ g = planes[1] ? planes[1](i) : r;
9438
+ b = planes[2] ? planes[2](i) : r;
9439
+ } else r = g = b = planes[0](i);
9440
+ out[o] = r;
9441
+ out[o + 1] = g;
9442
+ out[o + 2] = b;
9443
+ out[o + 3] = clamp012(alpha(i));
9444
+ }
9445
+ return out;
9446
+ }
9447
+ function deepToPlanes(data, n) {
9448
+ const bytes = data instanceof Uint16Array ? 2 : 4;
9449
+ const planes = [0, 1, 2, 3].map(() => new Uint8Array(n * bytes));
9450
+ if (data instanceof Uint16Array) {
9451
+ for (let i = 0; i < n; i++) {
9452
+ for (let c = 0; c < 4; c++) {
9453
+ const v = data[i * 4 + c];
9454
+ planes[c][2 * i] = v >> 8;
9455
+ planes[c][2 * i + 1] = v & 255;
9456
+ }
9457
+ }
9458
+ } else {
9459
+ const views = planes.map((p) => new DataView(p.buffer));
9460
+ for (let i = 0; i < n; i++) for (let c = 0; c < 4; c++) views[c].setFloat32(4 * i, data[i * 4 + c], false);
9461
+ }
9462
+ return planes;
9463
+ }
9464
+ function planeAtDepth(plane, depth) {
9465
+ if (depth === 8) return plane;
9466
+ if (depth === 16) {
9467
+ const out2 = new Uint8Array(plane.length * 2);
9468
+ for (let i = 0; i < plane.length; i++) out2[2 * i] = out2[2 * i + 1] = plane[i];
9469
+ return out2;
9470
+ }
9471
+ const out = new Uint8Array(plane.length * 4);
9472
+ const view = new DataView(out.buffer);
9473
+ for (let i = 0; i < plane.length; i++) view.setFloat32(4 * i, plane[i] / 255, false);
9474
+ return out;
9475
+ }
9556
9476
  function toMask8(plane, width, height, depth) {
9557
9477
  if (depth === 8) return new Uint8ClampedArray(plane.buffer, plane.byteOffset, width * height);
9558
9478
  const s = sampler(plane, depth, width, false, 0);
@@ -9587,6 +9507,16 @@ function matteWhite(data) {
9587
9507
  }
9588
9508
  return out;
9589
9509
  }
9510
+ function matteWhiteDeep(data) {
9511
+ const out = data.slice();
9512
+ const one = out instanceof Uint16Array ? 65535 : 1;
9513
+ for (let i = 0; i < out.length; i += 4) {
9514
+ const a = Math.min(1, Math.max(0, out[i + 3] / one));
9515
+ if (a >= 1) continue;
9516
+ for (let c = 0; c < 3; c++) out[i + c] = out instanceof Uint16Array ? Math.round(out[i + c] * a + one * (1 - a)) : out[i + c] * a + one * (1 - a);
9517
+ }
9518
+ return out;
9519
+ }
9590
9520
 
9591
9521
  // src/image-editor/psd/patterns.ts
9592
9522
  var MAX_EDGE = 3e4;
@@ -9823,16 +9753,19 @@ function recordPixels(ctx, rec, name) {
9823
9753
  const planes = ids.map((id) => rec.channels.some((c) => c.id === id) ? decodeOr(ctx, rec, id, name) ?? null : void 0);
9824
9754
  if (planes.some((p) => p === null)) return emptySurface(4);
9825
9755
  if (planes.every((p) => p === void 0)) return emptySurface(4);
9826
- const data = toRgba8({
9756
+ const set = {
9827
9757
  width,
9828
9758
  height,
9829
9759
  depth: ctx.file.header.depth,
9830
9760
  mode: ctx.file.header.colorMode,
9831
9761
  color: planes.slice(0, ctx.colorCount),
9832
9762
  alpha: planes[ctx.colorCount],
9833
- palette: ctx.palette
9834
- });
9835
- return surfaceFromPixels({ width, height, data }, 4, rec.rect.left, rec.rect.top);
9763
+ palette: ctx.palette,
9764
+ cmykToRgb: ctx.cmykToRgb
9765
+ };
9766
+ const deep = set.cmykToRgb ? null : toRgbaDeep(set);
9767
+ if (deep) return surfaceFromDeepPixels({ width, height, data: deep }, 4, rec.rect.left, rec.rect.top);
9768
+ return surfaceFromPixels({ width, height, data: toRgba8(set) }, 4, rec.rect.left, rec.rect.top);
9836
9769
  }
9837
9770
  function recordMask(ctx, rec, name) {
9838
9771
  const m = rec.mask;
@@ -10230,16 +10163,24 @@ function mergedLayer(ctx) {
10230
10163
  const plane = (i) => i < header.channels ? planes.subarray(i * size, (i + 1) * size) : void 0;
10231
10164
  const cc = ctx.colorCount;
10232
10165
  const hasAlpha = header.channels > cc && (ctx.file.layers.length === 0 || ctx.file.mergedAlpha);
10233
- const data = toRgba8({
10166
+ const set = {
10234
10167
  width,
10235
10168
  height,
10236
10169
  depth: header.depth,
10237
10170
  mode: header.colorMode,
10238
10171
  color: Array.from({ length: cc }, (_, i) => plane(i)),
10239
10172
  alpha: hasAlpha ? plane(cc) : void 0,
10240
- palette: ctx.palette
10241
- });
10242
- if (hasAlpha) unmatteWhite(data);
10173
+ palette: ctx.palette,
10174
+ cmykToRgb: ctx.cmykToRgb
10175
+ };
10176
+ const deep = hasAlpha || set.cmykToRgb ? null : toRgbaDeep(set);
10177
+ let surface;
10178
+ if (deep) surface = surfaceFromDeepPixels({ width, height, data: deep }, 4);
10179
+ else {
10180
+ const data = toRgba8(set);
10181
+ if (hasAlpha) unmatteWhite(data);
10182
+ surface = surfaceFromPixels({ width, height, data }, 4);
10183
+ }
10243
10184
  return {
10244
10185
  type: "pixel",
10245
10186
  id: ctx.newId("Background"),
@@ -10247,7 +10188,7 @@ function mergedLayer(ctx) {
10247
10188
  visible: true,
10248
10189
  opacity: 1,
10249
10190
  blend: "normal",
10250
- surface: surfaceFromPixels({ width, height, data }, 4),
10191
+ surface,
10251
10192
  offset: { x: 0, y: 0 }
10252
10193
  };
10253
10194
  }
@@ -10270,6 +10211,28 @@ function psdToLayers(file, options = {}) {
10270
10211
  depth: options.depth ?? 0,
10271
10212
  dpi: resolution(file) ?? 72
10272
10213
  };
10214
+ let cmykProfile = null;
10215
+ if (header.colorMode === MODE_CMYK && !ctx.skipPixels) {
10216
+ const icc = resource(file, 1039);
10217
+ let src = null;
10218
+ if (icc) {
10219
+ try {
10220
+ const p = parseProfile(icc);
10221
+ if (p.colorSpace === "cmyk") {
10222
+ src = p;
10223
+ cmykProfile = { name: p.description || "Embedded CMYK profile", icc: icc.slice() };
10224
+ } else warn.extra.push(`The CMYK file embeds a ${p.colorSpace.toUpperCase()} profile; the default coated CMYK profile was used.`);
10225
+ } catch (e) {
10226
+ warn.extra.push(`The CMYK profile could not be read (${e instanceof Error ? e.message : String(e)}); the default coated CMYK profile was used.`);
10227
+ }
10228
+ }
10229
+ if (!src) {
10230
+ src = builtinProfile("coated-cmyk");
10231
+ cmykProfile = { builtin: "coated-cmyk", name: src.description };
10232
+ }
10233
+ const t = Transform.create(src, srgbProfile(), { intent: "relative", bpc: true });
10234
+ ctx.cmykToRgb = (ink, out) => t.convert8(ink, 4, out, 4, false);
10235
+ }
10273
10236
  for (const block of file.globalBlocks) {
10274
10237
  if (LINKED_FILE_KEYS.includes(block.key)) {
10275
10238
  for (const f of parseLinkedFiles(block.data)) if (!ctx.linked.has(f.uuid)) ctx.linked.set(f.uuid, f);
@@ -10291,10 +10254,12 @@ function psdToLayers(file, options = {}) {
10291
10254
  }
10292
10255
  }
10293
10256
  const mode = COLOR_MODES[header.colorMode] ?? `mode ${header.colorMode}`;
10294
- if (mode !== "rgb" || header.depth !== 8) {
10295
- warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to 8-bit RGB.`);
10257
+ if (mode !== "rgb" && header.depth > 8 && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP) {
10258
+ warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to ${header.depth}-bit RGB.`);
10259
+ } else if (mode !== "rgb" || header.depth !== 8 && header.depth !== 16 && header.depth !== 32) {
10260
+ const how = header.colorMode === MODE_CMYK ? ` through ${cmykProfile?.name ?? "its profile"}` : "";
10261
+ warn.extra.push(`The file is ${header.depth}-bit ${mode}; it was converted to 8-bit RGB${how}.`);
10296
10262
  }
10297
- if (resource(file, 1039)) warn.extra.push("The embedded ICC profile is ignored; colours are read as sRGB.");
10298
10263
  let layers = [];
10299
10264
  if (file.layers.length) {
10300
10265
  const tree = layerTree(file);
@@ -10327,7 +10292,10 @@ function psdToLayers(file, options = {}) {
10327
10292
  resolution: resolution(file),
10328
10293
  patterns: [...ctx.patterns.values()],
10329
10294
  ...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)) } } : {},
10330
- info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels }
10295
+ info: { psb: header.psb, depth: header.depth, colorMode: mode, channels: header.channels },
10296
+ ...cmykProfile ? { sourceMode: { mode: "cmyk", profile: cmykProfile } } : header.colorMode === MODE_LAB ? { sourceMode: { mode: "lab" } } : {},
10297
+ ...resource(file, 1039) ? { iccProfile: resource(file, 1039).slice() } : {},
10298
+ bitDepth: (header.depth === 16 || header.depth === 32) && header.colorMode !== MODE_INDEXED && header.colorMode !== MODE_BITMAP ? header.depth : 8
10331
10299
  };
10332
10300
  }
10333
10301
  function importPsd(bytes, options = {}) {
@@ -11020,11 +10988,18 @@ function sectionBlock(kind, blendKey) {
11020
10988
  return w.result();
11021
10989
  }
11022
10990
  var toRect = (r) => ({ top: r.y, left: r.x, bottom: r.y + r.height, right: r.x + r.width });
11023
- function rleChannel(id, plane, width, height, psb) {
11024
- return { id, compression: 1, data: encodeRle(plane, { planes: 1, width, height, depth: 8, psb }) };
10991
+ function rleChannel(id, plane, width, height, psb, depth = 8) {
10992
+ const layout = { planes: 1, width, height, depth, psb };
10993
+ if (depth === 32) return { id, compression: 3, data: encodeZipPredicted(plane, layout) };
10994
+ return { id, compression: 1, data: encodeRle(plane, layout) };
10995
+ }
10996
+ function surfacePlanes(surface, bounds, depth) {
10997
+ const n = bounds.width * bounds.height;
10998
+ if (depth === 8) return rgbaToPlanes(readRegion(surface, bounds), n);
10999
+ return deepToPlanes(readDeepRegion(surface, bounds, depth), n);
11025
11000
  }
11026
11001
  var emptyChannel = (id) => ({ id, compression: 0, data: new Uint8Array(0) });
11027
- function maskChannel(mask, ox, oy, psb) {
11002
+ function maskChannel(mask, ox, oy, psb, depth = 8) {
11028
11003
  if (mask.source) throw new PsdError("A parametric mask must be baked before export.");
11029
11004
  const bounds = contentBounds(mask.surface);
11030
11005
  const def = mask.defaultValue;
@@ -11035,7 +11010,8 @@ function maskChannel(mask, ox, oy, psb) {
11035
11010
  if (!bounds) return { channel: emptyChannel(CHANNEL_USER_MASK), mask: m };
11036
11011
  const plane = readRegion(mask.surface, bounds);
11037
11012
  m.rect = toRect({ ...bounds, x: bounds.x + ox, y: bounds.y + oy });
11038
- return { channel: rleChannel(CHANNEL_USER_MASK, new Uint8Array(plane.buffer, plane.byteOffset, plane.length), bounds.width, bounds.height, psb), mask: m };
11013
+ const bytes = planeAtDepth(new Uint8Array(plane.buffer, plane.byteOffset, plane.length), depth);
11014
+ return { channel: rleChannel(CHANNEL_USER_MASK, bytes, bounds.width, bounds.height, psb, depth), mask: m };
11039
11015
  }
11040
11016
  function lockBits(layer) {
11041
11017
  const l = layer.locks;
@@ -11114,7 +11090,23 @@ function placedUnchanged(layer, idnt, placedId) {
11114
11090
  }
11115
11091
  function exportPsd(input) {
11116
11092
  const { width, height } = input;
11093
+ const depth = input.depth ?? 8;
11117
11094
  if (width < 1 || height < 1) throw new PsdError("The document is empty.");
11095
+ const mode = input.colorMode ?? "rgb";
11096
+ if (mode !== "rgb" && !input.colorPlanes) throw new PsdError(`A ${mode.toUpperCase()} file needs colorPlanes to convert the pixels.`);
11097
+ if (mode !== "rgb" && depth !== 8) throw new PsdError(`${mode.toUpperCase()} files are written at 8 bits per channel.`);
11098
+ const colorIds = mode === "cmyk" ? [0, 1, 2, 3] : [0, 1, 2];
11099
+ const colorPlanes = (rgba, n2) => mode === "rgb" ? rgbaToPlanes(rgba, n2).slice(0, 3) : input.colorPlanes(rgba, n2);
11100
+ const pixelChannels = (rgba, w, h) => {
11101
+ const n2 = w * h;
11102
+ const alpha = rgbaToPlanes(rgba, n2)[3];
11103
+ return [rleChannel(CHANNEL_ALPHA, alpha, w, h, psb), ...colorPlanes(rgba, n2).map((p, i) => rleChannel(i, p, w, h, psb))];
11104
+ };
11105
+ const surfaceChannels = (surface, bounds) => {
11106
+ if (mode !== "rgb") return pixelChannels(readRegion(surface, bounds), bounds.width, bounds.height);
11107
+ const [r, g, b, a2] = surfacePlanes(surface, bounds, depth);
11108
+ return [CHANNEL_ALPHA, 0, 1, 2].map((id, i) => rleChannel(id, [a2, r, g, b][i], bounds.width, bounds.height, psb, depth));
11109
+ };
11118
11110
  const psb = width > PSD_MAX_DIMENSION || height > PSD_MAX_DIMENSION;
11119
11111
  const records = [];
11120
11112
  let nextId = 0;
@@ -11158,7 +11150,7 @@ function exportPsd(input) {
11158
11150
  case "group": {
11159
11151
  records.push({
11160
11152
  rect: EMPTY_RECT,
11161
- channels: [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel),
11153
+ channels: [CHANNEL_ALPHA, ...colorIds].map(emptyChannel),
11162
11154
  blendKey: "norm",
11163
11155
  opacity: 255,
11164
11156
  clipping: 0,
@@ -11175,12 +11167,12 @@ function exportPsd(input) {
11175
11167
  const rec = {
11176
11168
  ...base,
11177
11169
  rect: EMPTY_RECT,
11178
- channels: [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel),
11170
+ channels: [CHANNEL_ALPHA, ...colorIds].map(emptyChannel),
11179
11171
  blendKey,
11180
11172
  flags: base.flags | FLAG_PIXELS_IRRELEVANT
11181
11173
  };
11182
11174
  if (layer.mask) {
11183
- const m = maskChannel(layer.mask, 0, 0, psb);
11175
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11184
11176
  rec.channels.push(m.channel);
11185
11177
  rec.mask = m.mask;
11186
11178
  }
@@ -11192,11 +11184,11 @@ function exportPsd(input) {
11192
11184
  const rec = {
11193
11185
  ...common2(layer, [{ key: block.key, data: block.data }]),
11194
11186
  rect: EMPTY_RECT,
11195
- channels: [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel),
11187
+ channels: [CHANNEL_ALPHA, ...colorIds].map(emptyChannel),
11196
11188
  blendKey: BLEND_TO_PSD[layer.blend] ?? "norm"
11197
11189
  };
11198
11190
  if (layer.mask) {
11199
- const m = maskChannel(layer.mask, 0, 0, psb);
11191
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11200
11192
  rec.channels.push(m.channel);
11201
11193
  rec.mask = m.mask;
11202
11194
  }
@@ -11213,20 +11205,13 @@ function exportPsd(input) {
11213
11205
  const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
11214
11206
  const bounds = contentBounds(layer.surface);
11215
11207
  if (bounds) {
11216
- const n2 = bounds.width * bounds.height;
11217
- const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
11218
11208
  rec.rect = toRect({ ...bounds, x: bounds.x + layer.offset.x, y: bounds.y + layer.offset.y });
11219
- rec.channels = [
11220
- rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
11221
- rleChannel(0, r2, bounds.width, bounds.height, psb),
11222
- rleChannel(1, g2, bounds.width, bounds.height, psb),
11223
- rleChannel(2, b2, bounds.width, bounds.height, psb)
11224
- ];
11209
+ rec.channels = surfaceChannels(layer.surface, bounds);
11225
11210
  } else {
11226
- rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
11211
+ rec.channels = [CHANNEL_ALPHA, ...colorIds].map(emptyChannel);
11227
11212
  }
11228
11213
  if (layer.mask) {
11229
- const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb);
11214
+ const m = maskChannel(layer.mask, layer.offset.x, layer.offset.y, psb, depth);
11230
11215
  rec.channels.push(m.channel);
11231
11216
  rec.mask = m.mask;
11232
11217
  }
@@ -11264,20 +11249,13 @@ function exportPsd(input) {
11264
11249
  const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
11265
11250
  const bounds = contentBounds(layer.surface);
11266
11251
  if (bounds) {
11267
- const n2 = bounds.width * bounds.height;
11268
- const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
11269
11252
  rec.rect = toRect(bounds);
11270
- rec.channels = [
11271
- rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
11272
- rleChannel(0, r2, bounds.width, bounds.height, psb),
11273
- rleChannel(1, g2, bounds.width, bounds.height, psb),
11274
- rleChannel(2, b2, bounds.width, bounds.height, psb)
11275
- ];
11253
+ rec.channels = surfaceChannels(layer.surface, bounds);
11276
11254
  } else {
11277
- rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
11255
+ rec.channels = [CHANNEL_ALPHA, ...colorIds].map(emptyChannel);
11278
11256
  }
11279
11257
  if (layer.mask) {
11280
- const m = maskChannel(layer.mask, 0, 0, psb);
11258
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11281
11259
  rec.channels.push(m.channel);
11282
11260
  rec.mask = m.mask;
11283
11261
  }
@@ -11292,7 +11270,7 @@ function exportPsd(input) {
11292
11270
  }
11293
11271
  if (layer.type === "shape") {
11294
11272
  const losses = /* @__PURE__ */ new Set();
11295
- for (const b2 of shapeBlocks(layer, width, height, input.resolution ?? 72, losses)) extra.push({ key: b2.key, data: padEven(b2.data) });
11273
+ for (const b of shapeBlocks(layer, width, height, input.resolution ?? 72, losses)) extra.push({ key: b.key, data: padEven(b.data) });
11296
11274
  for (const n2 of losses) note(n2, layer.name);
11297
11275
  if (layer.fill?.type === "pattern") patternIds2.add(layer.fill.patternId);
11298
11276
  if (layer.stroke?.paint.type === "pattern") patternIds2.add(layer.stroke.paint.patternId);
@@ -11302,20 +11280,13 @@ function exportPsd(input) {
11302
11280
  const rec = { ...common2(layer, extra), rect: EMPTY_RECT, channels: [], blendKey: BLEND_TO_PSD[layer.blend] ?? "norm" };
11303
11281
  const bounds = contentBounds(layer.surface);
11304
11282
  if (bounds) {
11305
- const n2 = bounds.width * bounds.height;
11306
- const [r2, g2, b2, a2] = rgbaToPlanes(readRegion(layer.surface, bounds), n2);
11307
11283
  rec.rect = toRect(bounds);
11308
- rec.channels = [
11309
- rleChannel(CHANNEL_ALPHA, a2, bounds.width, bounds.height, psb),
11310
- rleChannel(0, r2, bounds.width, bounds.height, psb),
11311
- rleChannel(1, g2, bounds.width, bounds.height, psb),
11312
- rleChannel(2, b2, bounds.width, bounds.height, psb)
11313
- ];
11284
+ rec.channels = surfaceChannels(layer.surface, bounds);
11314
11285
  } else {
11315
- rec.channels = [CHANNEL_ALPHA, 0, 1, 2].map(emptyChannel);
11286
+ rec.channels = [CHANNEL_ALPHA, ...colorIds].map(emptyChannel);
11316
11287
  }
11317
11288
  if (layer.mask) {
11318
- const m = maskChannel(layer.mask, 0, 0, psb);
11289
+ const m = maskChannel(layer.mask, 0, 0, psb, depth);
11319
11290
  rec.channels.push(m.channel);
11320
11291
  rec.mask = m.mask;
11321
11292
  }
@@ -11330,11 +11301,18 @@ function exportPsd(input) {
11330
11301
  if (records.length > 32767) throw new PsdError("A PSD holds at most 32767 layer records.");
11331
11302
  const n = width * height;
11332
11303
  if (input.merged.length < n * 4) throw new PsdError(`The merged image has ${input.merged.length} bytes, expected ${n * 4}.`);
11333
- const [r, g, b, a] = rgbaToPlanes(matteWhite(input.merged), n);
11304
+ const matted = matteWhite(input.merged);
11305
+ const a = rgbaToPlanes(matted, n)[3];
11334
11306
  const transparent = a.some((v) => v !== 255);
11335
- const planes = transparent ? [r, g, b, a] : [r, g, b];
11336
- const merged2 = new Uint8Array(n * planes.length);
11337
- planes.forEach((p, i) => merged2.set(p, i * n));
11307
+ let planes = [...colorPlanes(matted, n), ...transparent ? [a] : []].map((p) => planeAtDepth(p, depth));
11308
+ const deep = input.mergedDeep;
11309
+ if (deep && depth !== 8 && deep.length >= n * 4 && (deep instanceof Uint16Array ? depth === 16 : depth === 32)) {
11310
+ const dp = deepToPlanes(matteWhiteDeep(deep), n);
11311
+ planes = transparent ? dp : dp.slice(0, 3);
11312
+ }
11313
+ const planeBytes = n * (depth >> 3);
11314
+ const merged2 = new Uint8Array(planeBytes * planes.length);
11315
+ planes.forEach((p, i) => merged2.set(p, i * planeBytes));
11338
11316
  const res = Math.max(1, input.resolution ?? 72);
11339
11317
  const rw = new PsdWriter();
11340
11318
  for (let k = 0; k < 2; k++) {
@@ -11352,6 +11330,7 @@ function exportPsd(input) {
11352
11330
  { id: 1005, name: "", data: rw.result() },
11353
11331
  { id: 1057, name: "", data: version.result() }
11354
11332
  ];
11333
+ if (input.iccProfile?.length) resources.push({ id: 1039, name: "", data: input.iccProfile });
11355
11334
  if (input.globalLight) {
11356
11335
  const i32 = (v) => {
11357
11336
  const w = new PsdWriter();
@@ -11384,14 +11363,14 @@ function exportPsd(input) {
11384
11363
  if (filterItems.length) globalBlocks.push({ key: "FEid", data: writeFilterEffects(filterItems) });
11385
11364
  const bytes = writePsd(
11386
11365
  {
11387
- header: { psb, channels: planes.length, width, height, depth: 8, colorMode: 3 },
11366
+ header: { psb, channels: planes.length, width, height, depth, colorMode: mode === "cmyk" ? 4 : mode === "lab" ? 9 : 3 },
11388
11367
  colorModeData: new Uint8Array(0),
11389
11368
  resources,
11390
11369
  layers: records,
11391
11370
  mergedAlpha: transparent && records.length > 0,
11392
11371
  globalBlocks,
11393
- imageCompression: 1,
11394
- imageData: encodeRle(merged2, { planes: planes.length, width, height, depth: 8, psb })
11372
+ imageCompression: depth === 32 ? 0 : 1,
11373
+ imageData: depth === 32 ? merged2 : encodeRle(merged2, { planes: planes.length, width, height, depth, psb })
11395
11374
  },
11396
11375
  encodeLegacyName
11397
11376
  );
@@ -11527,6 +11506,7 @@ export {
11527
11506
  activeAdjustmentLayers,
11528
11507
  evaluateAdjustmentLayers,
11529
11508
  applyAdjustmentLayers,
11509
+ applyAdjustmentLayersFloat,
11530
11510
  adjustmentLayersKey,
11531
11511
  applyAdjustments,
11532
11512
  applyLegacyAdjustments,
@@ -11534,9 +11514,9 @@ export {
11534
11514
  applyBoxBlur,
11535
11515
  applyDepthMask,
11536
11516
  removeAlpha,
11517
+ TEXT_ALIGNS,
11537
11518
  SHAPE_OPERATIONS,
11538
11519
  LIVE_SHAPE_KINDS,
11539
- TEXT_ALIGNS,
11540
11520
  newLayerId,
11541
11521
  pixelLayers,
11542
11522
  developFilter,
@@ -11553,6 +11533,7 @@ export {
11553
11533
  depthMaskAlpha,
11554
11534
  runLayerFilters,
11555
11535
  LayerCompositor,
11536
+ compositeDeep,
11556
11537
  DEFAULT_ADJUSTMENTS_VALUES,
11557
11538
  DEFAULT_TRANSFORM_VALUES,
11558
11539
  DEFAULT_DEPTH_MASK_VALUES,
@@ -11612,18 +11593,6 @@ export {
11612
11593
  shapeFromAnnotation,
11613
11594
  annotationBlend,
11614
11595
  annotationOfShape,
11615
- DEFAULT_TEXT_STYLE,
11616
- DEFAULT_AUTO_LEADING,
11617
- fitRuns,
11618
- styleAt,
11619
- restyleRange,
11620
- spliceRuns,
11621
- paragraphRanges,
11622
- fitParagraphRuns,
11623
- fontOf,
11624
- layoutText,
11625
- textIndexAt,
11626
- caretAt,
11627
11596
  TEXT_RENDER_MARGIN,
11628
11597
  textMatrix,
11629
11598
  textOutlines,
@@ -11725,6 +11694,8 @@ export {
11725
11694
  serializePatterns,
11726
11695
  deserializePatterns,
11727
11696
  encodeSurface,
11697
+ encodeDeepSurface,
11698
+ decodeDeepSurface,
11728
11699
  serializeEffects,
11729
11700
  deserializeEffects,
11730
11701
  serializeLayer,
@@ -11764,4 +11735,4 @@ export {
11764
11735
  smartContentsFile,
11765
11736
  exportPsd
11766
11737
  };
11767
- //# sourceMappingURL=chunk-CZOXTEMN.js.map
11738
+ //# sourceMappingURL=chunk-XICA4PVO.js.map