ag-psd 30.2.0 → 31.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 (252) hide show
  1. package/.v8-cache/v24.13.1-x64-cf738c9d/01e5e61b +0 -0
  2. package/.v8-cache/v24.13.1-x64-cf738c9d/05135617 +0 -0
  3. package/.v8-cache/v24.13.1-x64-cf738c9d/06423db9 +0 -0
  4. package/.v8-cache/v24.13.1-x64-cf738c9d/06e765df +0 -0
  5. package/.v8-cache/v24.13.1-x64-cf738c9d/0930679d +0 -0
  6. package/.v8-cache/v24.13.1-x64-cf738c9d/09519a62 +0 -0
  7. package/.v8-cache/v24.13.1-x64-cf738c9d/0a6607b0 +0 -0
  8. package/.v8-cache/v24.13.1-x64-cf738c9d/0ad8fa6e +0 -0
  9. package/.v8-cache/v24.13.1-x64-cf738c9d/0d390e10 +0 -0
  10. package/.v8-cache/v24.13.1-x64-cf738c9d/0dfa7b16 +0 -0
  11. package/.v8-cache/v24.13.1-x64-cf738c9d/0e9e09db +0 -0
  12. package/.v8-cache/v24.13.1-x64-cf738c9d/1130885f +0 -0
  13. package/.v8-cache/v24.13.1-x64-cf738c9d/1222cb8c +0 -0
  14. package/.v8-cache/v24.13.1-x64-cf738c9d/15e2c039 +0 -0
  15. package/.v8-cache/v24.13.1-x64-cf738c9d/1a2d469d +0 -0
  16. package/.v8-cache/v24.13.1-x64-cf738c9d/1b300c82 +0 -0
  17. package/.v8-cache/v24.13.1-x64-cf738c9d/1bc3d370 +0 -0
  18. package/.v8-cache/v24.13.1-x64-cf738c9d/1e44e5af +0 -0
  19. package/.v8-cache/v24.13.1-x64-cf738c9d/1efa10a1 +0 -0
  20. package/.v8-cache/v24.13.1-x64-cf738c9d/1f6c8743 +0 -0
  21. package/.v8-cache/v24.13.1-x64-cf738c9d/20b27e40 +0 -0
  22. package/.v8-cache/v24.13.1-x64-cf738c9d/257c62ba +0 -0
  23. package/.v8-cache/v24.13.1-x64-cf738c9d/25d60154 +0 -0
  24. package/.v8-cache/v24.13.1-x64-cf738c9d/26f822f3 +0 -0
  25. package/.v8-cache/v24.13.1-x64-cf738c9d/2a1e2a8d +0 -0
  26. package/.v8-cache/v24.13.1-x64-cf738c9d/2b02fded +0 -0
  27. package/.v8-cache/v24.13.1-x64-cf738c9d/2c76dc0d +0 -0
  28. package/.v8-cache/v24.13.1-x64-cf738c9d/2deb286a +0 -0
  29. package/.v8-cache/v24.13.1-x64-cf738c9d/32018e44 +0 -0
  30. package/.v8-cache/v24.13.1-x64-cf738c9d/341402c3 +0 -0
  31. package/.v8-cache/v24.13.1-x64-cf738c9d/34e0fa2e +0 -0
  32. package/.v8-cache/v24.13.1-x64-cf738c9d/3bbf643e +0 -0
  33. package/.v8-cache/v24.13.1-x64-cf738c9d/3ceff89e +0 -0
  34. package/.v8-cache/v24.13.1-x64-cf738c9d/404f5cdc +0 -0
  35. package/.v8-cache/v24.13.1-x64-cf738c9d/4087aa2b +0 -0
  36. package/.v8-cache/v24.13.1-x64-cf738c9d/4376c1f9 +0 -0
  37. package/.v8-cache/v24.13.1-x64-cf738c9d/44903df4 +0 -0
  38. package/.v8-cache/v24.13.1-x64-cf738c9d/44d58dc8 +0 -0
  39. package/.v8-cache/v24.13.1-x64-cf738c9d/4511bacf +0 -0
  40. package/.v8-cache/v24.13.1-x64-cf738c9d/47da0ce8 +0 -0
  41. package/.v8-cache/v24.13.1-x64-cf738c9d/48cd54a9 +0 -0
  42. package/.v8-cache/v24.13.1-x64-cf738c9d/4d938476 +0 -0
  43. package/.v8-cache/v24.13.1-x64-cf738c9d/4ec6d390 +0 -0
  44. package/.v8-cache/v24.13.1-x64-cf738c9d/4f5702bd +0 -0
  45. package/.v8-cache/v24.13.1-x64-cf738c9d/514cc428 +0 -0
  46. package/.v8-cache/v24.13.1-x64-cf738c9d/557d3b42 +0 -0
  47. package/.v8-cache/v24.13.1-x64-cf738c9d/56abbff7 +0 -0
  48. package/.v8-cache/v24.13.1-x64-cf738c9d/57b540ee +0 -0
  49. package/.v8-cache/v24.13.1-x64-cf738c9d/5e20c081 +0 -0
  50. package/.v8-cache/v24.13.1-x64-cf738c9d/651c4ada +0 -0
  51. package/.v8-cache/v24.13.1-x64-cf738c9d/652a0d59 +0 -0
  52. package/.v8-cache/v24.13.1-x64-cf738c9d/6a0e89ee +0 -0
  53. package/.v8-cache/v24.13.1-x64-cf738c9d/6af33b91 +0 -0
  54. package/.v8-cache/v24.13.1-x64-cf738c9d/6c2562d2 +0 -0
  55. package/.v8-cache/v24.13.1-x64-cf738c9d/6dae0cfa +0 -0
  56. package/.v8-cache/v24.13.1-x64-cf738c9d/6e2529ce +0 -0
  57. package/.v8-cache/v24.13.1-x64-cf738c9d/71df9cb3 +0 -0
  58. package/.v8-cache/v24.13.1-x64-cf738c9d/72e1d543 +0 -0
  59. package/.v8-cache/v24.13.1-x64-cf738c9d/75519c80 +0 -0
  60. package/.v8-cache/v24.13.1-x64-cf738c9d/79bf115c +0 -0
  61. package/.v8-cache/v24.13.1-x64-cf738c9d/7a39347c +0 -0
  62. package/.v8-cache/v24.13.1-x64-cf738c9d/7b83e3d3 +0 -0
  63. package/.v8-cache/v24.13.1-x64-cf738c9d/7cd71bc5 +0 -0
  64. package/.v8-cache/v24.13.1-x64-cf738c9d/7da78512 +0 -0
  65. package/.v8-cache/v24.13.1-x64-cf738c9d/7ea06cea +0 -0
  66. package/.v8-cache/v24.13.1-x64-cf738c9d/82c3b573 +0 -0
  67. package/.v8-cache/v24.13.1-x64-cf738c9d/84c186e4 +0 -0
  68. package/.v8-cache/v24.13.1-x64-cf738c9d/8607bd36 +0 -0
  69. package/.v8-cache/v24.13.1-x64-cf738c9d/87372817 +0 -0
  70. package/.v8-cache/v24.13.1-x64-cf738c9d/87cf2209 +0 -0
  71. package/.v8-cache/v24.13.1-x64-cf738c9d/882aaa05 +0 -0
  72. package/.v8-cache/v24.13.1-x64-cf738c9d/8a4d3de8 +0 -0
  73. package/.v8-cache/v24.13.1-x64-cf738c9d/8e223473 +0 -0
  74. package/.v8-cache/v24.13.1-x64-cf738c9d/92b7aefd +0 -0
  75. package/.v8-cache/v24.13.1-x64-cf738c9d/932f0770 +0 -0
  76. package/.v8-cache/v24.13.1-x64-cf738c9d/937c03a1 +0 -0
  77. package/.v8-cache/v24.13.1-x64-cf738c9d/991e4758 +0 -0
  78. package/.v8-cache/v24.13.1-x64-cf738c9d/9af658fb +0 -0
  79. package/.v8-cache/v24.13.1-x64-cf738c9d/9ed80ba5 +0 -0
  80. package/.v8-cache/v24.13.1-x64-cf738c9d/9f0dc993 +0 -0
  81. package/.v8-cache/v24.13.1-x64-cf738c9d/a19c0c4f +0 -0
  82. package/.v8-cache/v24.13.1-x64-cf738c9d/a6409d95 +0 -0
  83. package/.v8-cache/v24.13.1-x64-cf738c9d/a7e80865 +0 -0
  84. package/.v8-cache/v24.13.1-x64-cf738c9d/ac9802c6 +0 -0
  85. package/.v8-cache/v24.13.1-x64-cf738c9d/acc36e66 +0 -0
  86. package/.v8-cache/v24.13.1-x64-cf738c9d/ad11e2dc +0 -0
  87. package/.v8-cache/v24.13.1-x64-cf738c9d/b0c8fcd8 +0 -0
  88. package/.v8-cache/v24.13.1-x64-cf738c9d/b1762958 +0 -0
  89. package/.v8-cache/v24.13.1-x64-cf738c9d/b3c2fab7 +0 -0
  90. package/.v8-cache/v24.13.1-x64-cf738c9d/b5b3329b +0 -0
  91. package/.v8-cache/v24.13.1-x64-cf738c9d/b806679e +0 -0
  92. package/.v8-cache/v24.13.1-x64-cf738c9d/bc1cdd48 +0 -0
  93. package/.v8-cache/v24.13.1-x64-cf738c9d/bc7ebd1d +0 -0
  94. package/.v8-cache/v24.13.1-x64-cf738c9d/c0b789d2 +0 -0
  95. package/.v8-cache/v24.13.1-x64-cf738c9d/c314aece +0 -0
  96. package/.v8-cache/v24.13.1-x64-cf738c9d/c399a5dc +0 -0
  97. package/.v8-cache/v24.13.1-x64-cf738c9d/c681cbc8 +0 -0
  98. package/.v8-cache/v24.13.1-x64-cf738c9d/c6834ffc +0 -0
  99. package/.v8-cache/v24.13.1-x64-cf738c9d/c6f12ed5 +0 -0
  100. package/.v8-cache/v24.13.1-x64-cf738c9d/cb0f0a3d +0 -0
  101. package/.v8-cache/v24.13.1-x64-cf738c9d/cbcb7c95 +0 -0
  102. package/.v8-cache/v24.13.1-x64-cf738c9d/cdd9107c +0 -0
  103. package/.v8-cache/v24.13.1-x64-cf738c9d/cdf2c4a3 +0 -0
  104. package/.v8-cache/v24.13.1-x64-cf738c9d/cfc49f4f +0 -0
  105. package/.v8-cache/v24.13.1-x64-cf738c9d/cff9434a +0 -0
  106. package/.v8-cache/v24.13.1-x64-cf738c9d/d02dd6f7 +0 -0
  107. package/.v8-cache/v24.13.1-x64-cf738c9d/d0507bf3 +0 -0
  108. package/.v8-cache/v24.13.1-x64-cf738c9d/d60fce19 +0 -0
  109. package/.v8-cache/v24.13.1-x64-cf738c9d/d733d619 +0 -0
  110. package/.v8-cache/v24.13.1-x64-cf738c9d/d75b7803 +0 -0
  111. package/.v8-cache/v24.13.1-x64-cf738c9d/dc86f000 +0 -0
  112. package/.v8-cache/v24.13.1-x64-cf738c9d/defa4f7f +0 -0
  113. package/.v8-cache/v24.13.1-x64-cf738c9d/e03e2acd +0 -0
  114. package/.v8-cache/v24.13.1-x64-cf738c9d/e0e3f52c +0 -0
  115. package/.v8-cache/v24.13.1-x64-cf738c9d/e158d332 +0 -0
  116. package/.v8-cache/v24.13.1-x64-cf738c9d/e6735171 +0 -0
  117. package/.v8-cache/v24.13.1-x64-cf738c9d/e6745c2b +0 -0
  118. package/.v8-cache/v24.13.1-x64-cf738c9d/e6b99945 +0 -0
  119. package/.v8-cache/v24.13.1-x64-cf738c9d/e6d8ceb8 +0 -0
  120. package/.v8-cache/v24.13.1-x64-cf738c9d/e7ffec37 +0 -0
  121. package/.v8-cache/v24.13.1-x64-cf738c9d/ea33b6de +0 -0
  122. package/.v8-cache/v24.13.1-x64-cf738c9d/eaafa3c4 +0 -0
  123. package/.v8-cache/v24.13.1-x64-cf738c9d/ebb50fca +0 -0
  124. package/.v8-cache/v24.13.1-x64-cf738c9d/ec805f2e +0 -0
  125. package/.v8-cache/v24.13.1-x64-cf738c9d/edaef8f1 +0 -0
  126. package/.v8-cache/v24.13.1-x64-cf738c9d/ee4401c8 +0 -0
  127. package/.v8-cache/v24.13.1-x64-cf738c9d/eeeebdfe +0 -0
  128. package/.v8-cache/v24.13.1-x64-cf738c9d/f3d51676 +0 -0
  129. package/.v8-cache/v24.13.1-x64-cf738c9d/f7b50a75 +0 -0
  130. package/.v8-cache/v24.13.1-x64-cf738c9d/fa58ca72 +0 -0
  131. package/.v8-cache/v24.13.1-x64-cf738c9d/fc97d72d +0 -0
  132. package/.v8-cache/v24.13.1-x64-cf738c9d/fd0a2987 +0 -0
  133. package/CHANGELOG.md +6 -0
  134. package/README.md +64 -0
  135. package/TODO.md +2 -0
  136. package/dist/abr.d.ts +196 -196
  137. package/dist/abr.js +364 -365
  138. package/dist/abr.js.map +1 -1
  139. package/dist/additionalInfo.d.ts +26 -26
  140. package/dist/additionalInfo.js +3478 -3478
  141. package/dist/additionalInfo.js.map +1 -1
  142. package/dist/ase.d.ts +32 -32
  143. package/dist/ase.js +81 -82
  144. package/dist/ase.js.map +1 -1
  145. package/dist/bundle.js +12380 -12259
  146. package/dist/csh.d.ts +10 -10
  147. package/dist/csh.js +35 -36
  148. package/dist/csh.js.map +1 -1
  149. package/dist/descriptor.d.ts +601 -601
  150. package/dist/descriptor.js +2003 -2003
  151. package/dist/descriptor.js.map +1 -1
  152. package/dist/effectsHelpers.d.ts +5 -5
  153. package/dist/effectsHelpers.js +286 -287
  154. package/dist/effectsHelpers.js.map +1 -1
  155. package/dist/engineData.d.ts +2 -2
  156. package/dist/engineData.js +334 -335
  157. package/dist/engineData.js.map +1 -1
  158. package/dist/engineData2.d.ts +2 -2
  159. package/dist/engineData2.js +409 -410
  160. package/dist/engineData2.js.map +1 -1
  161. package/dist/helpers.d.ts +74 -74
  162. package/dist/helpers.js +353 -342
  163. package/dist/helpers.js.map +1 -1
  164. package/dist/imageResources.d.ts +17 -17
  165. package/dist/imageResources.js +1040 -1040
  166. package/dist/imageResources.js.map +1 -1
  167. package/dist/index.d.ts +20 -22
  168. package/dist/index.js +61 -56
  169. package/dist/index.js.map +1 -1
  170. package/dist/initializeCanvas.d.ts +1 -1
  171. package/dist/initializeCanvas.js +9 -10
  172. package/dist/initializeCanvas.js.map +1 -1
  173. package/dist/jpeg.d.ts +1 -1
  174. package/dist/jpeg.js +1020 -1021
  175. package/dist/jpeg.js.map +1 -1
  176. package/dist/psd.d.ts +1877 -1873
  177. package/dist/psd.js +45 -45
  178. package/dist/psd.js.map +1 -1
  179. package/dist/psdReader.d.ts +52 -45
  180. package/dist/psdReader.js +1385 -1282
  181. package/dist/psdReader.js.map +1 -1
  182. package/dist/psdWriter.d.ts +34 -34
  183. package/dist/psdWriter.js +834 -824
  184. package/dist/psdWriter.js.map +1 -1
  185. package/dist/text.d.ts +179 -179
  186. package/dist/text.js +552 -553
  187. package/dist/text.js.map +1 -1
  188. package/dist/utf8.d.ts +4 -6
  189. package/dist/utf8.js +156 -157
  190. package/dist/utf8.js.map +1 -1
  191. package/dist-es/abr.d.ts +196 -196
  192. package/dist-es/abr.js +364 -361
  193. package/dist-es/abr.js.map +1 -1
  194. package/dist-es/additionalInfo.d.ts +26 -26
  195. package/dist-es/additionalInfo.js +3478 -3472
  196. package/dist-es/additionalInfo.js.map +1 -1
  197. package/dist-es/ase.d.ts +32 -32
  198. package/dist-es/ase.js +81 -78
  199. package/dist-es/ase.js.map +1 -1
  200. package/dist-es/csh.d.ts +10 -10
  201. package/dist-es/csh.js +35 -32
  202. package/dist-es/csh.js.map +1 -1
  203. package/dist-es/descriptor.d.ts +601 -601
  204. package/dist-es/descriptor.js +2003 -1970
  205. package/dist-es/descriptor.js.map +1 -1
  206. package/dist-es/effectsHelpers.d.ts +5 -5
  207. package/dist-es/effectsHelpers.js +286 -282
  208. package/dist-es/effectsHelpers.js.map +1 -1
  209. package/dist-es/engineData.d.ts +2 -2
  210. package/dist-es/engineData.js +334 -330
  211. package/dist-es/engineData.js.map +1 -1
  212. package/dist-es/engineData2.d.ts +2 -2
  213. package/dist-es/engineData2.js +409 -406
  214. package/dist-es/engineData2.js.map +1 -1
  215. package/dist-es/helpers.d.ts +74 -74
  216. package/dist-es/helpers.js +353 -324
  217. package/dist-es/helpers.js.map +1 -1
  218. package/dist-es/imageResources.d.ts +17 -17
  219. package/dist-es/imageResources.js +1040 -1037
  220. package/dist-es/imageResources.js.map +1 -1
  221. package/dist-es/index.d.ts +20 -22
  222. package/dist-es/index.js +61 -33
  223. package/dist-es/index.js.map +1 -1
  224. package/dist-es/initializeCanvas.d.ts +1 -1
  225. package/dist-es/initializeCanvas.js +9 -6
  226. package/dist-es/initializeCanvas.js.map +1 -1
  227. package/dist-es/jpeg.d.ts +1 -1
  228. package/dist-es/jpeg.js +1020 -1017
  229. package/dist-es/jpeg.js.map +1 -1
  230. package/dist-es/psd.d.ts +1877 -1873
  231. package/dist-es/psd.js +45 -42
  232. package/dist-es/psd.js.map +1 -1
  233. package/dist-es/psdReader.d.ts +52 -45
  234. package/dist-es/psdReader.js +1385 -1244
  235. package/dist-es/psdReader.js.map +1 -1
  236. package/dist-es/psdWriter.d.ts +34 -34
  237. package/dist-es/psdWriter.js +834 -794
  238. package/dist-es/psdWriter.js.map +1 -1
  239. package/dist-es/text.d.ts +179 -179
  240. package/dist-es/text.js +552 -548
  241. package/dist-es/text.js.map +1 -1
  242. package/dist-es/utf8.d.ts +4 -6
  243. package/dist-es/utf8.js +156 -150
  244. package/dist-es/utf8.js.map +1 -1
  245. package/package.json +4 -3
  246. package/src/helpers.ts +13 -3
  247. package/src/index.ts +4 -6
  248. package/src/psd.ts +4 -0
  249. package/src/psdReader.ts +136 -43
  250. package/src/psdWriter.ts +42 -23
  251. package/tsconfig-es6.json +2 -1
  252. package/tsconfig.json +1 -0
package/src/psdReader.ts CHANGED
@@ -234,6 +234,7 @@ export function readPsd(reader: PsdReader, readOptions: ReadOptions = {}) {
234
234
  Object.assign(reader, readOptions);
235
235
  reader.large = version === 2;
236
236
  reader.globalAlpha = false;
237
+ if (!reader.totalMemoryLimit) reader.totalMemoryLimit = 2 * 1024 * 1024 * 1024; // default 2GB memory limit
237
238
 
238
239
  // color mode data
239
240
  readSection(reader, 1, left => {
@@ -327,7 +328,16 @@ export function readPsd(reader: PsdReader, readOptions: ReadOptions = {}) {
327
328
  const skipComposite = reader.skipCompositeImageData && (reader.skipLayerImageData || hasChildren);
328
329
 
329
330
  if (!skipComposite) {
330
- readImageData(reader, psd);
331
+ if (reader.useRawData) {
332
+ psd.rawCompositeData = new Uint8Array(reader.view.buffer, reader.view.byteOffset + reader.offset);
333
+ } else {
334
+ const imageData = readImageData(reader, psd);
335
+ if (reader.useImageData) {
336
+ psd.imageData = imageData;
337
+ } else {
338
+ psd.canvas = imageDataToCanvas(imageData);
339
+ }
340
+ }
331
341
  }
332
342
 
333
343
  // TODO: show converted color mode instead of original PSD file color mode
@@ -556,7 +566,7 @@ function readLayerChannelImageData(reader: PsdReader, psd: Psd, layer: Layer, ch
556
566
  }
557
567
 
558
568
  if (!reader.useRawData) {
559
- decodeLayerImageData(layer, !!reader.useImageData, !!reader.throwForMissingFeatures);
569
+ decodeLayerImageData(layer, reader);
560
570
  }
561
571
  }
562
572
 
@@ -571,8 +581,91 @@ function resetAlpha({ data }: PixelData, cmyk: boolean) {
571
581
  }
572
582
  }
573
583
 
574
- export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throwForMissingFeatures?: boolean) {
575
- if (!layer.rawData) return;
584
+ export function getCompositeImageData(psd: Psd) {
585
+ const data = psd.rawCompositeData;
586
+ if (!data) return undefined;
587
+
588
+ const reader = createReader(data.buffer, data.byteOffset, data.byteLength);
589
+ const imageData = readImageData(reader, psd);
590
+ return imageData;
591
+ }
592
+
593
+ export function getCompositeCanvas(psd: Psd) {
594
+ return imageDataToCanvasSafe(getCompositeImageData(psd));
595
+ }
596
+
597
+ export function getLayerImageData(layer: Layer) {
598
+ return getDataFromLayer(layer, LayerDataType.Layer, false, undefined);
599
+ }
600
+
601
+ export function getLayerMaskImageData(layer: Layer) {
602
+ return getDataFromLayer(layer, LayerDataType.Mask, false, undefined);
603
+ }
604
+
605
+ export function getLayerRealMaskImageData(layer: Layer) {
606
+ return getDataFromLayer(layer, LayerDataType.RealMask, false, undefined);
607
+ }
608
+
609
+ export function getLayerCanvas(layer: Layer) {
610
+ return imageDataToCanvasSafe(getLayerImageData(layer));
611
+ }
612
+
613
+ export function getLayerMaskCanvas(layer: Layer) {
614
+ return imageDataToCanvasSafe(getLayerMaskImageData(layer));
615
+ }
616
+
617
+ export function getLayerRealMaskCanvas(layer: Layer) {
618
+ return imageDataToCanvasSafe(getLayerRealMaskImageData(layer));
619
+ }
620
+
621
+ function imageDataToCanvasSafe(imageData: PixelData | undefined) {
622
+ return imageData && imageDataToCanvas(imageData);
623
+ }
624
+
625
+ function setImageDataOrCanvas(obj: Layer | LayerMaskData, imageData: PixelData | undefined, useImageData: boolean | undefined) {
626
+ if (!imageData) return;
627
+
628
+ if (useImageData) {
629
+ obj.imageData = imageData;
630
+ } else {
631
+ obj.canvas = imageDataToCanvas(imageData);
632
+ }
633
+ }
634
+
635
+ export function decodeLayerPixels(layer: Layer, useImageData?: boolean) {
636
+ decodeLayerImageData(layer, { useImageData });
637
+ }
638
+
639
+ function decodeLayerImageData(layer: Layer, options: { useImageData?: boolean, throwForMissingFeatures?: boolean, memoryLimit?: number }) {
640
+ let { throwForMissingFeatures, useImageData } = options;
641
+
642
+ const imageData = getDataFromLayer(layer, LayerDataType.Layer, throwForMissingFeatures, options.memoryLimit);
643
+ setImageDataOrCanvas(layer, imageData, useImageData);
644
+ if (options.memoryLimit !== undefined) options.memoryLimit -= imageData?.data.byteLength ?? 0;
645
+
646
+ if (layer.mask) {
647
+ const maskData = getDataFromLayer(layer, LayerDataType.Mask, throwForMissingFeatures, options.memoryLimit);
648
+ setImageDataOrCanvas(layer.mask, maskData, useImageData);
649
+ if (options.memoryLimit !== undefined) options.memoryLimit -= maskData?.data.byteLength ?? 0;
650
+ }
651
+
652
+ if (layer.realMask) {
653
+ const maskData = getDataFromLayer(layer, LayerDataType.RealMask, throwForMissingFeatures, options.memoryLimit);
654
+ setImageDataOrCanvas(layer.realMask, maskData, useImageData);
655
+ if (options.memoryLimit !== undefined) options.memoryLimit -= maskData?.data.byteLength ?? 0;
656
+ }
657
+
658
+ delete layer.rawData;
659
+ }
660
+
661
+ enum LayerDataType {
662
+ Layer,
663
+ Mask,
664
+ RealMask,
665
+ }
666
+
667
+ function getDataFromLayer(layer: Layer, read: LayerDataType, throwForMissingFeatures?: boolean, memoryLimit?: number) {
668
+ if (!layer.rawData) return undefined;
576
669
 
577
670
  const { colorMode, bitsPerChannel, channels, large } = layer.rawData;
578
671
  const layerWidth = (layer.right || 0) - (layer.left || 0);
@@ -580,14 +673,15 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
580
673
  const cmyk = colorMode === ColorMode.CMYK;
581
674
 
582
675
  let imageData: PixelData | undefined;
676
+ let maskData: PixelData | undefined;
583
677
  let initializedAlpha = false;
584
678
 
585
- if (layerWidth && layerHeight) {
679
+ if (layerWidth && layerHeight && read === LayerDataType.Layer) {
586
680
  if (cmyk) {
587
681
  if (bitsPerChannel !== 8) throw new Error('bitsPerChannel Not supproted');
588
682
  imageData = { width: layerWidth, height: layerHeight, data: new Uint8ClampedArray(layerWidth * layerHeight * 5) } as any as ImageData;
589
683
  } else {
590
- imageData = createImageDataBitDepth(layerWidth, layerHeight, bitsPerChannel);
684
+ imageData = createImageDataBitDepth(layerWidth, layerHeight, bitsPerChannel, 4, memoryLimit);
591
685
  }
592
686
  }
593
687
 
@@ -602,6 +696,9 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
602
696
  const dataReader = createReader(data.buffer, data.byteOffset, data.byteLength);
603
697
 
604
698
  if (id === ChannelID.UserMask || id === ChannelID.RealUserMask) {
699
+ if (id === ChannelID.UserMask && read !== LayerDataType.Mask) continue;
700
+ if (id === ChannelID.RealUserMask && read !== LayerDataType.RealMask) continue;
701
+
605
702
  const mask = id === ChannelID.UserMask ? layer.mask : layer.realMask;
606
703
  if (!mask) throw new Error(`Missing layer ${id === ChannelID.UserMask ? 'mask' : 'real mask'} data`);
607
704
 
@@ -610,10 +707,8 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
610
707
  if (maskWidth < 0 || maskHeight < 0 || maskWidth > 30000 || maskHeight > 30000) throw new Error('Invalid mask size');
611
708
 
612
709
  if (maskWidth && maskHeight) {
613
- const maskData = createImageDataBitDepth(maskWidth, maskHeight, bitsPerChannel);
614
-
710
+ maskData = createImageDataBitDepth(maskWidth, maskHeight, bitsPerChannel, 4, memoryLimit);
615
711
  readData(dataReader, data.byteLength, maskData, compression, maskWidth, maskHeight, bitsPerChannel, 0, large, 4);
616
-
617
712
  if (RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
618
713
  if (id === ChannelID.UserMask) {
619
714
  (layer as any).maskDataRawCompression = compression;
@@ -623,17 +718,12 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
623
718
  (layer as any).realMaskDataRaw = data;
624
719
  }
625
720
  }
626
-
627
721
  setupGrayscale(maskData);
628
722
  resetAlpha(maskData, false);
629
-
630
- if (useImageData) {
631
- mask.imageData = maskData;
632
- } else {
633
- mask.canvas = imageDataToCanvas(maskData);
634
- }
635
723
  }
636
724
  } else {
725
+ if (read !== LayerDataType.Layer) continue;
726
+
637
727
  const offset = offsetForChannel(id, cmyk);
638
728
  let targetData = imageData;
639
729
 
@@ -670,15 +760,9 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
670
760
  imageData = createImageData(cmykData.width, cmykData.height);
671
761
  cmykToRgb(cmykData, imageData, false);
672
762
  }
673
-
674
- if (useImageData) {
675
- layer.imageData = imageData;
676
- } else {
677
- layer.canvas = imageDataToCanvas(imageData);
678
- }
679
763
  }
680
764
 
681
- delete layer.rawData;
765
+ return read === LayerDataType.Layer ? imageData : maskData;
682
766
  }
683
767
 
684
768
  function readData(reader: PsdReader, length: number, pixels: PixelData | undefined, compression: Compression, width: number, height: number, bitDepth: number, offset: number, large: boolean, step: number) {
@@ -774,7 +858,10 @@ export function readAdditionalLayerInfo(reader: PsdReader, target: LayerAddition
774
858
  }, false, u64);
775
859
  }
776
860
 
777
- export function createImageDataBitDepth(width: number, height: number, bitDepth: number, channels = 4): PixelData {
861
+ function createImageDataBitDepth(width: number, height: number, bitDepth: number, channels: number, memoryLimit: number | undefined): PixelData {
862
+ const sizeInBytes = width * height * channels * Math.max(1, bitDepth / 8);
863
+ if (memoryLimit !== undefined && sizeInBytes > memoryLimit) throw new Error('Exceeded memory limit');
864
+
778
865
  if (bitDepth === 1 || bitDepth === 8) {
779
866
  if (channels === 4) {
780
867
  return createImageData(width, height);
@@ -800,7 +887,8 @@ function readImageData(reader: PsdReader, psd: Psd) {
800
887
  if (compression !== Compression.RawData && compression !== Compression.RleCompressed)
801
888
  throw new Error(`Compression type not supported: ${compression}`);
802
889
 
803
- const imageData = createImageDataBitDepth(psd.width, psd.height, bitsPerChannel);
890
+ const imageData = createImageDataBitDepth(psd.width, psd.height, bitsPerChannel, 4, reader.totalMemoryLimit);
891
+ if (reader.totalMemoryLimit !== undefined) reader.totalMemoryLimit -= imageData.data.byteLength;
804
892
  resetImageData(imageData);
805
893
 
806
894
  switch (psd.colorMode) {
@@ -815,7 +903,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
815
903
  bytes = new Uint8Array(psd.width * psd.height);
816
904
  readDataRLE(reader, { data: bytes, width: psd.width, height: psd.height }, psd.width, psd.height, 8, 1, [0], reader.large);
817
905
  } else {
818
- throw new Error(`Bitmap compression not supported: ${compression}`);
906
+ throw new Error(`Compression not supported: ${compression}`);
819
907
  }
820
908
 
821
909
  decodeBitmap(bytes, imageData.data, psd.width, psd.height);
@@ -843,6 +931,8 @@ function readImageData(reader: PsdReader, psd: Psd) {
843
931
  const start = reader.offset;
844
932
  readDataRLE(reader, imageData, psd.width, psd.height, bitsPerChannel, 4, channels, reader.large);
845
933
  if (RAW_IMAGE_DATA) (psd as any).imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
934
+ } else {
935
+ throw new Error(`Compression not supported: ${compression}`);
846
936
  }
847
937
 
848
938
  if (psd.colorMode === ColorMode.Grayscale) {
@@ -856,7 +946,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
856
946
  if (!psd.palette) throw new Error('Missing color palette');
857
947
 
858
948
  if (compression === Compression.RawData) {
859
- throw new Error(`Not implemented`);
949
+ throw new Error(`Compression not supported: ${compression}`);
860
950
  } else if (compression === Compression.RleCompressed) {
861
951
  const indexedImageData: PixelData = {
862
952
  width: imageData.width,
@@ -866,7 +956,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
866
956
  readDataRLE(reader, indexedImageData, psd.width, psd.height, bitsPerChannel, 1, [0], reader.large);
867
957
  indexedToRgb(indexedImageData, imageData, psd.palette);
868
958
  } else {
869
- throw new Error(`Not implemented`);
959
+ throw new Error(`Compression not supported: ${compression}`);
870
960
  }
871
961
 
872
962
  break;
@@ -879,7 +969,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
879
969
  if (reader.globalAlpha) channels.push(4);
880
970
 
881
971
  if (compression === Compression.RawData) {
882
- throw new Error(`Not implemented`);
972
+ throw new Error(`Compression not supported: ${compression}`);
883
973
  // TODO: ...
884
974
  // for (let i = 0; i < channels.length; i++) {
885
975
  // readDataRaw(reader, imageData, channels[i], psd.width, psd.height);
@@ -897,7 +987,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
897
987
 
898
988
  if (RAW_IMAGE_DATA) (psd as any).imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
899
989
  } else {
900
- throw new Error(`Not implemented`);
990
+ throw new Error(`Compression not supported: ${compression}`);
901
991
  }
902
992
 
903
993
  break;
@@ -923,11 +1013,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
923
1013
  }
924
1014
  }
925
1015
 
926
- if (reader.useImageData) {
927
- psd.imageData = imageData;
928
- } else {
929
- psd.canvas = imageDataToCanvas(imageData);
930
- }
1016
+ return imageData;
931
1017
  }
932
1018
 
933
1019
  function cmykToRgb(cmyk: PixelData, rgb: PixelData, reverseAlpha: boolean) {
@@ -1310,9 +1396,7 @@ export function readPattern(reader: PsdReader): PatternInfo {
1310
1396
  data[dst + ch] = cdata[src];
1311
1397
  }
1312
1398
  }
1313
- }
1314
-
1315
- if (colorMode === ColorMode.Grayscale && ch < 1) {
1399
+ } else if (colorMode === ColorMode.Grayscale && ch < 1) {
1316
1400
  for (let y = 0; y < h; y++) {
1317
1401
  for (let x = 0; x < w; x++) {
1318
1402
  const src = x + y * w;
@@ -1323,11 +1407,20 @@ export function readPattern(reader: PsdReader): PatternInfo {
1323
1407
  data[dst + 2] = value;
1324
1408
  }
1325
1409
  }
1326
- }
1327
-
1328
- if (colorMode === ColorMode.Indexed) {
1329
- // TODO:
1330
- throw new Error('Indexed pattern color mode not implemented');
1410
+ } else if (colorMode === ColorMode.Indexed) {
1411
+ for (let y = 0; y < h; y++) {
1412
+ for (let x = 0; x < w; x++) {
1413
+ const src = x + y * w;
1414
+ const dst = (ox + x + (y + oy) * width) * 4;
1415
+ const index = cdata[src];
1416
+ const color = palette[index];
1417
+ data[dst + 0] = color.r;
1418
+ data[dst + 1] = color.g;
1419
+ data[dst + 2] = color.b;
1420
+ }
1421
+ }
1422
+ } else {
1423
+ if (reader.throwForMissingFeatures) throw new Error('Invalid color pattern');
1331
1424
  }
1332
1425
  } else if (compressionMode === 1) {
1333
1426
  const pixelData: PixelData = { data, width, height };
package/src/psdWriter.ts CHANGED
@@ -348,7 +348,7 @@ function writeLayerInfo(writer: PsdWriter, layers: Layer[], psd: Psd, globalAlph
348
348
  writeUint16(writer, channels.length);
349
349
 
350
350
  for (const c of channels) {
351
- writeInt16(writer, c.channelId);
351
+ writeInt16(writer, c.id);
352
352
  if (options.psb) writeUint32(writer, 0);
353
353
  writeUint32(writer, c.length);
354
354
  }
@@ -381,8 +381,8 @@ function writeLayerInfo(writer: PsdWriter, layers: Layer[], psd: Psd, globalAlph
381
381
  for (const channel of layerData.channels) {
382
382
  writeUint16(writer, channel.compression);
383
383
 
384
- if (channel.buffer) {
385
- writeBytes(writer, channel.buffer);
384
+ if (channel.data) {
385
+ writeBytes(writer, channel.data);
386
386
  }
387
387
  }
388
388
  }
@@ -635,12 +635,31 @@ function getMaskChannels(tempBuffer: Uint8Array, layerData: LayerChannelData, la
635
635
  compression = Compression.RleCompressed;
636
636
  }
637
637
 
638
- layerData.channels.push({ channelId: realMask ? ChannelID.RealUserMask : ChannelID.UserMask, compression, buffer, length: 2 + buffer.length });
638
+ layerData.channels.push({ id: realMask ? ChannelID.RealUserMask : ChannelID.UserMask, compression, data: buffer, length: 2 + buffer.length });
639
639
 
640
640
  layerData[realMask ? 'realMask' : 'mask'] = { top, left, right, bottom };
641
641
  }
642
642
 
643
+ function bounds(obj: { top?: number; left?: number; bottom?: number; right?: number; } | undefined) {
644
+ return obj ? {
645
+ top: obj.top || 0,
646
+ left: obj.left || 0,
647
+ right: obj.right || 0,
648
+ bottom: obj.bottom || 0,
649
+ } : undefined;
650
+ }
651
+
643
652
  function getChannels(tempBuffer: Uint8Array, layer: Layer, background: boolean, options: WriteOptions): LayerChannelData {
653
+ if (layer.rawData) {
654
+ return {
655
+ layer,
656
+ channels: layer.rawData.channels.map(c => ({ ...c, length: 2 + (c.data?.byteLength ?? 0) })),
657
+ ...bounds(layer)!,
658
+ mask: bounds(layer.mask),
659
+ realMask: bounds(layer.realMask),
660
+ };
661
+ }
662
+
644
663
  const layerData = getLayerChannels(tempBuffer, layer, background, options);
645
664
  if (layer.mask) getMaskChannels(tempBuffer, layerData, layer, layer.mask, options, false);
646
665
  if (layer.realMask) getMaskChannels(tempBuffer, layerData, layer, layer.realMask, options, true);
@@ -683,10 +702,10 @@ function getLayerChannels(tempBuffer: Uint8Array, layer: Layer, background: bool
683
702
  let right = (layer.right as any) | 0;
684
703
  let bottom = (layer.bottom as any) | 0;
685
704
  let channels: ChannelData[] = [
686
- { channelId: ChannelID.Transparency, compression: Compression.RawData, buffer: undefined, length: 2 },
687
- { channelId: ChannelID.Color0, compression: Compression.RawData, buffer: undefined, length: 2 },
688
- { channelId: ChannelID.Color1, compression: Compression.RawData, buffer: undefined, length: 2 },
689
- { channelId: ChannelID.Color2, compression: Compression.RawData, buffer: undefined, length: 2 },
705
+ { id: ChannelID.Transparency, compression: Compression.RawData, data: undefined, length: 2 },
706
+ { id: ChannelID.Color0, compression: Compression.RawData, data: undefined, length: 2 },
707
+ { id: ChannelID.Color1, compression: Compression.RawData, data: undefined, length: 2 },
708
+ { id: ChannelID.Color2, compression: Compression.RawData, data: undefined, length: 2 },
690
709
  ];
691
710
  let { width, height } = getLayerDimentions(layer);
692
711
 
@@ -699,22 +718,22 @@ function getLayerChannels(tempBuffer: Uint8Array, layer: Layer, background: bool
699
718
  right = left + width;
700
719
  bottom = top + height;
701
720
 
702
- let data = layer.imageData || layer.canvas!.getContext('2d')!.getImageData(0, 0, width, height);
721
+ let imageData = layer.imageData || layer.canvas!.getContext('2d')!.getImageData(0, 0, width, height);
703
722
 
704
723
  if (options.trimImageData) {
705
- const trimmed = trimData(data);
724
+ const trimmed = trimData(imageData);
706
725
 
707
- if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== data.width || trimmed.bottom !== data.height) {
726
+ if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== imageData.width || trimmed.bottom !== imageData.height) {
708
727
  left += trimmed.left;
709
728
  top += trimmed.top;
710
- right -= (data.width - trimmed.right);
711
- bottom -= (data.height - trimmed.bottom);
729
+ right -= (imageData.width - trimmed.right);
730
+ bottom -= (imageData.height - trimmed.bottom);
712
731
  width = right - left;
713
732
  height = bottom - top;
714
733
 
715
734
  if (!width || !height) return { layer, top, left, right, bottom, channels };
716
735
 
717
- data = cropImageData(data, trimmed.left, trimmed.top, width, height);
736
+ imageData = cropImageData(imageData, trimmed.left, trimmed.top, width, height);
718
737
  }
719
738
  }
720
739
 
@@ -724,28 +743,28 @@ function getLayerChannels(tempBuffer: Uint8Array, layer: Layer, background: bool
724
743
  ChannelID.Color2,
725
744
  ];
726
745
 
727
- if (!background || options.noBackground || layer.mask || hasAlpha(data) || (RAW_IMAGE_DATA && (layer as any).imageDataRaw?.['-1'])) {
746
+ if (!background || options.noBackground || layer.mask || hasAlpha(imageData) || (RAW_IMAGE_DATA && (layer as any).imageDataRaw?.['-1'])) {
728
747
  channelIds.unshift(ChannelID.Transparency);
729
748
  }
730
749
 
731
- channels = channelIds.map(channelId => {
732
- const offset = offsetForChannel(channelId, false); // TODO: psd.colorMode === ColorMode.CMYK);
733
- let buffer: Uint8Array;
750
+ channels = channelIds.map(id => {
751
+ const offset = offsetForChannel(id, false); // TODO: psd.colorMode === ColorMode.CMYK);
752
+ let data: Uint8Array;
734
753
  let compression: Compression;
735
754
 
736
755
  if (RAW_IMAGE_DATA && (layer as any).imageDataRaw) {
737
756
  // console.log('written raw layer image data');
738
- buffer = (layer as any).imageDataRaw[channelId];
739
- compression = (layer as any).imageDataRawCompression[channelId];
757
+ data = (layer as any).imageDataRaw[id];
758
+ compression = (layer as any).imageDataRawCompression[id];
740
759
  } else if (options.compress) {
741
- buffer = writeDataZipWithoutPrediction(data, [offset]);
760
+ data = writeDataZipWithoutPrediction(imageData, [offset]);
742
761
  compression = Compression.ZipWithoutPrediction;
743
762
  } else {
744
- buffer = writeDataRLE(tempBuffer, data, [offset], !!options.psb)!;
763
+ data = writeDataRLE(tempBuffer, imageData, [offset], !!options.psb)!;
745
764
  compression = Compression.RleCompressed;
746
765
  }
747
766
 
748
- return { channelId, compression, buffer, length: 2 + buffer.length };
767
+ return { id, compression, data, length: 2 + data.length };
749
768
  });
750
769
 
751
770
  return { layer, top, left, right, bottom, channels };
package/tsconfig-es6.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "extends": "./tsconfig.json",
3
3
  "compilerOptions": {
4
- "module": "es6",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
5
6
  "outDir": "dist-es"
6
7
  }
7
8
  }
package/tsconfig.json CHANGED
@@ -9,6 +9,7 @@
9
9
  "preserveConstEnums": true,
10
10
  "declaration": true,
11
11
  "useUnknownInCatchVariables": false,
12
+ "types": ["node", "mocha"],
12
13
  "strict": true,
13
14
  "sourceMap": true,
14
15
  "sourceRoot": "../src",