ag-psd 31.0.3 → 32.0.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 (138) hide show
  1. package/.v8-cache/v24.7.0-x64-ef5a0af0/00d0e0b4 +0 -0
  2. package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
  3. package/.v8-cache/v24.7.0-x64-ef5a0af0/0cc76730 +0 -0
  4. package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
  5. package/.v8-cache/v24.7.0-x64-ef5a0af0/20729831 +0 -0
  6. package/.v8-cache/v24.7.0-x64-ef5a0af0/214a593b +0 -0
  7. package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
  8. package/.v8-cache/v24.7.0-x64-ef5a0af0/25f8b84a +0 -0
  9. package/.v8-cache/v24.7.0-x64-ef5a0af0/27518289 +0 -0
  10. package/.v8-cache/v24.7.0-x64-ef5a0af0/330ef2d9 +0 -0
  11. package/.v8-cache/v24.7.0-x64-ef5a0af0/37ff16b8 +0 -0
  12. package/.v8-cache/v24.7.0-x64-ef5a0af0/3f72a97c +0 -0
  13. package/.v8-cache/v24.7.0-x64-ef5a0af0/4511bacf +0 -0
  14. package/.v8-cache/v24.7.0-x64-ef5a0af0/68416cb2 +0 -0
  15. package/.v8-cache/v24.7.0-x64-ef5a0af0/71df9cb3 +0 -0
  16. package/.v8-cache/v24.7.0-x64-ef5a0af0/75efccd4 +0 -0
  17. package/.v8-cache/v24.7.0-x64-ef5a0af0/762f9305 +0 -0
  18. package/.v8-cache/v24.7.0-x64-ef5a0af0/7bcfc50a +0 -0
  19. package/.v8-cache/v24.7.0-x64-ef5a0af0/7ea06cea +0 -0
  20. package/.v8-cache/v24.7.0-x64-ef5a0af0/825e9a05 +0 -0
  21. package/.v8-cache/v24.7.0-x64-ef5a0af0/87372817 +0 -0
  22. package/.v8-cache/v24.7.0-x64-ef5a0af0/87cf2209 +0 -0
  23. package/.v8-cache/v24.7.0-x64-ef5a0af0/891a7c73 +0 -0
  24. package/.v8-cache/v24.7.0-x64-ef5a0af0/8b68a3a2 +0 -0
  25. package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
  26. package/.v8-cache/v24.7.0-x64-ef5a0af0/a1d12a93 +0 -0
  27. package/.v8-cache/v24.7.0-x64-ef5a0af0/a7e80865 +0 -0
  28. package/.v8-cache/v24.7.0-x64-ef5a0af0/ac317c9c +0 -0
  29. package/.v8-cache/v24.7.0-x64-ef5a0af0/acc36e66 +0 -0
  30. package/.v8-cache/v24.7.0-x64-ef5a0af0/b3c2fab7 +0 -0
  31. package/.v8-cache/v24.7.0-x64-ef5a0af0/b8569d6b +0 -0
  32. package/.v8-cache/v24.7.0-x64-ef5a0af0/b8b073c4 +0 -0
  33. package/.v8-cache/v24.7.0-x64-ef5a0af0/bb489c89 +0 -0
  34. package/.v8-cache/v24.7.0-x64-ef5a0af0/c0b789d2 +0 -0
  35. package/.v8-cache/v24.7.0-x64-ef5a0af0/c314aece +0 -0
  36. package/.v8-cache/v24.7.0-x64-ef5a0af0/c46725e1 +0 -0
  37. package/.v8-cache/v24.7.0-x64-ef5a0af0/c794cb34 +0 -0
  38. package/.v8-cache/v24.7.0-x64-ef5a0af0/cd4ae980 +0 -0
  39. package/.v8-cache/v24.7.0-x64-ef5a0af0/cfc49f4f +0 -0
  40. package/.v8-cache/v24.7.0-x64-ef5a0af0/cff9434a +0 -0
  41. package/.v8-cache/v24.7.0-x64-ef5a0af0/d02dd6f7 +0 -0
  42. package/.v8-cache/v24.7.0-x64-ef5a0af0/dc86f000 +0 -0
  43. package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +0 -0
  44. package/.v8-cache/v24.7.0-x64-ef5a0af0/e6735171 +0 -0
  45. package/.v8-cache/v24.7.0-x64-ef5a0af0/f5417276 +0 -0
  46. package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
  47. package/.v8-cache/v24.7.0-x64-ef5a0af0/f74d3518 +0 -0
  48. package/.v8-cache/v24.7.0-x64-ef5a0af0/f886deac +0 -0
  49. package/.v8-cache/v24.7.0-x64-ef5a0af0/fd0a2987 +0 -0
  50. package/.v8-cache/v24.7.0-x64-ef5a0af0/fe349423 +0 -0
  51. package/CHANGELOG.md +29 -0
  52. package/dist/abr.js +12 -5
  53. package/dist/abr.js.map +1 -1
  54. package/dist/additionalInfo.d.ts +2 -0
  55. package/dist/additionalInfo.js +123 -68
  56. package/dist/additionalInfo.js.map +1 -1
  57. package/dist/bundle.js +1365 -632
  58. package/dist/descriptor.d.ts +15 -2
  59. package/dist/descriptor.js +329 -100
  60. package/dist/descriptor.js.map +1 -1
  61. package/dist/effectsHelpers.js +12 -12
  62. package/dist/effectsHelpers.js.map +1 -1
  63. package/dist/engineData.d.ts +3 -1
  64. package/dist/engineData.js +34 -13
  65. package/dist/engineData.js.map +1 -1
  66. package/dist/engineData2.js +50 -21
  67. package/dist/engineData2.js.map +1 -1
  68. package/dist/helpers.d.ts +5 -2
  69. package/dist/helpers.js +18 -4
  70. package/dist/helpers.js.map +1 -1
  71. package/dist/imageResources.js +45 -21
  72. package/dist/imageResources.js.map +1 -1
  73. package/dist/index.js +1 -0
  74. package/dist/index.js.map +1 -1
  75. package/dist/jpeg.js +27 -7
  76. package/dist/jpeg.js.map +1 -1
  77. package/dist/psd.d.ts +6 -1
  78. package/dist/psdReader.d.ts +2 -2
  79. package/dist/psdReader.js +457 -270
  80. package/dist/psdReader.js.map +1 -1
  81. package/dist/psdWriter.d.ts +2 -0
  82. package/dist/psdWriter.js +98 -76
  83. package/dist/psdWriter.js.map +1 -1
  84. package/dist/text.js +126 -23
  85. package/dist/text.js.map +1 -1
  86. package/dist/utf8.js +36 -15
  87. package/dist/utf8.js.map +1 -1
  88. package/dist-es/abr.js +12 -5
  89. package/dist-es/abr.js.map +1 -1
  90. package/dist-es/additionalInfo.d.ts +2 -0
  91. package/dist-es/additionalInfo.js +123 -68
  92. package/dist-es/additionalInfo.js.map +1 -1
  93. package/dist-es/descriptor.d.ts +15 -2
  94. package/dist-es/descriptor.js +329 -100
  95. package/dist-es/descriptor.js.map +1 -1
  96. package/dist-es/effectsHelpers.js +12 -12
  97. package/dist-es/effectsHelpers.js.map +1 -1
  98. package/dist-es/engineData.d.ts +3 -1
  99. package/dist-es/engineData.js +34 -13
  100. package/dist-es/engineData.js.map +1 -1
  101. package/dist-es/engineData2.js +50 -21
  102. package/dist-es/engineData2.js.map +1 -1
  103. package/dist-es/helpers.d.ts +5 -2
  104. package/dist-es/helpers.js +18 -4
  105. package/dist-es/helpers.js.map +1 -1
  106. package/dist-es/imageResources.js +45 -21
  107. package/dist-es/imageResources.js.map +1 -1
  108. package/dist-es/index.js +1 -0
  109. package/dist-es/index.js.map +1 -1
  110. package/dist-es/jpeg.js +27 -7
  111. package/dist-es/jpeg.js.map +1 -1
  112. package/dist-es/psd.d.ts +6 -1
  113. package/dist-es/psdReader.d.ts +2 -2
  114. package/dist-es/psdReader.js +457 -270
  115. package/dist-es/psdReader.js.map +1 -1
  116. package/dist-es/psdWriter.d.ts +2 -0
  117. package/dist-es/psdWriter.js +98 -76
  118. package/dist-es/psdWriter.js.map +1 -1
  119. package/dist-es/text.js +126 -23
  120. package/dist-es/text.js.map +1 -1
  121. package/dist-es/utf8.js +36 -15
  122. package/dist-es/utf8.js.map +1 -1
  123. package/package.json +1 -1
  124. package/src/abr.ts +14 -6
  125. package/src/additionalInfo.ts +127 -66
  126. package/src/descriptor.ts +347 -107
  127. package/src/effectsHelpers.ts +9 -9
  128. package/src/engineData.ts +36 -13
  129. package/src/engineData2.ts +468 -432
  130. package/src/helpers.ts +19 -4
  131. package/src/imageResources.ts +49 -22
  132. package/src/index.ts +1 -0
  133. package/src/jpeg.ts +24 -9
  134. package/src/psd.ts +3 -1
  135. package/src/psdReader.ts +477 -260
  136. package/src/psdWriter.ts +100 -83
  137. package/src/text.ts +122 -12
  138. package/src/utf8.ts +35 -17
package/dist-es/utf8.js CHANGED
@@ -18,30 +18,44 @@ function charLengthInBytes(code) {
18
18
  return 4;
19
19
  }
20
20
  }
21
- // Reads a scalar value at index `i`, replacing unpaired surrogates with U+FFFD,
21
+ // Returns scalar value at index `i` (combining surrogate pairs), replacing unpaired surrogates with U+FFFD,
22
22
  // matching how TextEncoder converts a string to a sequence of Unicode scalar values.
23
+ // Values above 0xffff always take 2 UTF-16 code units.
23
24
  function codePointAt(value, i) {
24
25
  const code = value.charCodeAt(i);
26
+ if (code < 0xd800 || code > 0xdfff)
27
+ return code;
25
28
  // high surrogate
26
- if (code >= 0xd800 && code <= 0xdbff && (i + 1) < value.length) {
29
+ if (code <= 0xdbff && (i + 1) < value.length) {
27
30
  const extra = value.charCodeAt(i + 1);
28
31
  // low surrogate
29
32
  if (extra >= 0xdc00 && extra <= 0xdfff) {
30
- return { code: ((code & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000, size: 2 };
33
+ return ((code & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
31
34
  }
32
35
  }
33
36
  // unpaired surrogate (lone high or lone low)
34
- if (code >= 0xd800 && code <= 0xdfff) {
35
- return { code: 0xfffd, size: 1 };
36
- }
37
- return { code, size: 1 };
37
+ return 0xfffd;
38
38
  }
39
39
  function stringLengthInBytes(value) {
40
40
  let result = 0;
41
- for (let i = 0; i < value.length;) {
42
- const { code, size } = codePointAt(value, i);
43
- result += charLengthInBytes(code);
44
- i += size;
41
+ for (let i = 0; i < value.length; i++) {
42
+ const code = value.charCodeAt(i);
43
+ if (code < 0x80) {
44
+ result += 1;
45
+ }
46
+ else if (code < 0x800) {
47
+ result += 2;
48
+ }
49
+ else {
50
+ const scalar = codePointAt(value, i);
51
+ if (scalar > 0xffff) {
52
+ result += 4;
53
+ i++;
54
+ }
55
+ else {
56
+ result += 3;
57
+ }
58
+ }
45
59
  }
46
60
  return result;
47
61
  }
@@ -70,10 +84,17 @@ function writeCharacter(buffer, offset, code) {
70
84
  return length;
71
85
  }
72
86
  function encodeStringTo(buffer, offset, value) {
73
- for (let i = 0; i < value.length;) {
74
- const { code, size } = codePointAt(value, i);
75
- offset += writeCharacter(buffer, offset, code);
76
- i += size;
87
+ for (let i = 0; i < value.length; i++) {
88
+ const code = value.charCodeAt(i);
89
+ if (code < 0x80) {
90
+ buffer[offset++] = code;
91
+ }
92
+ else {
93
+ const scalar = codePointAt(value, i);
94
+ if (scalar > 0xffff)
95
+ i++;
96
+ offset += writeCharacter(buffer, offset, scalar);
97
+ }
77
98
  }
78
99
  return offset;
79
100
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utf8.js","sourceRoot":"../src/","sources":["utf8.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utf8.js","sourceRoot":"../src/","sources":["utf8.ts"],"names":[],"mappings":";;AAkCA,kDAuBC;AA6BD,wCAcC;AAED,oCAQC;AAID,oCAiFC;AAnMD,SAAS,iBAAiB,CAAC,IAAY;IACtC,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,CAAC;IACV,CAAC;SAAM,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,CAAC;IACV,CAAC;SAAM,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,CAAC;IACV,CAAC;SAAM,CAAC;QACP,OAAO,CAAC,CAAC;IACV,CAAC;AACF,CAAC;AAED,4GAA4G;AAC5G,qFAAqF;AACrF,uDAAuD;AACvD,SAAS,WAAW,CAAC,KAAa,EAAE,CAAS;IAC5C,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAEjC,IAAI,IAAI,GAAG,MAAM,IAAI,IAAI,GAAG,MAAM;QAAE,OAAO,IAAI,CAAC;IAEhD,iBAAiB;IACjB,IAAI,IAAI,IAAI,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAEtC,gBAAgB;QAChB,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACxC,OAAO,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC;QAC3D,CAAC;IACF,CAAC;IAED,6CAA6C;IAC7C,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAgB,mBAAmB,CAAC,KAAa;IAChD,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAEjC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,CAAC;QACb,CAAC;aAAM,CAAC;YACP,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAErC,IAAI,MAAM,GAAG,MAAM,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC,CAAC;gBACZ,CAAC,EAAE,CAAC;YACL,CAAC;iBAAM,CAAC;gBACP,MAAM,IAAI,CAAC,CAAC;YACb,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAS,cAAc,CAAC,MAA2B,EAAE,MAAc,EAAE,IAAY;IAChF,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAEvC,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,CAAC;YACL,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YACtB,MAAM;QACP,KAAK,CAAC;YACL,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAC7C,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAC1C,MAAM;QACP,KAAK,CAAC;YACL,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAC9C,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACjD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAC1C,MAAM;QACP;YACC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAC9C,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAClD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YACjD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;YAC1C,MAAM;IACR,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAgB,cAAc,CAAC,MAA2B,EAAE,MAAc,EAAE,KAAa;IACxF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAEjC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;YACjB,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC;QACzB,CAAC;aAAM,CAAC;YACP,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACrC,IAAI,MAAM,GAAG,MAAM;gBAAE,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAClD,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,SAAgB,YAAY,CAAC,KAAa;IACzC,IAAI,KAAK,CAAC,MAAM,GAAG,IAAI,IAAI,OAAO,WAAW,KAAK,WAAW,EAAE,CAAC;QAC/D,OAAO,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1D,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,sFAAsF;AACtF,kGAAkG;AAClG,SAAgB,YAAY,CAAC,KAAiB;IAC7C,IAAI,KAAK,CAAC,UAAU,GAAG,IAAI,IAAI,OAAO,WAAW,KAAK,WAAW,EAAE,CAAC;QACnE,OAAO,CAAC,IAAI,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,SAAS,aAAa,CAAC,IAAY;QAClC,IAAI,IAAI,GAAG,MAAM,EAAE,CAAC;YACnB,IAAI,IAAI,OAAO,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,KAAK,EAAE,GAAG,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;YACjE,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QAChC,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,IAAI,aAAa,GAAG,IAAI,CAAC;IACzB,IAAI,aAAa,GAAG,IAAI,CAAC;IAEzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACvB,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;gBAClB,aAAa,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;iBAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;gBACzC,WAAW,GAAG,CAAC,CAAC;gBAChB,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;YACzB,CAAC;iBAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;gBACzC,IAAI,IAAI,KAAK,IAAI;oBAAE,aAAa,GAAG,IAAI,CAAC;gBACxC,IAAI,IAAI,KAAK,IAAI;oBAAE,aAAa,GAAG,IAAI,CAAC;gBACxC,WAAW,GAAG,CAAC,CAAC;gBAChB,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;YACzB,CAAC;iBAAM,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;gBACzC,IAAI,IAAI,KAAK,IAAI;oBAAE,aAAa,GAAG,IAAI,CAAC;gBACxC,IAAI,IAAI,KAAK,IAAI;oBAAE,aAAa,GAAG,IAAI,CAAC;gBACxC,WAAW,GAAG,CAAC,CAAC;gBAChB,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACP,uBAAuB;gBACvB,aAAa,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YAED,SAAS;QACV,CAAC;QAED,IAAI,IAAI,GAAG,aAAa,IAAI,IAAI,GAAG,aAAa,EAAE,CAAC;YAClD,8FAA8F;YAC9F,SAAS,GAAG,CAAC,CAAC;YACd,WAAW,GAAG,CAAC,CAAC;YAChB,SAAS,GAAG,CAAC,CAAC;YACd,aAAa,GAAG,IAAI,CAAC;YACrB,aAAa,GAAG,IAAI,CAAC;YACrB,aAAa,CAAC,MAAM,CAAC,CAAC;YACtB,CAAC,EAAE,CAAC;YACJ,SAAS;QACV,CAAC;QAED,aAAa,GAAG,IAAI,CAAC;QACrB,aAAa,GAAG,IAAI,CAAC;QACrB,SAAS,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAC7C,SAAS,EAAE,CAAC;QAEZ,IAAI,SAAS,KAAK,WAAW;YAAE,SAAS;QAExC,aAAa,CAAC,SAAS,CAAC,CAAC;QACzB,SAAS,GAAG,CAAC,CAAC;QACd,WAAW,GAAG,CAAC,CAAC;QAChB,SAAS,GAAG,CAAC,CAAC;IACf,CAAC;IAED,qCAAqC;IACrC,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;QACvB,aAAa,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ag-psd",
3
- "version": "31.0.3",
3
+ "version": "32.0.0",
4
4
  "description": "Library for reading and writing PSD files",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist-es/index.js",
package/src/abr.ts CHANGED
@@ -403,6 +403,9 @@ interface DescDescriptor {
403
403
  }[];
404
404
  }
405
405
 
406
+ // sanity limits for brush sample dimensions (Photoshop brushes are limited to 5000px)
407
+ const MAX_BRUSH_SIZE = 10000;
408
+
406
409
  const toBrushType: { [key: string]: 'brush' | 'mixer brush' | 'smudge brush'; } = {
407
410
  _: 'brush',
408
411
  MixB: 'mixer brush',
@@ -529,7 +532,7 @@ export function readAbr(buffer: ArrayBufferView, options: { logMissingFeatures?:
529
532
  while (reader.offset < reader.view.byteLength) {
530
533
  checkSignature(reader, '8BIM');
531
534
  const type = readSignature(reader) as 'samp' | 'desc' | 'patt' | 'phry';
532
- let size = readUint32(reader);
535
+ const size = readUint32(reader);
533
536
  const end = reader.offset + size;
534
537
 
535
538
  switch (type) {
@@ -550,9 +553,16 @@ export function readAbr(buffer: ArrayBufferView, options: { logMissingFeatures?:
550
553
  const h = readInt32(reader) - y;
551
554
  const w = readInt32(reader) - x;
552
555
  if (w <= 0 || h <= 0) throw new Error('Invalid bounds');
556
+ if (w > MAX_BRUSH_SIZE || h > MAX_BRUSH_SIZE) {
557
+ throw new Error(`Brush sample too large (${w}x${h})`);
558
+ }
553
559
 
554
560
  const bithDepth = readInt16(reader);
555
561
  const compression = readUint8(reader); // 0 - raw, 1 - RLE
562
+ if (compression === 0 && w * h * (bithDepth === 16 ? 2 : 1) > brushEnd - reader.offset) {
563
+ throw new Error('Brush sample data out of bounds');
564
+ }
565
+
556
566
  const alpha = new Uint8Array(w * h);
557
567
 
558
568
  if (bithDepth === 8) {
@@ -760,11 +770,9 @@ export function readAbr(buffer: ArrayBufferView, options: { logMissingFeatures?:
760
770
  throw new Error(`Invalid brush type: ${type}`);
761
771
  }
762
772
 
763
- // align to 4 bytes
764
- while (size % 4) {
765
- reader.offset++;
766
- size++;
767
- }
773
+ // skip any unread data in the section and align to 4 bytes
774
+ reader.offset = end;
775
+ while (reader.offset % 4) reader.offset++;
768
776
  }
769
777
  } else {
770
778
  throw new Error(`Unsupported ABR version (${version})`);
@@ -1,9 +1,9 @@
1
1
  import { fromByteArray, toByteArray } from 'base64-js';
2
2
  import { readEffects, writeEffects } from './effectsHelpers';
3
- import { clamp, createEnum, layerColors, MOCK_HANDLERS } from './helpers';
3
+ import { clamp, createEnum, layerColors, MOCK_HANDLERS, normalizeLabAB } from './helpers';
4
4
  import { LayerAdditionalInfo, BezierPath, Psd, BrightnessAdjustment, ExposureAdjustment, VibranceAdjustment, ColorBalanceAdjustment, BlackAndWhiteAdjustment, PhotoFilterAdjustment, ChannelMixerChannel, ChannelMixerAdjustment, PosterizeAdjustment, ThresholdAdjustment, GradientMapAdjustment, CMYK, SelectiveColorAdjustment, ColorLookupAdjustment, LevelsAdjustmentChannel, LevelsAdjustment, CurvesAdjustment, CurvesAdjustmentChannel, HueSaturationAdjustment, HueSaturationAdjustmentChannel, PresetInfo, Color, ColorBalanceValues, WriteOptions, LinkedFile, PlacedLayerType, Warp, KeyDescriptorItem, BooleanOperation, LayerEffectsInfo, Annotation, LayerVectorMask, AnimationFrame, Timeline, PlacedLayerFilter, UnitsValue, Filter, PlacedLayer, ReadOptions, Layer } from './psd';
5
5
  import { PsdReader, readSignature, readUnicodeString, skipBytes, readUint32, readUint8, readFloat64, readUint16, readBytes, readInt16, checkSignature, readFloat32, readFixedPointPath32, readSection, readColor, readInt32, readPascalString, readUnicodeStringWithLength, readAsciiString, readPattern, readLayerInfo } from './psdReader';
6
- import { PsdWriter, writeZeros, writeSignature, writeBytes, writeUint32, writeUint16, writeFloat64, writeUint8, writeInt16, writeFloat32, writeFixedPointPath32, writeUnicodeString, writeSection, writeUnicodeStringWithPadding, writeColor, writePascalString, writeInt32, writePattern } from './psdWriter';
6
+ import { PsdWriter, writeZeros, writeSignature, writeBytes, writeUint32, writeUint16, writeFloat64, writeUint8, writeInt16, writeFloat32, writeFixedPointPath32, writeUnicodeString, writeSection, writeUnicodeStringWithPadding, writeColor, writePascalString, writeInt32, writePattern, writeUint64 } from './psdWriter';
7
7
  import { Annt, BlnM, DescriptorColor, DescriptorUnitsValue, parsePercent, parseUnits, parseUnitsOrNumber, QuiltWarpDescriptor, strokeStyleLineAlignment, strokeStyleLineCapType, strokeStyleLineJoinType, TextDescriptor, textGridding, unitsPercent, unitsValue, WarpDescriptor, warpStyle, writeVersionAndDescriptor, readVersionAndDescriptor, StrokeDescriptor, Ornt, horzVrtcToXY, LmfxDescriptor, Lfx2Descriptor, FrameListDescriptor, TimelineDescriptor, FrameDescriptor, xyToHorzVrtc, serializeEffects, parseEffects, parseColor, serializeColor, serializeVectorContent, parseVectorContent, parseTrackList, serializeTrackList, FractionDescriptor, BlrM, BlrQ, SmBQ, SmBM, DspM, UndA, Cnvr, RplS, SphM, Wvtp, ZZTy, Dstr, Chnl, MztT, Lns, blurType, DfsM, ExtT, ExtR, FlCl, CntE, WndM, Drct, IntE, IntC, FlMd, unitsPercentF, frac, ClrS, descBoundsToBounds, boundsToDescBounds, presetKindType, gradientInterpolationMethodType, PxScDescriptor } from './descriptor';
8
8
  import { serializeEngineData, parseEngineData } from './engineData';
9
9
  import { encodeEngineData, decodeEngineData } from './text';
@@ -13,6 +13,8 @@ import type { InternalImageResources } from './imageResources';
13
13
  export interface ExtendedWriteOptions extends WriteOptions {
14
14
  layerIds: Set<number>;
15
15
  layerToId: Map<any, number>;
16
+ explicitLayerIds?: Set<number>; // ids set on layers in the document (generated ids can't use them)
17
+ nextGeneratedLayerId?: number; // all ids below this one are already taken
16
18
  }
17
19
 
18
20
  type HasMethod = (target: LayerAdditionalInfo) => boolean;
@@ -49,11 +51,6 @@ function readLength64(reader: PsdReader) {
49
51
  return readUint32(reader);
50
52
  }
51
53
 
52
- function writeLength64(writer: PsdWriter, length: number) {
53
- writeUint32(writer, 0);
54
- writeUint32(writer, length);
55
- }
56
-
57
54
  addHandler(
58
55
  'TySh',
59
56
  hasKey('text'),
@@ -95,7 +92,7 @@ addHandler(
95
92
  if (text.boundingBox) target.text.boundingBox = descBoundsToBounds(text.boundingBox);
96
93
 
97
94
  if (text.EngineData) {
98
- const engineData = parseEngineData(text.EngineData);
95
+ const engineData = parseEngineData(text.EngineData, reader);
99
96
  const textData = decodeEngineData(engineData);
100
97
  // console.log(require('util').inspect(engineData, false, 99, false), 'utf8');
101
98
 
@@ -140,10 +137,10 @@ addHandler(
140
137
  writeInt16(writer, 1); // warp version
141
138
  writeVersionAndDescriptor(writer, '', 'warp', encodeWarp(warp));
142
139
 
143
- writeFloat32(writer, text.left!);
144
- writeFloat32(writer, text.top!);
145
- writeFloat32(writer, text.right!);
146
- writeFloat32(writer, text.bottom!);
140
+ writeFloat32(writer, text.left ?? 0);
141
+ writeFloat32(writer, text.top ?? 0);
142
+ writeFloat32(writer, text.right ?? 0);
143
+ writeFloat32(writer, text.bottom ?? 0);
147
144
 
148
145
  // writeZeros(writer, 2);
149
146
  },
@@ -586,15 +583,53 @@ addHandler(
586
583
  (writer, target) => writeSignature(writer, target.nameSource!),
587
584
  );
588
585
 
586
+ // these sections reference layer id
587
+ function layerNeedsId(target: LayerAdditionalInfo) {
588
+ return !!(target.animationFrames || target.timeline || target.comps);
589
+ }
590
+
591
+ function getExplicitLayerIds(psd: Psd, options: ExtendedWriteOptions) {
592
+ if (!options.explicitLayerIds) {
593
+ const ids = new Set<number>();
594
+ const addIds = (layers: Layer[] | undefined) => {
595
+ for (const layer of layers ?? []) {
596
+ if (layer.id !== undefined) ids.add(layer.id);
597
+ addIds(layer.children);
598
+ }
599
+ };
600
+ addIds(psd.children);
601
+ options.explicitLayerIds = ids;
602
+ }
603
+
604
+ return options.explicitLayerIds;
605
+ }
606
+
607
+ function getLayerId(target: LayerAdditionalInfo, options: ExtendedWriteOptions) {
608
+ const id = options.layerToId.get(target) ?? target.id;
609
+ if (id === undefined) throw new Error('Missing layer id');
610
+ return id;
611
+ }
612
+
589
613
  addHandler(
590
614
  'lyid',
591
- hasKey('id'),
615
+ target => target.id !== undefined || layerNeedsId(target),
592
616
  (reader, target) => {
593
617
  target.id = readUint32(reader);
594
618
  },
595
- (writer, target, _psd, options) => {
596
- let id = target.id!;
597
- while (options.layerIds.has(id)) id += 100; // make sure we don't have duplicate layer ids
619
+ (writer, target, psd, options) => {
620
+ let id: number;
621
+
622
+ if (target.id !== undefined) {
623
+ id = target.id;
624
+ while (options.layerIds.has(id)) id += 100; // make sure we don't have duplicate layer ids
625
+ } else {
626
+ // generate id for layers that don't have it, if it's referenced by other sections
627
+ const explicitIds = getExplicitLayerIds(psd, options);
628
+ id = options.nextGeneratedLayerId ?? 1;
629
+ while (options.layerIds.has(id) || explicitIds.has(id)) id++;
630
+ options.nextGeneratedLayerId = id + 1;
631
+ }
632
+
598
633
  writeUint32(writer, id);
599
634
  options.layerIds.add(id);
600
635
  options.layerToId.set(target, id);
@@ -864,7 +899,7 @@ addHandler(
864
899
  writeZeros(writer, 3);
865
900
  writeSection(writer, 2, () => {
866
901
  const desc: FrameListDescriptor = {
867
- LaID: target.id ?? 0,
902
+ LaID: getLayerId(target, options),
868
903
  LaSt: [],
869
904
  };
870
905
 
@@ -922,9 +957,7 @@ addHandler(
922
957
  desc.trackList = serializeTrackList(timeline.tracks);
923
958
  }
924
959
 
925
- const id = options.layerToId.get(target) || target.id;
926
- if (!id) throw new Error('You need to provide layer.id value whan writing document with animations');
927
- desc.LyrI = id;
960
+ desc.LyrI = getLayerId(target, options);
928
961
 
929
962
  // console.log('WRITE:tmln', target.name, target.id, require('util').inspect(desc, false, 99, true));
930
963
  writeVersionAndDescriptor(writer, '', 'null', desc, 'anim');
@@ -950,16 +983,13 @@ addHandler(
950
983
  writeUint8(writer, 0); // copy (always false)
951
984
  writeZeros(writer, 3);
952
985
  writeSection(writer, 2, () => {
953
- const id = options.layerToId.get(target) || target.id;
954
- if (!id) throw new Error('You need to provide layer.id value whan writing document with layer comps');
955
-
956
986
  const desc: CmlsDescriptor = {} as any;
957
987
 
958
988
  if (comps.originalEffectsReferencePoint) {
959
989
  desc.origFXRefPoint = { Hrzn: comps.originalEffectsReferencePoint.x, Vrtc: comps.originalEffectsReferencePoint.y };
960
990
  }
961
991
 
962
- desc.LyrI = id;
992
+ desc.LyrI = getLayerId(target, options);
963
993
  desc.layerSettings = [];
964
994
 
965
995
  for (const item of comps.settings) {
@@ -980,7 +1010,7 @@ addHandler(
980
1010
 
981
1011
  addHandler(
982
1012
  'PxSc',
983
- () => false,
1013
+ hasKey('pixelSource'),
984
1014
  (reader, target) => {
985
1015
  const desc = readVersionAndDescriptor(reader, true) as PxScDescriptor;
986
1016
  // console.log('PxSc', require('util').inspect(desc, false, 99, true));
@@ -1017,7 +1047,7 @@ addHandler(
1017
1047
  _classID: 'PixelSource',
1018
1048
  pixelSourceType: 1986285651, // vdP
1019
1049
  descVersion: 1,
1020
- origin: { Hrzn: source.origin.x, Vrtc: source.origin.y },
1050
+ origin: { Hrzn: source.origin.x, Vrtc: source.origin.y }, // written as 'null' class with 'long' values (see writeDescriptorStructure)
1021
1051
  interpretation: {
1022
1052
  _name: '',
1023
1053
  _classID: 'footageInterpretation',
@@ -1997,7 +2027,7 @@ type SoLdDescriptorFilterItem = {
1997
2027
  Fltr: {
1998
2028
  _name: 'Perspective Warp';
1999
2029
  _classID: 'perspectiveWarpTransform';
2000
- quads: { indices: number[]; }[];
2030
+ quads: { _name?: ''; _classID?: string; indices: number[]; }[];
2001
2031
  vertices: HrznVrtcDescriptor[];
2002
2032
  warpedVertices: HrznVrtcDescriptor[];
2003
2033
  };
@@ -2048,11 +2078,13 @@ interface SoLdDescriptorFilter {
2048
2078
  }
2049
2079
 
2050
2080
  function uint8ToFloat32(array: Uint8Array) {
2051
- return new Float32Array(array.buffer.slice(array.byteOffset), 0, array.byteLength / 4);
2081
+ const length = Math.floor(array.byteLength / 4);
2082
+ return new Float32Array(array.buffer.slice(array.byteOffset, array.byteOffset + length * 4), 0, length);
2052
2083
  }
2053
2084
 
2054
2085
  function uint8ToUint32(array: Uint8Array) {
2055
- return new Uint32Array(array.buffer.slice(array.byteOffset), 0, array.byteLength / 4);
2086
+ const length = Math.floor(array.byteLength / 4);
2087
+ return new Uint32Array(array.buffer.slice(array.byteOffset, array.byteOffset + length * 4), 0, length);
2056
2088
  }
2057
2089
 
2058
2090
  function toUint8(array: Uint32Array | Float32Array) {
@@ -2510,7 +2542,7 @@ function parseFilterFXItem(f: SoLdDescriptorFilterItem, options: ReadOptions): F
2510
2542
  { x: f.Fltr.PuX2, y: f.Fltr.PuY2, },
2511
2543
  { x: f.Fltr.PuX3, y: f.Fltr.PuY3, },
2512
2544
  ],
2513
- puppetShapeList: f.Fltr.puppetShapeList!.map(p => ({
2545
+ puppetShapeList: (f.Fltr.puppetShapeList || []).map(p => ({
2514
2546
  rigidType: p.rigidType,
2515
2547
  // TODO: VrsM
2516
2548
  // TODO: VrsN
@@ -3245,7 +3277,7 @@ function serializeFilterFXItem(f: Filter): SoLdDescriptorFilterItem {
3245
3277
  _classID: 'rigidTransform',
3246
3278
  'null': ['Ordn.Trgt'], // TODO: ???
3247
3279
  rigidType: f.filter.rigidType,
3248
- puppetShapeList: f.filter.puppetShapeList.map(p => ({
3280
+ puppetShapeList: (f.filter.puppetShapeList || []).map(p => ({
3249
3281
  _name: '',
3250
3282
  _classID: 'puppetShape',
3251
3283
  rigidType: p.rigidType,
@@ -3356,7 +3388,7 @@ function serializeFilterFXItem(f: Filter): SoLdDescriptorFilterItem {
3356
3388
  _classID: 'perspectiveWarpTransform',
3357
3389
  vertices: f.filter.vertices.map(pointToHrznVrtc),
3358
3390
  warpedVertices: f.filter.warpedVertices.map(pointToHrznVrtc),
3359
- quads: f.filter.quads.map(indices => ({ indices })),
3391
+ quads: f.filter.quads.map(indices => ({ _name: '', _classID: 'quadIndices', indices })),
3360
3392
  },
3361
3393
  filterID: 442,
3362
3394
  };
@@ -3399,10 +3431,17 @@ function serializeFilterFXItem(f: Filter): SoLdDescriptorFilterItem {
3399
3431
  },
3400
3432
  filterID: 1114793795,
3401
3433
  };
3402
- // case 'hsb/hsl': return {
3403
- // TODO: ...
3404
- // };
3405
- default: throw new Error(`Unknow filter type: ${(f as any).type}`);
3434
+ case 'hsb/hsl': return {
3435
+ ...base,
3436
+ Fltr: {
3437
+ _name: 'HSB/HSL',
3438
+ _classID: 'HsbP',
3439
+ Inpt: ClrS.encode(f.filter.inputMode),
3440
+ Otpt: ClrS.encode(f.filter.rowOrder),
3441
+ },
3442
+ filterID: 1215521360,
3443
+ };
3444
+ default: throw new Error(`Unknown filter type: ${(f as any).type}`);
3406
3445
  }
3407
3446
  }
3408
3447
 
@@ -3531,6 +3570,9 @@ addHandler(
3531
3570
  throw new Error('Placed layer ID must be in a GUID format (example: 20953ddb-9391-11ec-b4f1-c15674f50bc4)');
3532
3571
  }
3533
3572
 
3573
+ const placedType = placedLayerTypes.indexOf(placed.type);
3574
+ if (placedType === -1) throw new Error('Invalid placedLayer type');
3575
+
3534
3576
  const desc: SoLdDescriptor = {
3535
3577
  Idnt: placed.id,
3536
3578
  placed: placed.placed ?? placed.id,
@@ -3541,7 +3583,7 @@ addHandler(
3541
3583
  duration: placed.duration || { numerator: 0, denominator: 600 },
3542
3584
  frameCount: placed.frameCount || 0,
3543
3585
  Annt: 16,
3544
- Type: placedLayerTypes.indexOf(placed.type),
3586
+ Type: placedType,
3545
3587
  Trnf: placed.transform,
3546
3588
  nonAffineTransform: placed.nonAffineTransform ?? placed.transform,
3547
3589
  // quiltWarp: {} as any,
@@ -3651,7 +3693,7 @@ addHandler(
3651
3693
  (reader, target) => {
3652
3694
  target.userMask = {
3653
3695
  colorSpace: readColor(reader),
3654
- opacity: readUint16(reader) / 0xff,
3696
+ opacity: readUint16(reader) / 100,
3655
3697
  };
3656
3698
  const flag = readUint8(reader);
3657
3699
  if (flag !== 128) throw new Error('Invalid flag value');
@@ -3660,7 +3702,7 @@ addHandler(
3660
3702
  (writer, target) => {
3661
3703
  const userMask = target.userMask!;
3662
3704
  writeColor(writer, userMask.colorSpace);
3663
- writeUint16(writer, clamp(userMask.opacity, 0, 1) * 0xff);
3705
+ writeUint16(writer, Math.round(clamp(userMask.opacity, 0, 1) * 100));
3664
3706
  writeUint8(writer, 128);
3665
3707
  writeZeros(writer, 1);
3666
3708
  },
@@ -3810,7 +3852,8 @@ addHandler(
3810
3852
  const annotations: Annotation[] = [];
3811
3853
 
3812
3854
  for (let i = 0; i < count; i++) {
3813
- /*const length =*/ readUint32(reader);
3855
+ const recordStart = reader.offset;
3856
+ const length = readUint32(reader); // includes the length field itself
3814
3857
  const type = readSignature(reader);
3815
3858
  const open = !!readUint8(reader);
3816
3859
  /*const flags =*/ readUint8(reader); // always 28
@@ -3827,10 +3870,12 @@ addHandler(
3827
3870
  let data: string | Uint8Array;
3828
3871
 
3829
3872
  if (type === 'txtA') {
3873
+ const dataStart = reader.offset;
3874
+
3830
3875
  if (dataLength >= 2 && readUint16(reader) === 0xfeff) {
3831
- data = readUnicodeStringWithLength(reader, (dataLength - 2) / 2);
3876
+ data = readUnicodeStringWithLength(reader, Math.floor((dataLength - 2) / 2));
3832
3877
  } else {
3833
- reader.offset -= 2;
3878
+ reader.offset = dataStart;
3834
3879
  data = readAsciiString(reader, dataLength);
3835
3880
  }
3836
3881
 
@@ -3844,6 +3889,8 @@ addHandler(
3844
3889
  annotations.push({
3845
3890
  type: type === 'txtA' ? 'text' : 'sound', open, iconLocation, popupLocation, color, author, name, date, data,
3846
3891
  });
3892
+
3893
+ if (length >= (reader.offset - recordStart)) reader.offset = recordStart + length;
3847
3894
  }
3848
3895
 
3849
3896
  (target as Psd).annotations = annotations;
@@ -3998,16 +4045,19 @@ function createLnkHandler(tag: string) {
3998
4045
  for (const file of psd.linkedFiles!) {
3999
4046
  if ((tag === 'lnkE') !== !!file.linkedFile) continue;
4000
4047
 
4048
+ const external = tag === 'lnkE';
4001
4049
  let version = 2;
4002
4050
  if (file.assetLockedState != null) version = 7;
4003
4051
  else if (file.assetModTime != null) version = 6;
4004
4052
  else if (file.childDocumentID != null) version = 5;
4005
- else if (tag === 'lnkE') version = 3;
4053
+ // liFE version 2 is the only one with embedded data, it has no date and its file size is the size of the data,
4054
+ // versions 5+ can't store the data, so it's not written in that case
4055
+ else if (external && !file.data) version = 4;
4006
4056
 
4007
- writeLength64(writer, 0);
4057
+ writeUint64(writer, 0);
4008
4058
 
4009
4059
  const sizeOffset = writer.offset;
4010
- writeSignature(writer, (tag === 'lnkE') ? 'liFE' : (file.data ? 'liFD' : 'liFA'));
4060
+ writeSignature(writer, external ? 'liFE' : (file.data ? 'liFD' : 'liFA'));
4011
4061
  writeInt32(writer, version);
4012
4062
  if (!file.id || typeof file.id !== 'string' || !/^[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/.test(file.id)) {
4013
4063
  throw new Error('Linked file ID must be in a GUID format (example: 20953ddb-9391-11ec-b4f1-c15674f50bc4)');
@@ -4016,7 +4066,7 @@ function createLnkHandler(tag: string) {
4016
4066
  writeUnicodeStringWithPadding(writer, file.name || '');
4017
4067
  writeSignature(writer, file.type ? `${file.type} `.substring(0, 4) : ' ');
4018
4068
  writeSignature(writer, file.creator ? `${file.creator} `.substring(0, 4) : '\0\0\0\0');
4019
- writeLength64(writer, file.data ? file.data.byteLength : 0);
4069
+ writeUint64(writer, (!external && file.data) ? file.data.byteLength : 0);
4020
4070
 
4021
4071
  if (file.descriptor && file.descriptor.compInfo) {
4022
4072
  const desc: FileOpenDescriptor = {
@@ -4032,7 +4082,7 @@ function createLnkHandler(tag: string) {
4032
4082
  writeUint8(writer, 0);
4033
4083
  }
4034
4084
 
4035
- if (tag === 'lnkE') {
4085
+ if (external) {
4036
4086
  const desc: LinkedFileDescriptor = {
4037
4087
  descVersion: 2,
4038
4088
  'Nm ': file.linkedFile?.name ?? '',
@@ -4042,7 +4092,9 @@ function createLnkHandler(tag: string) {
4042
4092
  };
4043
4093
 
4044
4094
  writeVersionAndDescriptor(writer, '', 'ExternalFileLink', desc);
4095
+ }
4045
4096
 
4097
+ if (external && version > 3) {
4046
4098
  const time = file.time ? new Date(file.time) : new Date();
4047
4099
  writeInt32(writer, time.getUTCFullYear());
4048
4100
  writeUint8(writer, time.getUTCMonth());
@@ -4052,15 +4104,18 @@ function createLnkHandler(tag: string) {
4052
4104
  writeFloat64(writer, time.getUTCSeconds() + time.getUTCMilliseconds() / 1000);
4053
4105
  }
4054
4106
 
4055
- if (file.data) {
4056
- writeBytes(writer, file.data);
4107
+ if (external) {
4108
+ writeUint64(writer, (version === 2 ? file.data?.byteLength : file.linkedFile?.fileSize) || 0); // file size
4109
+ } else if (file.data) {
4110
+ writeBytes(writer, file.data); // liFD
4057
4111
  } else {
4058
- writeLength64(writer, file.linkedFile?.fileSize || 0);
4112
+ writeZeros(writer, 8); // liFA
4059
4113
  }
4060
4114
 
4061
4115
  if (version >= 5) writeUnicodeStringWithPadding(writer, file.childDocumentID || '');
4062
4116
  if (version >= 6) writeFloat64(writer, file.assetModTime || 0);
4063
4117
  if (version >= 7) writeUint8(writer, file.assetLockedState || 0);
4118
+ if (external && version === 2 && file.data) writeBytes(writer, file.data);
4064
4119
 
4065
4120
  let size = writer.offset - sizeOffset;
4066
4121
  writer.view.setUint32(sizeOffset - 4, size, false); // write size
@@ -4565,10 +4620,15 @@ addHandler(
4565
4620
  color = readColor(reader);
4566
4621
  } else { // version 3
4567
4622
  // TODO: test this, this is probably wrong
4623
+ // values are stored as L (0..100), a, b (-128..127) multiplied by 100,
4624
+ // normalize them to the same scale as readColor() so they can be written back as version 2
4625
+ const l = readInt32(reader) / 100;
4626
+ const a = readInt32(reader) / 100;
4627
+ const b = readInt32(reader) / 100;
4568
4628
  color = {
4569
- l: readInt32(reader) / 100,
4570
- a: readInt32(reader) / 100,
4571
- b: readInt32(reader) / 100,
4629
+ l: l / 100,
4630
+ a: normalizeLabAB(a),
4631
+ b: normalizeLabAB(b),
4572
4632
  };
4573
4633
  }
4574
4634
 
@@ -4585,7 +4645,7 @@ addHandler(
4585
4645
  const info = target.adjustment as PhotoFilterAdjustment;
4586
4646
  writeUint16(writer, 2); // version
4587
4647
  writeColor(writer, info.color || { l: 0, a: 0, b: 0 });
4588
- writeUint32(writer, (info.density || 0) * 100);
4648
+ writeUint32(writer, Math.round(Math.max(0, info.density || 0) * 100));
4589
4649
  writeUint8(writer, info.preserveLuminosity ? 1 : 0);
4590
4650
  writeZeros(writer, 3);
4591
4651
  },
@@ -4844,8 +4904,9 @@ addHandler(
4844
4904
 
4845
4905
  skipBytes(reader, left());
4846
4906
 
4847
- for (const s of info.colorStops) s.location /= interpolation;
4848
- for (const s of info.opacityStops) s.location /= interpolation;
4907
+ // stop locations are always in 0..4096 range, independent of smoothness
4908
+ for (const s of info.colorStops) s.location /= 4096;
4909
+ for (const s of info.opacityStops) s.location /= 4096;
4849
4910
 
4850
4911
  target.adjustment = info;
4851
4912
  },
@@ -4862,10 +4923,10 @@ addHandler(
4862
4923
  writeUnicodeStringWithPadding(writer, info.name || '');
4863
4924
  writeUint16(writer, info.colorStops && info.colorStops.length || 0);
4864
4925
 
4865
- const interpolation = Math.round((info.smoothness ?? 1) * 4096);
4926
+ const interpolation = Math.round(clamp(info.smoothness ?? 1, 0, 1) * 4096);
4866
4927
 
4867
4928
  for (const s of info.colorStops || []) {
4868
- writeUint32(writer, Math.round(s.location * interpolation));
4929
+ writeUint32(writer, Math.round(clamp(s.location, 0, 1) * 4096));
4869
4930
  writeUint32(writer, Math.round(s.midpoint * 100));
4870
4931
  writeColor(writer, s.color);
4871
4932
  writeZeros(writer, 2);
@@ -4874,9 +4935,9 @@ addHandler(
4874
4935
  writeUint16(writer, info.opacityStops && info.opacityStops.length || 0);
4875
4936
 
4876
4937
  for (const s of info.opacityStops || []) {
4877
- writeUint32(writer, Math.round(s.location * interpolation));
4938
+ writeUint32(writer, Math.round(clamp(s.location, 0, 1) * 4096));
4878
4939
  writeUint32(writer, Math.round(s.midpoint * 100));
4879
- writeUint16(writer, Math.round(s.opacity * 0xff));
4940
+ writeUint16(writer, Math.round(clamp(s.opacity, 0, 1) * 0xff));
4880
4941
  }
4881
4942
 
4882
4943
  writeUint16(writer, 2); // expansion count
@@ -5102,7 +5163,7 @@ addHandler(
5102
5163
  target.engineData = fromByteArray(data);
5103
5164
 
5104
5165
  const layersByIndex = getTextLayersSortedByIndex(psd);
5105
- const engineData = parseEngineData(data);
5166
+ const engineData = parseEngineData(data, reader);
5106
5167
  const engineData2 = decodeEngineData2(engineData);
5107
5168
  const TextFrameSet = engineData2.ResourceDict.TextFrameSet;
5108
5169
 
@@ -5230,7 +5291,7 @@ addHandler(
5230
5291
 
5231
5292
  writer.view.setUint32(length2Offset - 4, writer.offset - length2Offset, false);
5232
5293
 
5233
- const extra = target.filterEffectsMasks![target.filterEffectsMasks!.length - 1]?.extra;
5294
+ const extra = mask.extra;
5234
5295
  if (extra) {
5235
5296
  writeUint8(writer, 1);
5236
5297
  writeInt32(writer, extra.top);
@@ -5262,12 +5323,12 @@ addHandler(
5262
5323
  (reader, target) => {
5263
5324
  target.filterMask = {
5264
5325
  colorSpace: readColor(reader),
5265
- opacity: readUint16(reader) / 0xff,
5326
+ opacity: readUint16(reader) / 100,
5266
5327
  };
5267
5328
  },
5268
5329
  (writer, target) => {
5269
5330
  writeColor(writer, target.filterMask!.colorSpace);
5270
- writeUint16(writer, clamp(target.filterMask!.opacity ?? 1, 0, 1) * 0xff);
5331
+ writeUint16(writer, Math.round(clamp(target.filterMask!.opacity ?? 1, 0, 1) * 100));
5271
5332
  },
5272
5333
  );
5273
5334
 
@@ -5439,7 +5500,7 @@ addHandler(
5439
5500
  skipBytes(reader, 3);
5440
5501
  },
5441
5502
  (writer, target) => {
5442
- writeUint8(writer, target.fillOpacity! * 0xff);
5503
+ writeUint8(writer, Math.round(clamp(target.fillOpacity!, 0, 1) * 0xff));
5443
5504
  writeZeros(writer, 3);
5444
5505
  },
5445
5506
  );
@@ -5450,7 +5511,7 @@ addHandler(
5450
5511
  (reader, target, left) => {
5451
5512
  target.channelBlendingRestrictions = [];
5452
5513
 
5453
- while (left() > 4) {
5514
+ while (left() >= 4) {
5454
5515
  target.channelBlendingRestrictions.push(readInt32(reader));
5455
5516
  }
5456
5517
  },