ag-psd 30.2.0 → 31.0.1

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 +9 -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
@@ -1,1245 +1,1386 @@
1
- var __rest = (this && this.__rest) || function (s, e) {
2
- var t = {};
3
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
- t[p] = s[p];
5
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
- t[p[i]] = s[p[i]];
9
- }
10
- return t;
11
- };
12
- import { inflate as inflateSync } from 'pako';
13
- import { resetImageData, offsetForChannel, decodeBitmap, createImageData, toBlendMode, RAW_IMAGE_DATA, largeAdditionalInfoKeys, imageDataToCanvas } from './helpers';
14
- import { infoHandlersMap } from './additionalInfo';
15
- import { resourceHandlersMap } from './imageResources';
16
- export const supportedColorModes = [0 /* ColorMode.Bitmap */, 1 /* ColorMode.Grayscale */, 3 /* ColorMode.RGB */, 2 /* ColorMode.Indexed */];
17
- const colorModes = ['bitmap', 'grayscale', 'indexed', 'RGB', 'CMYK', 'multichannel', 'duotone', 'lab'];
18
- function setupGrayscale(data) {
19
- const size = data.width * data.height * 4;
20
- for (let i = 0; i < size; i += 4) {
21
- const c = data.data[i];
22
- data.data[i + 1] = c;
23
- data.data[i + 2] = c;
24
- }
25
- }
26
- export function createReader(buffer, offset, length) {
27
- const view = new DataView(buffer, offset, length);
28
- return { view, offset: 0, strict: false, debug: false, large: false, globalAlpha: false, log: console.log };
29
- }
30
- export function warnOrThrow(reader, message) {
31
- if (reader.strict)
32
- throw new Error(message);
33
- if (reader.debug)
34
- reader.log(message);
35
- }
36
- export function readUint8(reader) {
37
- reader.offset += 1;
38
- return reader.view.getUint8(reader.offset - 1);
39
- }
40
- export function peekUint8(reader) {
41
- return reader.view.getUint8(reader.offset);
42
- }
43
- export function readInt16(reader) {
44
- reader.offset += 2;
45
- return reader.view.getInt16(reader.offset - 2, false);
46
- }
47
- export function readUint16(reader) {
48
- reader.offset += 2;
49
- return reader.view.getUint16(reader.offset - 2, false);
50
- }
51
- export function readUint16LE(reader) {
52
- reader.offset += 2;
53
- return reader.view.getUint16(reader.offset - 2, true);
54
- }
55
- export function readInt32(reader) {
56
- reader.offset += 4;
57
- return reader.view.getInt32(reader.offset - 4, false);
58
- }
59
- export function readInt32LE(reader) {
60
- reader.offset += 4;
61
- return reader.view.getInt32(reader.offset - 4, true);
62
- }
63
- export function readUint32(reader) {
64
- reader.offset += 4;
65
- return reader.view.getUint32(reader.offset - 4, false);
66
- }
67
- export function readFloat32(reader) {
68
- reader.offset += 4;
69
- return reader.view.getFloat32(reader.offset - 4, false);
70
- }
71
- export function readFloat64(reader) {
72
- reader.offset += 8;
73
- return reader.view.getFloat64(reader.offset - 8, false);
74
- }
75
- // 32-bit fixed-point number 16.16
76
- export function readFixedPoint32(reader) {
77
- return readInt32(reader) / (1 << 16);
78
- }
79
- // 32-bit fixed-point number 8.24
80
- export function readFixedPointPath32(reader) {
81
- return readInt32(reader) / (1 << 24);
82
- }
83
- export function readBytes(reader, length) {
84
- const start = reader.view.byteOffset + reader.offset;
85
- reader.offset += length;
86
- if ((start + length) > reader.view.buffer.byteLength) {
87
- // fix for broken PSD files that are missing part of file at the end
88
- warnOrThrow(reader, 'Reading bytes exceeding buffer length');
89
- if (length > (100 * 1024 * 1024))
90
- throw new Error('Reading past end of file'); // limit to 100MB
91
- const result = new Uint8Array(length);
92
- const len = Math.min(length, reader.view.byteLength - start);
93
- if (len > 0)
94
- result.set(new Uint8Array(reader.view.buffer, start, len));
95
- return result;
96
- }
97
- else {
98
- return new Uint8Array(reader.view.buffer, start, length);
99
- }
100
- }
101
- export function readSignature(reader) {
102
- return readShortString(reader, 4);
103
- }
104
- export function validSignatureAt(reader, offset) {
105
- const sig = String.fromCharCode(reader.view.getUint8(offset))
106
- + String.fromCharCode(reader.view.getUint8(offset + 1))
107
- + String.fromCharCode(reader.view.getUint8(offset + 2))
108
- + String.fromCharCode(reader.view.getUint8(offset + 3));
109
- return sig == '8BIM' || sig == '8B64';
110
- }
111
- export function readPascalString(reader, padTo) {
112
- let length = readUint8(reader);
113
- const text = length ? readShortString(reader, length) : '';
114
- while (++length % padTo) { // starts with length + 1 so we count the size byte too
115
- reader.offset++;
116
- }
117
- return text;
118
- }
119
- export function readUnicodeString(reader) {
120
- const length = readUint32(reader);
121
- return readUnicodeStringWithLength(reader, length);
122
- }
123
- export function readUnicodeStringWithLength(reader, length) {
124
- let text = '';
125
- while (length--) {
126
- const value = readUint16(reader);
127
- if (value || length > 0) { // remove trailing \0
128
- text += String.fromCharCode(value);
129
- }
130
- }
131
- return text;
132
- }
133
- export function readUnicodeStringWithLengthLE(reader, length) {
134
- let text = '';
135
- while (length--) {
136
- const value = readUint16LE(reader);
137
- if (value || length > 0) { // remove trailing \0
138
- text += String.fromCharCode(value);
139
- }
140
- }
141
- return text;
142
- }
143
- export function readAsciiString(reader, length) {
144
- let text = '';
145
- while (length--) {
146
- text += String.fromCharCode(readUint8(reader));
147
- }
148
- return text;
149
- }
150
- export function skipBytes(reader, count) {
151
- reader.offset += count;
152
- }
153
- export function checkSignature(reader, a, b) {
154
- const offset = reader.offset;
155
- const signature = readSignature(reader);
156
- if (signature !== a && signature !== b) {
157
- throw new Error(`Invalid signature: '${signature}' at 0x${offset.toString(16)}`);
158
- }
159
- }
160
- function readShortString(reader, length) {
161
- const buffer = readBytes(reader, length);
162
- let result = '';
163
- for (let i = 0; i < buffer.length; i++) {
164
- result += String.fromCharCode(buffer[i]);
165
- }
166
- return result;
167
- }
168
- function isValidSignature(sig) {
169
- return sig === '8BIM' || sig === 'MeSa' || sig === 'AgHg' || sig === 'PHUT' || sig === 'DCSR';
170
- }
171
- export function readPsd(reader, readOptions = {}) {
172
- var _a;
173
- // header
174
- checkSignature(reader, '8BPS');
175
- const version = readUint16(reader);
176
- if (version !== 1 && version !== 2)
177
- throw new Error(`Invalid PSD file version: ${version}`);
178
- skipBytes(reader, 6);
179
- const channels = readUint16(reader);
180
- const height = readUint32(reader);
181
- const width = readUint32(reader);
182
- const bitsPerChannel = readUint16(reader);
183
- const colorMode = readUint16(reader);
184
- const maxSize = version === 1 ? 30000 : 300000;
185
- if (width > maxSize || height > maxSize)
186
- throw new Error(`Invalid size: ${width}x${height}`);
187
- if (channels > 16)
188
- throw new Error(`Invalid channel count: ${channels}`);
189
- if (![1, 8, 16, 32].includes(bitsPerChannel))
190
- throw new Error(`Invalid bitsPerChannel: ${bitsPerChannel}`);
191
- if (supportedColorModes.indexOf(colorMode) === -1)
192
- throw new Error(`Color mode not supported: ${(_a = colorModes[colorMode]) !== null && _a !== void 0 ? _a : colorMode}`);
193
- const psd = { width, height, channels, bitsPerChannel, colorMode };
194
- Object.assign(reader, readOptions);
195
- reader.large = version === 2;
196
- reader.globalAlpha = false;
197
- // color mode data
198
- readSection(reader, 1, left => {
199
- if (!left())
200
- return;
201
- if (colorMode === 2 /* ColorMode.Indexed */) {
202
- // should have 256 colors here saved as 8bit channels RGB
203
- if (left() != 768)
204
- throw new Error('Invalid color palette size');
205
- psd.palette = [];
206
- for (let i = 0; i < 256; i++)
207
- psd.palette.push({ r: readUint8(reader), g: 0, b: 0 });
208
- for (let i = 0; i < 256; i++)
209
- psd.palette[i].g = readUint8(reader);
210
- for (let i = 0; i < 256; i++)
211
- psd.palette[i].b = readUint8(reader);
212
- }
213
- else {
214
- // TODO: unknown format for duotone, also seems to have some data here for 32bit colors
215
- // if (options.throwForMissingFeatures) throw new Error('Color mode data not supported');
216
- }
217
- skipBytes(reader, left());
218
- });
219
- // image resources
220
- const imageResources = {};
221
- readSection(reader, 1, left => {
222
- while (left() > 0) {
223
- realignWithSignature(reader, isValidSignature);
224
- const id = readUint16(reader);
225
- readPascalString(reader, 2); // name
226
- readSection(reader, 2, left => {
227
- const handler = resourceHandlersMap[id];
228
- const skip = id === 1036 && !!reader.skipThumbnail;
229
- if (handler && !skip) {
230
- try {
231
- handler.read(reader, imageResources, left);
232
- }
233
- catch (e) {
234
- if (reader.throwForMissingFeatures)
235
- throw e;
236
- skipBytes(reader, left());
237
- }
238
- }
239
- else {
240
- // options.logMissingFeatures && console.log(`Unhandled image resource: ${id} (${left()})`);
241
- skipBytes(reader, left());
242
- }
243
- });
244
- }
245
- });
246
- const { layersGroup, layerGroupsEnabledId } = imageResources, rest = __rest(imageResources, ["layersGroup", "layerGroupsEnabledId"]);
247
- if (Object.keys(rest)) {
248
- psd.imageResources = rest;
249
- }
250
- // layer and mask info
251
- readSection(reader, 1, left => {
252
- readSection(reader, 2, left => {
253
- readLayerInfo(reader, psd, imageResources);
254
- skipBytes(reader, left());
255
- }, undefined, reader.large);
256
- // SAI does not include this section
257
- if (left() > 0) {
258
- const globalLayerMaskInfo = readGlobalLayerMaskInfo(reader);
259
- if (globalLayerMaskInfo)
260
- psd.globalLayerMaskInfo = globalLayerMaskInfo;
261
- }
262
- else {
263
- // revert back to end of section if exceeded section limits
264
- // opt.logMissingFeatures && console.log('reverting to end of section');
265
- skipBytes(reader, left());
266
- }
267
- while (left() > 0) {
268
- // sometimes there are empty bytes here
269
- while (left() && peekUint8(reader) === 0) {
270
- // opt.logMissingFeatures && console.log('skipping 0 byte');
271
- skipBytes(reader, 1);
272
- }
273
- if (left() >= 12) {
274
- readAdditionalLayerInfo(reader, psd, psd, imageResources);
275
- }
276
- else {
277
- // opt.logMissingFeatures && console.log('skipping leftover bytes', left());
278
- skipBytes(reader, left());
279
- }
280
- }
281
- }, undefined, reader.large);
282
- const hasChildren = psd.children && psd.children.length;
283
- const skipComposite = reader.skipCompositeImageData && (reader.skipLayerImageData || hasChildren);
284
- if (!skipComposite) {
285
- readImageData(reader, psd);
286
- }
287
- // TODO: show converted color mode instead of original PSD file color mode
288
- // but add option to preserve file color mode (need to return image data instead of canvas in that case)
289
- // psd.colorMode = ColorMode.RGB; // we convert all color modes to RGB
290
- return psd;
291
- }
292
- export function readLayerInfo(reader, psd, imageResources) {
293
- var _a, _b;
294
- const { layersGroup = [], layerGroupsEnabledId = [] } = imageResources;
295
- let layerCount = readInt16(reader);
296
- if (layerCount < 0) {
297
- reader.globalAlpha = true;
298
- layerCount = -layerCount;
299
- }
300
- const layers = [];
301
- const layerChannels = [];
302
- for (let i = 0; i < layerCount; i++) {
303
- const { layer, channels } = readLayerRecord(reader, psd, imageResources);
304
- if (layersGroup[i] !== undefined)
305
- layer.linkGroup = layersGroup[i];
306
- if (layerGroupsEnabledId[i] !== undefined)
307
- layer.linkGroupEnabled = !!layerGroupsEnabledId[i];
308
- layers.push(layer);
309
- layerChannels.push(channels);
310
- }
311
- for (let i = 0; i < layerCount; i++) {
312
- readLayerChannelImageData(reader, psd, layers[i], layerChannels[i]);
313
- }
314
- if (!psd.children)
315
- psd.children = [];
316
- const stack = [psd];
317
- for (let i = layers.length - 1; i >= 0; i--) {
318
- const l = layers[i];
319
- const type = l.sectionDivider ? l.sectionDivider.type : 0 /* SectionDividerType.Other */;
320
- if (type === 1 /* SectionDividerType.OpenFolder */ || type === 2 /* SectionDividerType.ClosedFolder */) {
321
- l.opened = type === 1 /* SectionDividerType.OpenFolder */;
322
- l.children = [];
323
- if ((_a = l.sectionDivider) === null || _a === void 0 ? void 0 : _a.key) {
324
- l.blendMode = (_b = toBlendMode[l.sectionDivider.key]) !== null && _b !== void 0 ? _b : l.blendMode;
325
- }
326
- stack[stack.length - 1].children.unshift(l);
327
- stack.push(l);
328
- }
329
- else if (type === 3 /* SectionDividerType.BoundingSectionDivider */) {
330
- stack.pop();
331
- // this was workaround because I didn't know what `lsdk` section was, now it's probably not needed anymore
332
- // } else if (l.name === '</Layer group>' && !l.sectionDivider && !l.top && !l.left && !l.bottom && !l.right) {
333
- // // sometimes layer group terminator doesn't have sectionDivider, so we just guess here (PS bug ?)
334
- // stack.pop();
335
- }
336
- else {
337
- stack[stack.length - 1].children.unshift(l);
338
- }
339
- }
340
- }
341
- function readLayerRecord(reader, psd, imageResources) {
342
- const layer = {};
343
- layer.top = readInt32(reader);
344
- layer.left = readInt32(reader);
345
- layer.bottom = readInt32(reader);
346
- layer.right = readInt32(reader);
347
- const channelCount = readUint16(reader);
348
- const channels = [];
349
- for (let i = 0; i < channelCount; i++) {
350
- let id = readInt16(reader);
351
- let length = readUint32(reader);
352
- if (reader.large) {
353
- if (length !== 0)
354
- throw new Error('Sizes larger than 4GB are not supported');
355
- length = readUint32(reader);
356
- }
357
- channels.push({ id, length });
358
- }
359
- checkSignature(reader, '8BIM');
360
- const blendMode = readSignature(reader);
361
- if (!toBlendMode[blendMode])
362
- throw new Error(`Invalid blend mode: '${blendMode}'`);
363
- layer.blendMode = toBlendMode[blendMode];
364
- layer.opacity = readUint8(reader) / 0xff;
365
- layer.clipping = readUint8(reader) === 1;
366
- const flags = readUint8(reader);
367
- layer.transparencyProtected = (flags & 0x01) !== 0;
368
- layer.hidden = (flags & 0x02) !== 0;
369
- if (flags & 0x20)
370
- layer.effectsOpen = true;
371
- // 0x04 - obsolete
372
- // 0x08 - 1 for Photoshop 5.0 and later, tells if bit 4 has useful information
373
- // 0x10 - pixel data irrelevant to appearance of document
374
- // 0x20 - effects/filters panel is expanded
375
- skipBytes(reader, 1);
376
- readSection(reader, 1, left => {
377
- readLayerMaskData(reader, layer);
378
- const blendingRanges = readLayerBlendingRanges(reader);
379
- if (blendingRanges)
380
- layer.blendingRanges = blendingRanges;
381
- layer.name = readPascalString(reader, 1); // should be padded to 4, but is not sometimes
382
- // HACK: fix for sometimes layer.name string not being padded correctly, just skip until we get valid signature
383
- while (left() > 4 && !validSignatureAt(reader, reader.offset))
384
- reader.offset++;
385
- while (left() >= 12)
386
- readAdditionalLayerInfo(reader, layer, psd, imageResources);
387
- skipBytes(reader, left());
388
- });
389
- return { layer, channels };
390
- }
391
- function readLayerMaskData(reader, layer) {
392
- return readSection(reader, 1, left => {
393
- if (!left())
394
- return undefined;
395
- const mask = {};
396
- layer.mask = mask;
397
- mask.top = readInt32(reader);
398
- mask.left = readInt32(reader);
399
- mask.bottom = readInt32(reader);
400
- mask.right = readInt32(reader);
401
- mask.defaultColor = readUint8(reader);
402
- const flags = readUint8(reader);
403
- mask.positionRelativeToLayer = (flags & 1 /* LayerMaskFlags.PositionRelativeToLayer */) !== 0;
404
- mask.disabled = (flags & 2 /* LayerMaskFlags.LayerMaskDisabled */) !== 0;
405
- mask.fromVectorData = (flags & 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */) !== 0;
406
- if (left() >= 18) {
407
- const realMask = {};
408
- layer.realMask = realMask;
409
- const realFlags = readUint8(reader);
410
- realMask.positionRelativeToLayer = (realFlags & 1 /* LayerMaskFlags.PositionRelativeToLayer */) !== 0;
411
- realMask.disabled = (realFlags & 2 /* LayerMaskFlags.LayerMaskDisabled */) !== 0;
412
- realMask.fromVectorData = (realFlags & 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */) !== 0;
413
- realMask.defaultColor = readUint8(reader); // Real user mask background. 0 or 255.
414
- realMask.top = readInt32(reader);
415
- realMask.left = readInt32(reader);
416
- realMask.bottom = readInt32(reader);
417
- realMask.right = readInt32(reader);
418
- }
419
- if (flags & 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */) {
420
- const params = readUint8(reader);
421
- if (params & 1 /* MaskParams.UserMaskDensity */)
422
- mask.userMaskDensity = readUint8(reader) / 0xff;
423
- if (params & 2 /* MaskParams.UserMaskFeather */)
424
- mask.userMaskFeather = readFloat64(reader);
425
- if (params & 4 /* MaskParams.VectorMaskDensity */)
426
- mask.vectorMaskDensity = readUint8(reader) / 0xff;
427
- if (params & 8 /* MaskParams.VectorMaskFeather */)
428
- mask.vectorMaskFeather = readFloat64(reader);
429
- }
430
- skipBytes(reader, left());
431
- });
432
- }
433
- function readBlendingRange(reader) {
434
- return [readUint8(reader), readUint8(reader), readUint8(reader), readUint8(reader)];
435
- }
436
- function readLayerBlendingRanges(reader) {
437
- return readSection(reader, 1, left => {
438
- const compositeGrayBlendSource = readBlendingRange(reader);
439
- const compositeGraphBlendDestinationRange = readBlendingRange(reader);
440
- const ranges = [];
441
- while (left() > 0) {
442
- const sourceRange = readBlendingRange(reader);
443
- const destRange = readBlendingRange(reader);
444
- ranges.push({ sourceRange, destRange });
445
- }
446
- return { compositeGrayBlendSource, compositeGraphBlendDestinationRange, ranges };
447
- });
448
- }
449
- function readLayerChannelImageData(reader, psd, layer, channels) {
450
- if (reader.skipLayerImageData)
451
- return;
452
- const { colorMode = 3 /* ColorMode.RGB */, bitsPerChannel = 8 } = psd;
453
- layer.rawData = { colorMode, bitsPerChannel, channels: [], large: reader.large };
454
- for (const channel of channels) {
455
- const start = reader.offset;
456
- let compression = 0 /* Compression.RawData */;
457
- let data = undefined;
458
- if (channel.length === 1)
459
- throw new Error('Invalid channel length');
460
- if (channel.length) {
461
- compression = readUint16(reader);
462
- // try to fix broken files where there's 1 byte shift of channel
463
- if (compression > 3) {
464
- reader.offset -= 1;
465
- compression = readUint16(reader);
466
- }
467
- // try to fix broken files where there's 1 byte shift of channel
468
- if (compression > 3) {
469
- reader.offset -= 3;
470
- compression = readUint16(reader);
471
- }
472
- if (compression > 3)
473
- throw new Error(`Invalid compression: ${compression}`);
474
- if (channel.length > 2) {
475
- data = readBytes(reader, channel.length - 2);
476
- }
477
- }
478
- reader.offset = start + channel.length;
479
- layer.rawData.channels.push({ id: channel.id, compression, data });
480
- }
481
- if (!reader.useRawData) {
482
- decodeLayerImageData(layer, !!reader.useImageData, !!reader.throwForMissingFeatures);
483
- }
484
- }
485
- function resetAlpha({ data }, cmyk) {
486
- const alpha = (data instanceof Float32Array) ? 1.0 : ((data instanceof Uint16Array) ? 0xffff : 0xff);
487
- const offset = (cmyk ? 4 : 3) | 0;
488
- const length = data.length | 0;
489
- const step = (cmyk ? 5 : 4) | 0;
490
- for (let p = offset; p < length; p = (p + step) | 0) {
491
- data[p] = alpha;
492
- }
493
- }
494
- export function decodeLayerImageData(layer, useImageData, throwForMissingFeatures) {
495
- if (!layer.rawData)
496
- return;
497
- const { colorMode, bitsPerChannel, channels, large } = layer.rawData;
498
- const layerWidth = (layer.right || 0) - (layer.left || 0);
499
- const layerHeight = (layer.bottom || 0) - (layer.top || 0);
500
- const cmyk = colorMode === 4 /* ColorMode.CMYK */;
501
- let imageData;
502
- let initializedAlpha = false;
503
- if (layerWidth && layerHeight) {
504
- if (cmyk) {
505
- if (bitsPerChannel !== 8)
506
- throw new Error('bitsPerChannel Not supproted');
507
- imageData = { width: layerWidth, height: layerHeight, data: new Uint8ClampedArray(layerWidth * layerHeight * 5) };
508
- }
509
- else {
510
- imageData = createImageDataBitDepth(layerWidth, layerHeight, bitsPerChannel);
511
- }
512
- }
513
- if (RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
514
- layer.imageDataRaw = [];
515
- layer.imageDataRawCompression = [];
516
- }
517
- for (const { id, compression, data } of channels) {
518
- if (!data)
519
- continue;
520
- const dataReader = createReader(data.buffer, data.byteOffset, data.byteLength);
521
- if (id === -2 /* ChannelID.UserMask */ || id === -3 /* ChannelID.RealUserMask */) {
522
- const mask = id === -2 /* ChannelID.UserMask */ ? layer.mask : layer.realMask;
523
- if (!mask)
524
- throw new Error(`Missing layer ${id === -2 /* ChannelID.UserMask */ ? 'mask' : 'real mask'} data`);
525
- const maskWidth = (mask.right || 0) - (mask.left || 0);
526
- const maskHeight = (mask.bottom || 0) - (mask.top || 0);
527
- if (maskWidth < 0 || maskHeight < 0 || maskWidth > 30000 || maskHeight > 30000)
528
- throw new Error('Invalid mask size');
529
- if (maskWidth && maskHeight) {
530
- const maskData = createImageDataBitDepth(maskWidth, maskHeight, bitsPerChannel);
531
- readData(dataReader, data.byteLength, maskData, compression, maskWidth, maskHeight, bitsPerChannel, 0, large, 4);
532
- if (RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
533
- if (id === -2 /* ChannelID.UserMask */) {
534
- layer.maskDataRawCompression = compression;
535
- layer.maskDataRaw = data;
536
- }
537
- else {
538
- layer.realMaskDataRawCompression = compression;
539
- layer.realMaskDataRaw = data;
540
- }
541
- }
542
- setupGrayscale(maskData);
543
- resetAlpha(maskData, false);
544
- if (useImageData) {
545
- mask.imageData = maskData;
546
- }
547
- else {
548
- mask.canvas = imageDataToCanvas(maskData);
549
- }
550
- }
551
- }
552
- else {
553
- const offset = offsetForChannel(id, cmyk);
554
- let targetData = imageData;
555
- if (offset < 0) {
556
- targetData = undefined;
557
- if (throwForMissingFeatures) {
558
- throw new Error(`Channel not supported: ${id}`);
559
- }
560
- }
561
- readData(dataReader, data.byteLength, targetData, compression, layerWidth, layerHeight, bitsPerChannel, offset, large, cmyk ? 5 : 4);
562
- if (RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
563
- layer.imageDataRawCompression[id] = compression;
564
- layer.imageDataRaw[id] = data;
565
- }
566
- if (targetData && colorMode === 1 /* ColorMode.Grayscale */) {
567
- setupGrayscale(targetData);
568
- }
569
- }
570
- if (id === -1 /* ChannelID.Transparency */) {
571
- initializedAlpha = true;
572
- }
573
- }
574
- if (imageData) {
575
- if (!initializedAlpha)
576
- resetAlpha(imageData, cmyk);
577
- if (cmyk) {
578
- const cmykData = imageData;
579
- imageData = createImageData(cmykData.width, cmykData.height);
580
- cmykToRgb(cmykData, imageData, false);
581
- }
582
- if (useImageData) {
583
- layer.imageData = imageData;
584
- }
585
- else {
586
- layer.canvas = imageDataToCanvas(imageData);
587
- }
588
- }
589
- delete layer.rawData;
590
- }
591
- function readData(reader, length, pixels, compression, width, height, bitDepth, offset, large, step) {
592
- if (!length)
593
- return;
594
- if (compression === 0 /* Compression.RawData */) {
595
- if (length !== (width * height * Math.floor(bitDepth / 8))) {
596
- reader.log(`Invalid length (${length}, ${width * height * Math.floor(bitDepth / 8)})`);
597
- }
598
- const data = readBytes(reader, length);
599
- readDataRaw(data, pixels, bitDepth, step, offset);
600
- }
601
- else if (compression === 1 /* Compression.RleCompressed */) {
602
- // const reader = createReader(data.buffer, data.byteOffset, data.byteLength);
603
- readDataRLE(reader, pixels, width, height, bitDepth, step, [offset], large);
604
- }
605
- else if (compression === 2 /* Compression.ZipWithoutPrediction */) {
606
- const data = readBytes(reader, length);
607
- readDataZip(data, pixels, width, height, bitDepth, step, offset, false);
608
- }
609
- else if (compression === 3 /* Compression.ZipWithPrediction */) {
610
- const data = readBytes(reader, length);
611
- readDataZip(data, pixels, width, height, bitDepth, step, offset, true);
612
- }
613
- else {
614
- throw new Error(`Invalid Compression type: ${compression}`);
615
- }
616
- }
617
- export function readGlobalLayerMaskInfo(reader) {
618
- return readSection(reader, 1, left => {
619
- if (!left())
620
- return undefined;
621
- const overlayColorSpace = readUint16(reader);
622
- const colorSpace1 = readUint16(reader);
623
- const colorSpace2 = readUint16(reader);
624
- const colorSpace3 = readUint16(reader);
625
- const colorSpace4 = readUint16(reader);
626
- const opacity = readUint16(reader) / 0xff;
627
- const kind = readUint8(reader);
628
- skipBytes(reader, left()); // 3 bytes of padding ?
629
- return { overlayColorSpace, colorSpace1, colorSpace2, colorSpace3, colorSpace4, opacity, kind };
630
- });
631
- }
632
- const fixOffsets = [0, 1, -1, 2, -2, 3, -3, 4, -4];
633
- function realignWithSignature(reader, isValid) {
634
- const sigOffset = reader.offset;
635
- let sig = '';
636
- // attempt to fix broken document by realigning with the signature
637
- for (const offset of fixOffsets) {
638
- try {
639
- reader.offset = sigOffset + offset;
640
- sig = readSignature(reader);
641
- }
642
- catch (_a) { }
643
- if (isValid(sig))
644
- break;
645
- }
646
- if (!isValid(sig)) {
647
- throw new Error(`Invalid signature: '${sig}' at 0x${(sigOffset).toString(16)}`);
648
- }
649
- return sig;
650
- }
651
- function isValidAdditionalInfoSignature(sig) {
652
- return sig === '8BIM' || sig === '8B64';
653
- }
654
- export function readAdditionalLayerInfo(reader, target, psd, imageResources) {
655
- const sig = realignWithSignature(reader, isValidAdditionalInfoSignature);
656
- const key = readSignature(reader);
657
- // `largeAdditionalInfoKeys` fallback, because some keys don't have 8B64 signature even when they are 64bit
658
- const u64 = sig === '8B64' || (reader.large && largeAdditionalInfoKeys.indexOf(key) !== -1);
659
- readSection(reader, 2, left => {
660
- const handler = infoHandlersMap[key];
661
- if (handler) {
662
- try {
663
- handler.read(reader, target, left, psd, imageResources);
664
- }
665
- catch (e) {
666
- if (reader.throwForMissingFeatures)
667
- throw e;
668
- }
669
- }
670
- else {
671
- reader.logMissingFeatures && reader.log(`Unhandled additional info: ${key}`);
672
- skipBytes(reader, left());
673
- }
674
- if (left()) {
675
- reader.logMissingFeatures && reader.log(`Unread ${left()} bytes left for additional info: ${key}`);
676
- skipBytes(reader, left());
677
- }
678
- }, false, u64);
679
- }
680
- export function createImageDataBitDepth(width, height, bitDepth, channels = 4) {
681
- if (bitDepth === 1 || bitDepth === 8) {
682
- if (channels === 4) {
683
- return createImageData(width, height);
684
- }
685
- else {
686
- return { width, height, data: new Uint8ClampedArray(width * height * channels) };
687
- }
688
- }
689
- else if (bitDepth === 16) {
690
- return { width, height, data: new Uint16Array(width * height * channels) };
691
- }
692
- else if (bitDepth === 32) {
693
- return { width, height, data: new Float32Array(width * height * channels) };
694
- }
695
- else {
696
- throw new Error(`Invalid bitDepth (${bitDepth})`);
697
- }
698
- }
699
- function readImageData(reader, psd) {
700
- var _a;
701
- const compression = readUint16(reader);
702
- const bitsPerChannel = (_a = psd.bitsPerChannel) !== null && _a !== void 0 ? _a : 8;
703
- if (supportedColorModes.indexOf(psd.colorMode) === -1)
704
- throw new Error(`Color mode not supported: ${psd.colorMode}`);
705
- if (compression !== 0 /* Compression.RawData */ && compression !== 1 /* Compression.RleCompressed */)
706
- throw new Error(`Compression type not supported: ${compression}`);
707
- const imageData = createImageDataBitDepth(psd.width, psd.height, bitsPerChannel);
708
- resetImageData(imageData);
709
- switch (psd.colorMode) {
710
- case 0 /* ColorMode.Bitmap */: {
711
- if (bitsPerChannel !== 1)
712
- throw new Error('Invalid bitsPerChannel for bitmap color mode');
713
- let bytes;
714
- if (compression === 0 /* Compression.RawData */) {
715
- bytes = readBytes(reader, Math.ceil(psd.width / 8) * psd.height);
716
- }
717
- else if (compression === 1 /* Compression.RleCompressed */) {
718
- bytes = new Uint8Array(psd.width * psd.height);
719
- readDataRLE(reader, { data: bytes, width: psd.width, height: psd.height }, psd.width, psd.height, 8, 1, [0], reader.large);
720
- }
721
- else {
722
- throw new Error(`Bitmap compression not supported: ${compression}`);
723
- }
724
- decodeBitmap(bytes, imageData.data, psd.width, psd.height);
725
- break;
726
- }
727
- case 3 /* ColorMode.RGB */:
728
- case 1 /* ColorMode.Grayscale */: {
729
- const channels = psd.colorMode === 1 /* ColorMode.Grayscale */ ? [0] : [0, 1, 2];
730
- if (psd.channels && psd.channels > 3) {
731
- for (let i = 3; i < psd.channels; i++) {
732
- // TODO: store these channels in additional image data
733
- channels.push(i);
734
- }
735
- }
736
- else if (reader.globalAlpha) {
737
- channels.push(3);
738
- }
739
- if (compression === 0 /* Compression.RawData */) {
740
- for (let i = 0; i < channels.length; i++) {
741
- const data = readBytes(reader, psd.width * psd.height * Math.floor(bitsPerChannel / 8));
742
- readDataRaw(data, imageData, bitsPerChannel, 4, channels[i]);
743
- }
744
- }
745
- else if (compression === 1 /* Compression.RleCompressed */) {
746
- const start = reader.offset;
747
- readDataRLE(reader, imageData, psd.width, psd.height, bitsPerChannel, 4, channels, reader.large);
748
- if (RAW_IMAGE_DATA)
749
- psd.imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
750
- }
751
- if (psd.colorMode === 1 /* ColorMode.Grayscale */) {
752
- setupGrayscale(imageData);
753
- }
754
- break;
755
- }
756
- case 2 /* ColorMode.Indexed */: {
757
- if (bitsPerChannel !== 8)
758
- throw new Error('bitsPerChannel Not supproted');
759
- if (psd.channels !== 1)
760
- throw new Error('Invalid channel count');
761
- if (!psd.palette)
762
- throw new Error('Missing color palette');
763
- if (compression === 0 /* Compression.RawData */) {
764
- throw new Error(`Not implemented`);
765
- }
766
- else if (compression === 1 /* Compression.RleCompressed */) {
767
- const indexedImageData = {
768
- width: imageData.width,
769
- height: imageData.height,
770
- data: new Uint8Array(imageData.width * imageData.height),
771
- };
772
- readDataRLE(reader, indexedImageData, psd.width, psd.height, bitsPerChannel, 1, [0], reader.large);
773
- indexedToRgb(indexedImageData, imageData, psd.palette);
774
- }
775
- else {
776
- throw new Error(`Not implemented`);
777
- }
778
- break;
779
- }
780
- case 4 /* ColorMode.CMYK */: {
781
- if (bitsPerChannel !== 8)
782
- throw new Error('bitsPerChannel Not supproted');
783
- if (psd.channels !== 4)
784
- throw new Error(`Invalid channel count`);
785
- const channels = [0, 1, 2, 3];
786
- if (reader.globalAlpha)
787
- channels.push(4);
788
- if (compression === 0 /* Compression.RawData */) {
789
- throw new Error(`Not implemented`);
790
- // TODO: ...
791
- // for (let i = 0; i < channels.length; i++) {
792
- // readDataRaw(reader, imageData, channels[i], psd.width, psd.height);
793
- // }
794
- }
795
- else if (compression === 1 /* Compression.RleCompressed */) {
796
- const cmykImageData = {
797
- width: imageData.width,
798
- height: imageData.height,
799
- data: new Uint8Array(imageData.width * imageData.height * 5),
800
- };
801
- const start = reader.offset;
802
- readDataRLE(reader, cmykImageData, psd.width, psd.height, bitsPerChannel, 5, channels, reader.large);
803
- cmykToRgb(cmykImageData, imageData, true);
804
- if (RAW_IMAGE_DATA)
805
- psd.imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
806
- }
807
- else {
808
- throw new Error(`Not implemented`);
809
- }
810
- break;
811
- }
812
- default: throw new Error(`Color mode not supported: ${psd.colorMode}`);
813
- }
814
- // remove weird white matte
815
- if (reader.globalAlpha) {
816
- if (psd.bitsPerChannel !== 8)
817
- throw new Error('bitsPerChannel Not supproted');
818
- const p = imageData.data;
819
- const size = imageData.width * imageData.height * 4;
820
- for (let i = 0; i < size; i += 4) {
821
- const pa = p[i + 3];
822
- if (pa != 0 && pa != 255) {
823
- const a = pa / 255;
824
- const ra = 1 / a;
825
- const invA = 255 * (1 - ra);
826
- p[i + 0] = p[i + 0] * ra + invA;
827
- p[i + 1] = p[i + 1] * ra + invA;
828
- p[i + 2] = p[i + 2] * ra + invA;
829
- }
830
- }
831
- }
832
- if (reader.useImageData) {
833
- psd.imageData = imageData;
834
- }
835
- else {
836
- psd.canvas = imageDataToCanvas(imageData);
837
- }
838
- }
839
- function cmykToRgb(cmyk, rgb, reverseAlpha) {
840
- const size = rgb.width * rgb.height * 4;
841
- const srcData = cmyk.data;
842
- const dstData = rgb.data;
843
- for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
844
- const c = srcData[src];
845
- const m = srcData[src + 1];
846
- const y = srcData[src + 2];
847
- const k = srcData[src + 3];
848
- dstData[dst] = ((((c * k) | 0) / 255) | 0);
849
- dstData[dst + 1] = ((((m * k) | 0) / 255) | 0);
850
- dstData[dst + 2] = ((((y * k) | 0) / 255) | 0);
851
- dstData[dst + 3] = reverseAlpha ? 255 - srcData[src + 4] : srcData[src + 4];
852
- }
853
- // for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
854
- // const c = 1 - (srcData[src + 0] / 255);
855
- // const m = 1 - (srcData[src + 1] / 255);
856
- // const y = 1 - (srcData[src + 2] / 255);
857
- // // const k = srcData[src + 3] / 255;
858
- // dstData[dst + 0] = ((1 - c * 0.8) * 255) | 0;
859
- // dstData[dst + 1] = ((1 - m * 0.8) * 255) | 0;
860
- // dstData[dst + 2] = ((1 - y * 0.8) * 255) | 0;
861
- // dstData[dst + 3] = reverseAlpha ? 255 - srcData[src + 4] : srcData[src + 4];
862
- // }
863
- }
864
- function indexedToRgb(indexed, rgb, palette) {
865
- const size = indexed.width * indexed.height;
866
- const srcData = indexed.data;
867
- const dstData = rgb.data;
868
- for (let src = 0, dst = 0; src < size; src++, dst += 4) {
869
- const c = palette[srcData[src]];
870
- dstData[dst + 0] = c.r;
871
- dstData[dst + 1] = c.g;
872
- dstData[dst + 2] = c.b;
873
- dstData[dst + 3] = 255;
874
- }
875
- }
876
- function verifyCompatible(a, b) {
877
- if ((a.byteLength / a.length) !== (b.byteLength / b.length)) {
878
- throw new Error('Invalid array types');
879
- }
880
- }
881
- function bytesToArray(bytes, bitDepth) {
882
- if (bitDepth === 8) {
883
- return bytes;
884
- }
885
- else if (bitDepth === 16) {
886
- // PSD files store 16-bit channel data in big-endian byte order.
887
- // Swap each pair of bytes so that Uint16Array (native-endian) reads the correct values.
888
- for (let i = 0; i < bytes.byteLength; i += 2) {
889
- const tmp = bytes[i];
890
- bytes[i] = bytes[i + 1];
891
- bytes[i + 1] = tmp;
892
- }
893
- if (bytes.byteOffset % 2) {
894
- const result = new Uint16Array(bytes.byteLength / 2);
895
- new Uint8Array(result.buffer, result.byteOffset, result.byteLength).set(bytes);
896
- return result;
897
- }
898
- else {
899
- return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2);
900
- }
901
- }
902
- else if (bitDepth === 32) {
903
- if (bytes.byteOffset % 4) {
904
- const result = new Float32Array(bytes.byteLength / 4);
905
- new Uint8Array(result.buffer, result.byteOffset, result.byteLength).set(bytes);
906
- return result;
907
- }
908
- else {
909
- return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
910
- }
911
- }
912
- else {
913
- throw new Error(`Invalid bitDepth (${bitDepth})`);
914
- }
915
- }
916
- function copyChannelToPixelData(pixelData, channel, offset, step) {
917
- verifyCompatible(pixelData.data, channel);
918
- const size = pixelData.width * pixelData.height;
919
- const data = pixelData.data;
920
- for (let i = 0, p = offset | 0; i < size; i++, p = (p + step) | 0) {
921
- data[p] = channel[i];
922
- }
923
- }
924
- function readDataRaw(buffer, pixelData, bitDepth, step, offset) {
925
- if (bitDepth == 32) {
926
- for (let i = 0; i < buffer.byteLength; i += 4) {
927
- const a = buffer[i + 0];
928
- const b = buffer[i + 1];
929
- const c = buffer[i + 2];
930
- const d = buffer[i + 3];
931
- buffer[i + 0] = d;
932
- buffer[i + 1] = c;
933
- buffer[i + 2] = b;
934
- buffer[i + 3] = a;
935
- }
936
- }
937
- const array = bytesToArray(buffer, bitDepth);
938
- if (pixelData && offset < step) {
939
- copyChannelToPixelData(pixelData, array, offset, step);
940
- }
941
- }
942
- function decodePredicted(data, width, height, mod) {
943
- for (let y = 0; y < height; y++) {
944
- const offset = y * width;
945
- for (let x = 1, o = offset + 1; x < width; x++, o++) {
946
- data[o] = (data[o - 1] + data[o]) % mod;
947
- }
948
- }
949
- }
950
- export function readDataZip(compressed, pixelData, width, height, bitDepth, step, offset, prediction) {
951
- const decompressed = inflateSync(compressed);
952
- if (pixelData && offset < step) {
953
- const array = bytesToArray(decompressed, bitDepth);
954
- if (bitDepth === 8) {
955
- if (prediction)
956
- decodePredicted(decompressed, width, height, 0x100);
957
- copyChannelToPixelData(pixelData, decompressed, offset, step);
958
- }
959
- else if (bitDepth === 16) {
960
- if (prediction)
961
- decodePredicted(array, width, height, 0x10000);
962
- copyChannelToPixelData(pixelData, array, offset, step);
963
- }
964
- else if (bitDepth === 32) {
965
- if (prediction)
966
- decodePredicted(decompressed, width * 4, height, 0x100);
967
- let di = offset;
968
- const dst = new Uint32Array(pixelData.data.buffer, pixelData.data.byteOffset, pixelData.data.length);
969
- for (let y = 0; y < height; y++) {
970
- let a = width * 4 * y;
971
- for (let x = 0; x < width; x++, a++, di += step) {
972
- const b = a + width;
973
- const c = b + width;
974
- const d = c + width;
975
- dst[di] = ((decompressed[a] << 24) | (decompressed[b] << 16) | (decompressed[c] << 8) | decompressed[d]) >>> 0;
976
- }
977
- }
978
- }
979
- else {
980
- throw new Error('Invalid bitDepth');
981
- }
982
- }
983
- }
984
- export function readDataRLE(reader, pixelData, width, height, _bitDepth, step, offsets, large) {
985
- const data = pixelData && pixelData.data;
986
- let lengths;
987
- if (large) {
988
- lengths = new Uint32Array(offsets.length * height);
989
- for (let o = 0, li = 0; o < offsets.length; o++) {
990
- for (let y = 0; y < height; y++, li++) {
991
- lengths[li] = readUint32(reader);
992
- }
993
- }
994
- }
995
- else {
996
- lengths = new Uint16Array(offsets.length * height);
997
- for (let o = 0, li = 0; o < offsets.length; o++) {
998
- for (let y = 0; y < height; y++, li++) {
999
- lengths[li] = readUint16(reader);
1000
- }
1001
- }
1002
- }
1003
- // if (bitDepth !== 1 && bitDepth !== 8) throw new Error(`Invalid bit depth (${bitDepth})`);
1004
- const extraLimit = (step - 1) | 0; // 3 for rgb, 4 for cmyk
1005
- for (let c = 0, li = 0; c < offsets.length; c++) {
1006
- const offset = offsets[c] | 0;
1007
- const extra = c > extraLimit || offset > extraLimit;
1008
- if (!data || extra) {
1009
- for (let y = 0; y < height; y++, li++) {
1010
- skipBytes(reader, lengths[li]);
1011
- }
1012
- }
1013
- else {
1014
- for (let y = 0, p = offset | 0; y < height; y++, li++) {
1015
- const length = lengths[li];
1016
- const buffer = readBytes(reader, length);
1017
- for (let i = 0, x = 0; i < length; i++) {
1018
- let header = buffer[i];
1019
- if (header > 128) {
1020
- const value = buffer[++i];
1021
- header = (256 - header) | 0;
1022
- for (let j = 0; j <= header && x < width; j = (j + 1) | 0, x = (x + 1) | 0) {
1023
- data[p] = value;
1024
- p = (p + step) | 0;
1025
- }
1026
- }
1027
- else if (header < 128) {
1028
- for (let j = 0; j <= header && x < width; j = (j + 1) | 0, x = (x + 1) | 0) {
1029
- data[p] = buffer[++i];
1030
- p = (p + step) | 0;
1031
- }
1032
- }
1033
- else {
1034
- // ignore 128
1035
- }
1036
- // This showed up on some images from non-photoshop programs, ignoring it seems to work just fine.
1037
- // if (i >= length) throw new Error(`Invalid RLE data: exceeded buffer size ${i}/${length}`);
1038
- }
1039
- }
1040
- }
1041
- }
1042
- }
1043
- export function readSection(reader, round, func, skipEmpty = true, eightBytes = false) {
1044
- let length = readUint32(reader);
1045
- if (eightBytes) {
1046
- if (length !== 0)
1047
- throw new Error('Sizes larger than 4GB are not supported');
1048
- length = readUint32(reader);
1049
- }
1050
- if (length <= 0 && skipEmpty)
1051
- return undefined;
1052
- let end = reader.offset + length;
1053
- if (end > reader.view.byteLength)
1054
- throw new Error('Section exceeds file size');
1055
- const result = func(() => end - reader.offset);
1056
- if (reader.offset !== end) {
1057
- if (reader.offset > end) {
1058
- warnOrThrow(reader, 'Exceeded section limits');
1059
- }
1060
- else {
1061
- warnOrThrow(reader, `Unread section data`); // : ${end - reader.offset} bytes at 0x${reader.offset.toString(16)}`);
1062
- }
1063
- }
1064
- while (length % round) {
1065
- length++;
1066
- end++;
1067
- }
1068
- // while (end % round) end++;
1069
- reader.offset = end;
1070
- return result;
1071
- }
1072
- export function readColor(reader) {
1073
- const colorSpace = readUint16(reader);
1074
- switch (colorSpace) {
1075
- case 0 /* ColorSpace.RGB */: {
1076
- const r = readUint16(reader) / 257;
1077
- const g = readUint16(reader) / 257;
1078
- const b = readUint16(reader) / 257;
1079
- skipBytes(reader, 2);
1080
- return { r, g, b };
1081
- }
1082
- case 1 /* ColorSpace.HSB */: {
1083
- const h = readUint16(reader) / 0xffff;
1084
- const s = readUint16(reader) / 0xffff;
1085
- const b = readUint16(reader) / 0xffff;
1086
- skipBytes(reader, 2);
1087
- return { h, s, b };
1088
- }
1089
- case 2 /* ColorSpace.CMYK */: {
1090
- const c = readUint16(reader) / 257;
1091
- const m = readUint16(reader) / 257;
1092
- const y = readUint16(reader) / 257;
1093
- const k = readUint16(reader) / 257;
1094
- return { c, m, y, k };
1095
- }
1096
- case 7 /* ColorSpace.Lab */: {
1097
- const l = readInt16(reader) / 10000;
1098
- const ta = readInt16(reader);
1099
- const tb = readInt16(reader);
1100
- const a = ta < 0 ? (ta / 12800) : (ta / 12700);
1101
- const b = tb < 0 ? (tb / 12800) : (tb / 12700);
1102
- skipBytes(reader, 2);
1103
- return { l, a, b };
1104
- }
1105
- case 8 /* ColorSpace.Grayscale */: {
1106
- const k = readUint16(reader) * 255 / 10000;
1107
- skipBytes(reader, 6);
1108
- return { k };
1109
- }
1110
- default:
1111
- throw new Error('Invalid color space');
1112
- }
1113
- }
1114
- export function readPattern(reader) {
1115
- let length = readUint32(reader);
1116
- while (length % 4)
1117
- length++;
1118
- const end = reader.offset + length;
1119
- const version = readUint32(reader);
1120
- if (version !== 1)
1121
- throw new Error(`Invalid pattern version: ${version}`);
1122
- const colorMode = readUint32(reader);
1123
- const x = readInt16(reader);
1124
- const y = readInt16(reader);
1125
- // we only support RGB and grayscale for now
1126
- if (colorMode !== 3 /* ColorMode.RGB */ && colorMode !== 1 /* ColorMode.Grayscale */ && colorMode !== 2 /* ColorMode.Indexed */) {
1127
- throw new Error(`Unsupported pattern color mode: ${colorMode}`);
1128
- }
1129
- let name = readUnicodeString(reader);
1130
- const id = readPascalString(reader, 1);
1131
- const palette = [];
1132
- if (colorMode === 2 /* ColorMode.Indexed */) {
1133
- for (let i = 0; i < 256; i++) {
1134
- palette.push({
1135
- r: readUint8(reader),
1136
- g: readUint8(reader),
1137
- b: readUint8(reader),
1138
- });
1139
- }
1140
- skipBytes(reader, 4); // no idea what this is
1141
- }
1142
- // virtual memory array list
1143
- const version2 = readUint32(reader);
1144
- if (version2 !== 3)
1145
- throw new Error(`Invalid pattern VMAL version: ${version2}`);
1146
- readUint32(reader); // length
1147
- const top = readUint32(reader);
1148
- const left = readUint32(reader);
1149
- const bottom = readUint32(reader);
1150
- const right = readUint32(reader);
1151
- const channelsCount = readUint32(reader);
1152
- const width = right - left;
1153
- const height = bottom - top;
1154
- const data = new Uint8Array(width * height * 4);
1155
- for (let i = 3; i < data.byteLength; i += 4) {
1156
- data[i] = 255;
1157
- }
1158
- for (let i = 0, ch = 0; i < (channelsCount + 2); i++) {
1159
- const has = readUint32(reader);
1160
- if (!has)
1161
- continue;
1162
- const length = readUint32(reader);
1163
- const pixelDepth = readUint32(reader);
1164
- const ctop = readUint32(reader);
1165
- const cleft = readUint32(reader);
1166
- const cbottom = readUint32(reader);
1167
- const cright = readUint32(reader);
1168
- const pixelDepth2 = readUint16(reader);
1169
- const compressionMode = readUint8(reader); // 0 - raw, 1 - rle
1170
- const dataLength = length - (4 + 16 + 2 + 1);
1171
- const cdata = readBytes(reader, dataLength);
1172
- if (pixelDepth !== 8 || pixelDepth2 !== 8) {
1173
- throw new Error('16bit pixel depth not supported for patterns');
1174
- }
1175
- const w = cright - cleft;
1176
- const h = cbottom - ctop;
1177
- const ox = cleft - left;
1178
- const oy = ctop - top;
1179
- if (compressionMode === 0) {
1180
- if (colorMode === 3 /* ColorMode.RGB */ && ch < 3) {
1181
- for (let y = 0; y < h; y++) {
1182
- for (let x = 0; x < w; x++) {
1183
- const src = x + y * w;
1184
- const dst = (ox + x + (y + oy) * width) * 4;
1185
- data[dst + ch] = cdata[src];
1186
- }
1187
- }
1188
- }
1189
- if (colorMode === 1 /* ColorMode.Grayscale */ && ch < 1) {
1190
- for (let y = 0; y < h; y++) {
1191
- for (let x = 0; x < w; x++) {
1192
- const src = x + y * w;
1193
- const dst = (ox + x + (y + oy) * width) * 4;
1194
- const value = cdata[src];
1195
- data[dst + 0] = value;
1196
- data[dst + 1] = value;
1197
- data[dst + 2] = value;
1198
- }
1199
- }
1200
- }
1201
- if (colorMode === 2 /* ColorMode.Indexed */) {
1202
- // TODO:
1203
- throw new Error('Indexed pattern color mode not implemented');
1204
- }
1205
- }
1206
- else if (compressionMode === 1) {
1207
- const pixelData = { data, width, height };
1208
- const tempData = { data: new Uint8Array(w * h), width: w, height: h };
1209
- const cdataReader = createReader(cdata.buffer, cdata.byteOffset, cdata.byteLength);
1210
- if (colorMode === 3 /* ColorMode.RGB */ && ch < 3) {
1211
- readDataRLE(cdataReader, tempData, w, h, 8, 1, [0], false);
1212
- copyChannelToRGBA(tempData, pixelData, ox, oy, ch);
1213
- }
1214
- if (colorMode === 1 /* ColorMode.Grayscale */ && ch < 1) {
1215
- readDataRLE(cdataReader, tempData, w, h, 8, 1, [0], false);
1216
- copyChannelToRGBA(tempData, pixelData, ox, oy, 0);
1217
- setupGrayscale(pixelData);
1218
- }
1219
- if (colorMode === 2 /* ColorMode.Indexed */) {
1220
- // TODO:
1221
- throw new Error('Indexed pattern color mode not implemented');
1222
- }
1223
- }
1224
- else {
1225
- throw new Error('Invalid pattern compression mode');
1226
- }
1227
- ch++;
1228
- }
1229
- reader.offset = end;
1230
- return { id, name, x, y, bounds: { x: left, y: top, w: width, h: height }, data };
1231
- }
1232
- function copyChannelToRGBA(srcData, dstData, ox, oy, offset) {
1233
- const w = srcData.width;
1234
- const h = srcData.height;
1235
- const width = dstData.width;
1236
- for (let y = 0; y < h; y++) {
1237
- for (let x = 0; x < w; x++) {
1238
- const src = x + y * w;
1239
- const dst = (ox + x + (y + oy) * width) * 4;
1240
- const value = srcData.data[src];
1241
- dstData.data[dst + offset] = value;
1242
- }
1243
- }
1244
- }
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.supportedColorModes = void 0;
15
+ exports.createReader = createReader;
16
+ exports.warnOrThrow = warnOrThrow;
17
+ exports.readUint8 = readUint8;
18
+ exports.peekUint8 = peekUint8;
19
+ exports.readInt16 = readInt16;
20
+ exports.readUint16 = readUint16;
21
+ exports.readUint16LE = readUint16LE;
22
+ exports.readInt32 = readInt32;
23
+ exports.readInt32LE = readInt32LE;
24
+ exports.readUint32 = readUint32;
25
+ exports.readFloat32 = readFloat32;
26
+ exports.readFloat64 = readFloat64;
27
+ exports.readFixedPoint32 = readFixedPoint32;
28
+ exports.readFixedPointPath32 = readFixedPointPath32;
29
+ exports.readBytes = readBytes;
30
+ exports.readSignature = readSignature;
31
+ exports.validSignatureAt = validSignatureAt;
32
+ exports.readPascalString = readPascalString;
33
+ exports.readUnicodeString = readUnicodeString;
34
+ exports.readUnicodeStringWithLength = readUnicodeStringWithLength;
35
+ exports.readUnicodeStringWithLengthLE = readUnicodeStringWithLengthLE;
36
+ exports.readAsciiString = readAsciiString;
37
+ exports.skipBytes = skipBytes;
38
+ exports.checkSignature = checkSignature;
39
+ exports.readPsd = readPsd;
40
+ exports.readLayerInfo = readLayerInfo;
41
+ exports.getCompositeImageData = getCompositeImageData;
42
+ exports.getCompositeCanvas = getCompositeCanvas;
43
+ exports.getLayerImageData = getLayerImageData;
44
+ exports.getLayerMaskImageData = getLayerMaskImageData;
45
+ exports.getLayerRealMaskImageData = getLayerRealMaskImageData;
46
+ exports.getLayerCanvas = getLayerCanvas;
47
+ exports.getLayerMaskCanvas = getLayerMaskCanvas;
48
+ exports.getLayerRealMaskCanvas = getLayerRealMaskCanvas;
49
+ exports.decodeLayerPixels = decodeLayerPixels;
50
+ exports.readGlobalLayerMaskInfo = readGlobalLayerMaskInfo;
51
+ exports.readAdditionalLayerInfo = readAdditionalLayerInfo;
52
+ exports.readDataZip = readDataZip;
53
+ exports.readDataRLE = readDataRLE;
54
+ exports.readSection = readSection;
55
+ exports.readColor = readColor;
56
+ exports.readPattern = readPattern;
57
+ const pako_1 = require("pako");
58
+ const helpers_1 = require("./helpers");
59
+ const additionalInfo_1 = require("./additionalInfo");
60
+ const imageResources_1 = require("./imageResources");
61
+ exports.supportedColorModes = [0 /* ColorMode.Bitmap */, 1 /* ColorMode.Grayscale */, 3 /* ColorMode.RGB */, 2 /* ColorMode.Indexed */];
62
+ const colorModes = ['bitmap', 'grayscale', 'indexed', 'RGB', 'CMYK', 'multichannel', 'duotone', 'lab'];
63
+ function setupGrayscale(data) {
64
+ const size = data.width * data.height * 4;
65
+ for (let i = 0; i < size; i += 4) {
66
+ const c = data.data[i];
67
+ data.data[i + 1] = c;
68
+ data.data[i + 2] = c;
69
+ }
70
+ }
71
+ function createReader(buffer, offset, length) {
72
+ const view = new DataView(buffer, offset, length);
73
+ return { view, offset: 0, strict: false, debug: false, large: false, globalAlpha: false, log: console.log };
74
+ }
75
+ function warnOrThrow(reader, message) {
76
+ if (reader.strict)
77
+ throw new Error(message);
78
+ if (reader.debug)
79
+ reader.log(message);
80
+ }
81
+ function readUint8(reader) {
82
+ reader.offset += 1;
83
+ return reader.view.getUint8(reader.offset - 1);
84
+ }
85
+ function peekUint8(reader) {
86
+ return reader.view.getUint8(reader.offset);
87
+ }
88
+ function readInt16(reader) {
89
+ reader.offset += 2;
90
+ return reader.view.getInt16(reader.offset - 2, false);
91
+ }
92
+ function readUint16(reader) {
93
+ reader.offset += 2;
94
+ return reader.view.getUint16(reader.offset - 2, false);
95
+ }
96
+ function readUint16LE(reader) {
97
+ reader.offset += 2;
98
+ return reader.view.getUint16(reader.offset - 2, true);
99
+ }
100
+ function readInt32(reader) {
101
+ reader.offset += 4;
102
+ return reader.view.getInt32(reader.offset - 4, false);
103
+ }
104
+ function readInt32LE(reader) {
105
+ reader.offset += 4;
106
+ return reader.view.getInt32(reader.offset - 4, true);
107
+ }
108
+ function readUint32(reader) {
109
+ reader.offset += 4;
110
+ return reader.view.getUint32(reader.offset - 4, false);
111
+ }
112
+ function readFloat32(reader) {
113
+ reader.offset += 4;
114
+ return reader.view.getFloat32(reader.offset - 4, false);
115
+ }
116
+ function readFloat64(reader) {
117
+ reader.offset += 8;
118
+ return reader.view.getFloat64(reader.offset - 8, false);
119
+ }
120
+ // 32-bit fixed-point number 16.16
121
+ function readFixedPoint32(reader) {
122
+ return readInt32(reader) / (1 << 16);
123
+ }
124
+ // 32-bit fixed-point number 8.24
125
+ function readFixedPointPath32(reader) {
126
+ return readInt32(reader) / (1 << 24);
127
+ }
128
+ function readBytes(reader, length) {
129
+ const start = reader.view.byteOffset + reader.offset;
130
+ reader.offset += length;
131
+ if ((start + length) > reader.view.buffer.byteLength) {
132
+ // fix for broken PSD files that are missing part of file at the end
133
+ warnOrThrow(reader, 'Reading bytes exceeding buffer length');
134
+ if (length > (100 * 1024 * 1024))
135
+ throw new Error('Reading past end of file'); // limit to 100MB
136
+ const result = new Uint8Array(length);
137
+ const len = Math.min(length, reader.view.byteLength - start);
138
+ if (len > 0)
139
+ result.set(new Uint8Array(reader.view.buffer, start, len));
140
+ return result;
141
+ }
142
+ else {
143
+ return new Uint8Array(reader.view.buffer, start, length);
144
+ }
145
+ }
146
+ function readSignature(reader) {
147
+ return readShortString(reader, 4);
148
+ }
149
+ function validSignatureAt(reader, offset) {
150
+ const sig = String.fromCharCode(reader.view.getUint8(offset))
151
+ + String.fromCharCode(reader.view.getUint8(offset + 1))
152
+ + String.fromCharCode(reader.view.getUint8(offset + 2))
153
+ + String.fromCharCode(reader.view.getUint8(offset + 3));
154
+ return sig == '8BIM' || sig == '8B64';
155
+ }
156
+ function readPascalString(reader, padTo) {
157
+ let length = readUint8(reader);
158
+ const text = length ? readShortString(reader, length) : '';
159
+ while (++length % padTo) { // starts with length + 1 so we count the size byte too
160
+ reader.offset++;
161
+ }
162
+ return text;
163
+ }
164
+ function readUnicodeString(reader) {
165
+ const length = readUint32(reader);
166
+ return readUnicodeStringWithLength(reader, length);
167
+ }
168
+ function readUnicodeStringWithLength(reader, length) {
169
+ let text = '';
170
+ while (length--) {
171
+ const value = readUint16(reader);
172
+ if (value || length > 0) { // remove trailing \0
173
+ text += String.fromCharCode(value);
174
+ }
175
+ }
176
+ return text;
177
+ }
178
+ function readUnicodeStringWithLengthLE(reader, length) {
179
+ let text = '';
180
+ while (length--) {
181
+ const value = readUint16LE(reader);
182
+ if (value || length > 0) { // remove trailing \0
183
+ text += String.fromCharCode(value);
184
+ }
185
+ }
186
+ return text;
187
+ }
188
+ function readAsciiString(reader, length) {
189
+ let text = '';
190
+ while (length--) {
191
+ text += String.fromCharCode(readUint8(reader));
192
+ }
193
+ return text;
194
+ }
195
+ function skipBytes(reader, count) {
196
+ reader.offset += count;
197
+ }
198
+ function checkSignature(reader, a, b) {
199
+ const offset = reader.offset;
200
+ const signature = readSignature(reader);
201
+ if (signature !== a && signature !== b) {
202
+ throw new Error(`Invalid signature: '${signature}' at 0x${offset.toString(16)}`);
203
+ }
204
+ }
205
+ function readShortString(reader, length) {
206
+ const buffer = readBytes(reader, length);
207
+ let result = '';
208
+ for (let i = 0; i < buffer.length; i++) {
209
+ result += String.fromCharCode(buffer[i]);
210
+ }
211
+ return result;
212
+ }
213
+ function isValidSignature(sig) {
214
+ return sig === '8BIM' || sig === 'MeSa' || sig === 'AgHg' || sig === 'PHUT' || sig === 'DCSR';
215
+ }
216
+ function readPsd(reader, readOptions = {}) {
217
+ var _a;
218
+ // header
219
+ checkSignature(reader, '8BPS');
220
+ const version = readUint16(reader);
221
+ if (version !== 1 && version !== 2)
222
+ throw new Error(`Invalid PSD file version: ${version}`);
223
+ skipBytes(reader, 6);
224
+ const channels = readUint16(reader);
225
+ const height = readUint32(reader);
226
+ const width = readUint32(reader);
227
+ const bitsPerChannel = readUint16(reader);
228
+ const colorMode = readUint16(reader);
229
+ const maxSize = version === 1 ? 30000 : 300000;
230
+ if (width > maxSize || height > maxSize)
231
+ throw new Error(`Invalid size: ${width}x${height}`);
232
+ if (channels > 16)
233
+ throw new Error(`Invalid channel count: ${channels}`);
234
+ if (![1, 8, 16, 32].includes(bitsPerChannel))
235
+ throw new Error(`Invalid bitsPerChannel: ${bitsPerChannel}`);
236
+ if (exports.supportedColorModes.indexOf(colorMode) === -1)
237
+ throw new Error(`Color mode not supported: ${(_a = colorModes[colorMode]) !== null && _a !== void 0 ? _a : colorMode}`);
238
+ const psd = { width, height, channels, bitsPerChannel, colorMode };
239
+ Object.assign(reader, readOptions);
240
+ reader.large = version === 2;
241
+ reader.globalAlpha = false;
242
+ if (!reader.totalMemoryLimit)
243
+ reader.totalMemoryLimit = 2 * 1024 * 1024 * 1024; // default 2GB memory limit
244
+ // color mode data
245
+ readSection(reader, 1, left => {
246
+ if (!left())
247
+ return;
248
+ if (colorMode === 2 /* ColorMode.Indexed */) {
249
+ // should have 256 colors here saved as 8bit channels RGB
250
+ if (left() != 768)
251
+ throw new Error('Invalid color palette size');
252
+ psd.palette = [];
253
+ for (let i = 0; i < 256; i++)
254
+ psd.palette.push({ r: readUint8(reader), g: 0, b: 0 });
255
+ for (let i = 0; i < 256; i++)
256
+ psd.palette[i].g = readUint8(reader);
257
+ for (let i = 0; i < 256; i++)
258
+ psd.palette[i].b = readUint8(reader);
259
+ }
260
+ else {
261
+ // TODO: unknown format for duotone, also seems to have some data here for 32bit colors
262
+ // if (options.throwForMissingFeatures) throw new Error('Color mode data not supported');
263
+ }
264
+ skipBytes(reader, left());
265
+ });
266
+ // image resources
267
+ const imageResources = {};
268
+ readSection(reader, 1, left => {
269
+ while (left() > 0) {
270
+ realignWithSignature(reader, isValidSignature);
271
+ const id = readUint16(reader);
272
+ readPascalString(reader, 2); // name
273
+ readSection(reader, 2, left => {
274
+ const handler = imageResources_1.resourceHandlersMap[id];
275
+ const skip = id === 1036 && !!reader.skipThumbnail;
276
+ if (handler && !skip) {
277
+ try {
278
+ handler.read(reader, imageResources, left);
279
+ }
280
+ catch (e) {
281
+ if (reader.throwForMissingFeatures)
282
+ throw e;
283
+ skipBytes(reader, left());
284
+ }
285
+ }
286
+ else {
287
+ // options.logMissingFeatures && console.log(`Unhandled image resource: ${id} (${left()})`);
288
+ skipBytes(reader, left());
289
+ }
290
+ });
291
+ }
292
+ });
293
+ const { layersGroup, layerGroupsEnabledId } = imageResources, rest = __rest(imageResources, ["layersGroup", "layerGroupsEnabledId"]);
294
+ if (Object.keys(rest)) {
295
+ psd.imageResources = rest;
296
+ }
297
+ // layer and mask info
298
+ readSection(reader, 1, left => {
299
+ readSection(reader, 2, left => {
300
+ readLayerInfo(reader, psd, imageResources);
301
+ skipBytes(reader, left());
302
+ }, undefined, reader.large);
303
+ // SAI does not include this section
304
+ if (left() > 0) {
305
+ const globalLayerMaskInfo = readGlobalLayerMaskInfo(reader);
306
+ if (globalLayerMaskInfo)
307
+ psd.globalLayerMaskInfo = globalLayerMaskInfo;
308
+ }
309
+ else {
310
+ // revert back to end of section if exceeded section limits
311
+ // opt.logMissingFeatures && console.log('reverting to end of section');
312
+ skipBytes(reader, left());
313
+ }
314
+ while (left() > 0) {
315
+ // sometimes there are empty bytes here
316
+ while (left() && peekUint8(reader) === 0) {
317
+ // opt.logMissingFeatures && console.log('skipping 0 byte');
318
+ skipBytes(reader, 1);
319
+ }
320
+ if (left() >= 12) {
321
+ readAdditionalLayerInfo(reader, psd, psd, imageResources);
322
+ }
323
+ else {
324
+ // opt.logMissingFeatures && console.log('skipping leftover bytes', left());
325
+ skipBytes(reader, left());
326
+ }
327
+ }
328
+ }, undefined, reader.large);
329
+ const hasChildren = psd.children && psd.children.length;
330
+ const skipComposite = reader.skipCompositeImageData && (reader.skipLayerImageData || hasChildren);
331
+ if (!skipComposite) {
332
+ if (reader.useRawData) {
333
+ psd.rawCompositeData = new Uint8Array(reader.view.buffer, reader.view.byteOffset + reader.offset);
334
+ }
335
+ else {
336
+ const imageData = readImageData(reader, psd);
337
+ if (reader.useImageData) {
338
+ psd.imageData = imageData;
339
+ }
340
+ else {
341
+ psd.canvas = (0, helpers_1.imageDataToCanvas)(imageData);
342
+ }
343
+ }
344
+ }
345
+ // TODO: show converted color mode instead of original PSD file color mode
346
+ // but add option to preserve file color mode (need to return image data instead of canvas in that case)
347
+ // psd.colorMode = ColorMode.RGB; // we convert all color modes to RGB
348
+ return psd;
349
+ }
350
+ function readLayerInfo(reader, psd, imageResources) {
351
+ var _a, _b;
352
+ const { layersGroup = [], layerGroupsEnabledId = [] } = imageResources;
353
+ let layerCount = readInt16(reader);
354
+ if (layerCount < 0) {
355
+ reader.globalAlpha = true;
356
+ layerCount = -layerCount;
357
+ }
358
+ const layers = [];
359
+ const layerChannels = [];
360
+ for (let i = 0; i < layerCount; i++) {
361
+ const { layer, channels } = readLayerRecord(reader, psd, imageResources);
362
+ if (layersGroup[i] !== undefined)
363
+ layer.linkGroup = layersGroup[i];
364
+ if (layerGroupsEnabledId[i] !== undefined)
365
+ layer.linkGroupEnabled = !!layerGroupsEnabledId[i];
366
+ layers.push(layer);
367
+ layerChannels.push(channels);
368
+ }
369
+ for (let i = 0; i < layerCount; i++) {
370
+ readLayerChannelImageData(reader, psd, layers[i], layerChannels[i]);
371
+ }
372
+ if (!psd.children)
373
+ psd.children = [];
374
+ const stack = [psd];
375
+ for (let i = layers.length - 1; i >= 0; i--) {
376
+ const l = layers[i];
377
+ const type = l.sectionDivider ? l.sectionDivider.type : 0 /* SectionDividerType.Other */;
378
+ if (type === 1 /* SectionDividerType.OpenFolder */ || type === 2 /* SectionDividerType.ClosedFolder */) {
379
+ l.opened = type === 1 /* SectionDividerType.OpenFolder */;
380
+ l.children = [];
381
+ if ((_a = l.sectionDivider) === null || _a === void 0 ? void 0 : _a.key) {
382
+ l.blendMode = (_b = helpers_1.toBlendMode[l.sectionDivider.key]) !== null && _b !== void 0 ? _b : l.blendMode;
383
+ }
384
+ stack[stack.length - 1].children.unshift(l);
385
+ stack.push(l);
386
+ }
387
+ else if (type === 3 /* SectionDividerType.BoundingSectionDivider */) {
388
+ stack.pop();
389
+ // this was workaround because I didn't know what `lsdk` section was, now it's probably not needed anymore
390
+ // } else if (l.name === '</Layer group>' && !l.sectionDivider && !l.top && !l.left && !l.bottom && !l.right) {
391
+ // // sometimes layer group terminator doesn't have sectionDivider, so we just guess here (PS bug ?)
392
+ // stack.pop();
393
+ }
394
+ else {
395
+ stack[stack.length - 1].children.unshift(l);
396
+ }
397
+ }
398
+ }
399
+ function readLayerRecord(reader, psd, imageResources) {
400
+ const layer = {};
401
+ layer.top = readInt32(reader);
402
+ layer.left = readInt32(reader);
403
+ layer.bottom = readInt32(reader);
404
+ layer.right = readInt32(reader);
405
+ const channelCount = readUint16(reader);
406
+ const channels = [];
407
+ for (let i = 0; i < channelCount; i++) {
408
+ let id = readInt16(reader);
409
+ let length = readUint32(reader);
410
+ if (reader.large) {
411
+ if (length !== 0)
412
+ throw new Error('Sizes larger than 4GB are not supported');
413
+ length = readUint32(reader);
414
+ }
415
+ channels.push({ id, length });
416
+ }
417
+ checkSignature(reader, '8BIM');
418
+ const blendMode = readSignature(reader);
419
+ if (!helpers_1.toBlendMode[blendMode])
420
+ throw new Error(`Invalid blend mode: '${blendMode}'`);
421
+ layer.blendMode = helpers_1.toBlendMode[blendMode];
422
+ layer.opacity = readUint8(reader) / 0xff;
423
+ layer.clipping = readUint8(reader) === 1;
424
+ const flags = readUint8(reader);
425
+ layer.transparencyProtected = (flags & 0x01) !== 0;
426
+ layer.hidden = (flags & 0x02) !== 0;
427
+ if (flags & 0x20)
428
+ layer.effectsOpen = true;
429
+ // 0x04 - obsolete
430
+ // 0x08 - 1 for Photoshop 5.0 and later, tells if bit 4 has useful information
431
+ // 0x10 - pixel data irrelevant to appearance of document
432
+ // 0x20 - effects/filters panel is expanded
433
+ skipBytes(reader, 1);
434
+ readSection(reader, 1, left => {
435
+ readLayerMaskData(reader, layer);
436
+ const blendingRanges = readLayerBlendingRanges(reader);
437
+ if (blendingRanges)
438
+ layer.blendingRanges = blendingRanges;
439
+ layer.name = readPascalString(reader, 1); // should be padded to 4, but is not sometimes
440
+ // HACK: fix for sometimes layer.name string not being padded correctly, just skip until we get valid signature
441
+ while (left() > 4 && !validSignatureAt(reader, reader.offset))
442
+ reader.offset++;
443
+ while (left() >= 12)
444
+ readAdditionalLayerInfo(reader, layer, psd, imageResources);
445
+ skipBytes(reader, left());
446
+ });
447
+ return { layer, channels };
448
+ }
449
+ function readLayerMaskData(reader, layer) {
450
+ return readSection(reader, 1, left => {
451
+ if (!left())
452
+ return undefined;
453
+ const mask = {};
454
+ layer.mask = mask;
455
+ mask.top = readInt32(reader);
456
+ mask.left = readInt32(reader);
457
+ mask.bottom = readInt32(reader);
458
+ mask.right = readInt32(reader);
459
+ mask.defaultColor = readUint8(reader);
460
+ const flags = readUint8(reader);
461
+ mask.positionRelativeToLayer = (flags & 1 /* LayerMaskFlags.PositionRelativeToLayer */) !== 0;
462
+ mask.disabled = (flags & 2 /* LayerMaskFlags.LayerMaskDisabled */) !== 0;
463
+ mask.fromVectorData = (flags & 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */) !== 0;
464
+ if (left() >= 18) {
465
+ const realMask = {};
466
+ layer.realMask = realMask;
467
+ const realFlags = readUint8(reader);
468
+ realMask.positionRelativeToLayer = (realFlags & 1 /* LayerMaskFlags.PositionRelativeToLayer */) !== 0;
469
+ realMask.disabled = (realFlags & 2 /* LayerMaskFlags.LayerMaskDisabled */) !== 0;
470
+ realMask.fromVectorData = (realFlags & 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */) !== 0;
471
+ realMask.defaultColor = readUint8(reader); // Real user mask background. 0 or 255.
472
+ realMask.top = readInt32(reader);
473
+ realMask.left = readInt32(reader);
474
+ realMask.bottom = readInt32(reader);
475
+ realMask.right = readInt32(reader);
476
+ }
477
+ if (flags & 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */) {
478
+ const params = readUint8(reader);
479
+ if (params & 1 /* MaskParams.UserMaskDensity */)
480
+ mask.userMaskDensity = readUint8(reader) / 0xff;
481
+ if (params & 2 /* MaskParams.UserMaskFeather */)
482
+ mask.userMaskFeather = readFloat64(reader);
483
+ if (params & 4 /* MaskParams.VectorMaskDensity */)
484
+ mask.vectorMaskDensity = readUint8(reader) / 0xff;
485
+ if (params & 8 /* MaskParams.VectorMaskFeather */)
486
+ mask.vectorMaskFeather = readFloat64(reader);
487
+ }
488
+ skipBytes(reader, left());
489
+ });
490
+ }
491
+ function readBlendingRange(reader) {
492
+ return [readUint8(reader), readUint8(reader), readUint8(reader), readUint8(reader)];
493
+ }
494
+ function readLayerBlendingRanges(reader) {
495
+ return readSection(reader, 1, left => {
496
+ const compositeGrayBlendSource = readBlendingRange(reader);
497
+ const compositeGraphBlendDestinationRange = readBlendingRange(reader);
498
+ const ranges = [];
499
+ while (left() > 0) {
500
+ const sourceRange = readBlendingRange(reader);
501
+ const destRange = readBlendingRange(reader);
502
+ ranges.push({ sourceRange, destRange });
503
+ }
504
+ return { compositeGrayBlendSource, compositeGraphBlendDestinationRange, ranges };
505
+ });
506
+ }
507
+ function readLayerChannelImageData(reader, psd, layer, channels) {
508
+ if (reader.skipLayerImageData)
509
+ return;
510
+ const { colorMode = 3 /* ColorMode.RGB */, bitsPerChannel = 8 } = psd;
511
+ layer.rawData = { colorMode, bitsPerChannel, channels: [], large: reader.large };
512
+ for (const channel of channels) {
513
+ const start = reader.offset;
514
+ let compression = 0 /* Compression.RawData */;
515
+ let data = undefined;
516
+ if (channel.length === 1)
517
+ throw new Error('Invalid channel length');
518
+ if (channel.length) {
519
+ compression = readUint16(reader);
520
+ // try to fix broken files where there's 1 byte shift of channel
521
+ if (compression > 3) {
522
+ reader.offset -= 1;
523
+ compression = readUint16(reader);
524
+ }
525
+ // try to fix broken files where there's 1 byte shift of channel
526
+ if (compression > 3) {
527
+ reader.offset -= 3;
528
+ compression = readUint16(reader);
529
+ }
530
+ if (compression > 3)
531
+ throw new Error(`Invalid compression: ${compression}`);
532
+ if (channel.length > 2) {
533
+ data = readBytes(reader, channel.length - 2);
534
+ }
535
+ }
536
+ reader.offset = start + channel.length;
537
+ layer.rawData.channels.push({ id: channel.id, compression, data });
538
+ }
539
+ if (!reader.useRawData) {
540
+ decodeLayerImageData(layer, reader);
541
+ }
542
+ }
543
+ function resetAlpha({ data }, cmyk) {
544
+ const alpha = (data instanceof Float32Array) ? 1.0 : ((data instanceof Uint16Array) ? 0xffff : 0xff);
545
+ const offset = (cmyk ? 4 : 3) | 0;
546
+ const length = data.length | 0;
547
+ const step = (cmyk ? 5 : 4) | 0;
548
+ for (let p = offset; p < length; p = (p + step) | 0) {
549
+ data[p] = alpha;
550
+ }
551
+ }
552
+ function getCompositeImageData(psd) {
553
+ const data = psd.rawCompositeData;
554
+ if (!data)
555
+ return undefined;
556
+ const reader = createReader(data.buffer, data.byteOffset, data.byteLength);
557
+ const imageData = readImageData(reader, psd);
558
+ return imageData;
559
+ }
560
+ function getCompositeCanvas(psd) {
561
+ return imageDataToCanvasSafe(getCompositeImageData(psd));
562
+ }
563
+ function getLayerImageData(layer) {
564
+ return getDataFromLayer(layer, LayerDataType.Layer, false, undefined);
565
+ }
566
+ function getLayerMaskImageData(layer) {
567
+ return getDataFromLayer(layer, LayerDataType.Mask, false, undefined);
568
+ }
569
+ function getLayerRealMaskImageData(layer) {
570
+ return getDataFromLayer(layer, LayerDataType.RealMask, false, undefined);
571
+ }
572
+ function getLayerCanvas(layer) {
573
+ return imageDataToCanvasSafe(getLayerImageData(layer));
574
+ }
575
+ function getLayerMaskCanvas(layer) {
576
+ return imageDataToCanvasSafe(getLayerMaskImageData(layer));
577
+ }
578
+ function getLayerRealMaskCanvas(layer) {
579
+ return imageDataToCanvasSafe(getLayerRealMaskImageData(layer));
580
+ }
581
+ function imageDataToCanvasSafe(imageData) {
582
+ return imageData && (0, helpers_1.imageDataToCanvas)(imageData);
583
+ }
584
+ function setImageDataOrCanvas(obj, imageData, useImageData) {
585
+ if (!imageData)
586
+ return;
587
+ if (useImageData) {
588
+ obj.imageData = imageData;
589
+ }
590
+ else {
591
+ obj.canvas = (0, helpers_1.imageDataToCanvas)(imageData);
592
+ }
593
+ }
594
+ function decodeLayerPixels(layer, useImageData) {
595
+ decodeLayerImageData(layer, { useImageData });
596
+ }
597
+ function decodeLayerImageData(layer, options) {
598
+ var _a, _b, _c;
599
+ let { throwForMissingFeatures, useImageData } = options;
600
+ const imageData = getDataFromLayer(layer, LayerDataType.Layer, throwForMissingFeatures, options.totalMemoryLimit);
601
+ setImageDataOrCanvas(layer, imageData, useImageData);
602
+ if (options.totalMemoryLimit !== undefined)
603
+ options.totalMemoryLimit -= (_a = imageData === null || imageData === void 0 ? void 0 : imageData.data.byteLength) !== null && _a !== void 0 ? _a : 0;
604
+ if (layer.mask) {
605
+ const maskData = getDataFromLayer(layer, LayerDataType.Mask, throwForMissingFeatures, options.totalMemoryLimit);
606
+ setImageDataOrCanvas(layer.mask, maskData, useImageData);
607
+ if (options.totalMemoryLimit !== undefined)
608
+ options.totalMemoryLimit -= (_b = maskData === null || maskData === void 0 ? void 0 : maskData.data.byteLength) !== null && _b !== void 0 ? _b : 0;
609
+ }
610
+ if (layer.realMask) {
611
+ const maskData = getDataFromLayer(layer, LayerDataType.RealMask, throwForMissingFeatures, options.totalMemoryLimit);
612
+ setImageDataOrCanvas(layer.realMask, maskData, useImageData);
613
+ if (options.totalMemoryLimit !== undefined)
614
+ options.totalMemoryLimit -= (_c = maskData === null || maskData === void 0 ? void 0 : maskData.data.byteLength) !== null && _c !== void 0 ? _c : 0;
615
+ }
616
+ delete layer.rawData;
617
+ }
618
+ var LayerDataType;
619
+ (function (LayerDataType) {
620
+ LayerDataType[LayerDataType["Layer"] = 0] = "Layer";
621
+ LayerDataType[LayerDataType["Mask"] = 1] = "Mask";
622
+ LayerDataType[LayerDataType["RealMask"] = 2] = "RealMask";
623
+ })(LayerDataType || (LayerDataType = {}));
624
+ function getDataFromLayer(layer, read, throwForMissingFeatures, memoryLimit) {
625
+ if (!layer.rawData)
626
+ return undefined;
627
+ const { colorMode, bitsPerChannel, channels, large } = layer.rawData;
628
+ const layerWidth = (layer.right || 0) - (layer.left || 0);
629
+ const layerHeight = (layer.bottom || 0) - (layer.top || 0);
630
+ const cmyk = colorMode === 4 /* ColorMode.CMYK */;
631
+ let imageData;
632
+ let maskData;
633
+ let initializedAlpha = false;
634
+ if (layerWidth && layerHeight && read === LayerDataType.Layer) {
635
+ if (cmyk) {
636
+ if (bitsPerChannel !== 8)
637
+ throw new Error('bitsPerChannel Not supproted');
638
+ imageData = { width: layerWidth, height: layerHeight, data: new Uint8ClampedArray(layerWidth * layerHeight * 5) };
639
+ }
640
+ else {
641
+ imageData = createImageDataBitDepth(layerWidth, layerHeight, bitsPerChannel, 4, memoryLimit);
642
+ }
643
+ }
644
+ if (helpers_1.RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
645
+ layer.imageDataRaw = [];
646
+ layer.imageDataRawCompression = [];
647
+ }
648
+ for (const { id, compression, data } of channels) {
649
+ if (!data)
650
+ continue;
651
+ const dataReader = createReader(data.buffer, data.byteOffset, data.byteLength);
652
+ if (id === -2 /* ChannelID.UserMask */ || id === -3 /* ChannelID.RealUserMask */) {
653
+ if (id === -2 /* ChannelID.UserMask */ && read !== LayerDataType.Mask)
654
+ continue;
655
+ if (id === -3 /* ChannelID.RealUserMask */ && read !== LayerDataType.RealMask)
656
+ continue;
657
+ const mask = id === -2 /* ChannelID.UserMask */ ? layer.mask : layer.realMask;
658
+ if (!mask)
659
+ throw new Error(`Missing layer ${id === -2 /* ChannelID.UserMask */ ? 'mask' : 'real mask'} data`);
660
+ const maskWidth = (mask.right || 0) - (mask.left || 0);
661
+ const maskHeight = (mask.bottom || 0) - (mask.top || 0);
662
+ if (maskWidth < 0 || maskHeight < 0 || maskWidth > 30000 || maskHeight > 30000)
663
+ throw new Error('Invalid mask size');
664
+ if (maskWidth && maskHeight) {
665
+ maskData = createImageDataBitDepth(maskWidth, maskHeight, bitsPerChannel, 4, memoryLimit);
666
+ readData(dataReader, data.byteLength, maskData, compression, maskWidth, maskHeight, bitsPerChannel, 0, large, 4);
667
+ if (helpers_1.RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
668
+ if (id === -2 /* ChannelID.UserMask */) {
669
+ layer.maskDataRawCompression = compression;
670
+ layer.maskDataRaw = data;
671
+ }
672
+ else {
673
+ layer.realMaskDataRawCompression = compression;
674
+ layer.realMaskDataRaw = data;
675
+ }
676
+ }
677
+ setupGrayscale(maskData);
678
+ resetAlpha(maskData, false);
679
+ }
680
+ }
681
+ else {
682
+ if (read !== LayerDataType.Layer)
683
+ continue;
684
+ const offset = (0, helpers_1.offsetForChannel)(id, cmyk);
685
+ let targetData = imageData;
686
+ if (offset < 0) {
687
+ targetData = undefined;
688
+ if (throwForMissingFeatures) {
689
+ throw new Error(`Channel not supported: ${id}`);
690
+ }
691
+ }
692
+ readData(dataReader, data.byteLength, targetData, compression, layerWidth, layerHeight, bitsPerChannel, offset, large, cmyk ? 5 : 4);
693
+ if (helpers_1.RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
694
+ layer.imageDataRawCompression[id] = compression;
695
+ layer.imageDataRaw[id] = data;
696
+ }
697
+ if (targetData && colorMode === 1 /* ColorMode.Grayscale */) {
698
+ setupGrayscale(targetData);
699
+ }
700
+ }
701
+ if (id === -1 /* ChannelID.Transparency */) {
702
+ initializedAlpha = true;
703
+ }
704
+ }
705
+ if (imageData) {
706
+ if (!initializedAlpha)
707
+ resetAlpha(imageData, cmyk);
708
+ if (cmyk) {
709
+ const cmykData = imageData;
710
+ imageData = (0, helpers_1.createImageData)(cmykData.width, cmykData.height);
711
+ cmykToRgb(cmykData, imageData, false);
712
+ }
713
+ }
714
+ return read === LayerDataType.Layer ? imageData : maskData;
715
+ }
716
+ function readData(reader, length, pixels, compression, width, height, bitDepth, offset, large, step) {
717
+ if (!length)
718
+ return;
719
+ if (compression === 0 /* Compression.RawData */) {
720
+ if (length !== (width * height * Math.floor(bitDepth / 8))) {
721
+ reader.log(`Invalid length (${length}, ${width * height * Math.floor(bitDepth / 8)})`);
722
+ }
723
+ const data = readBytes(reader, length);
724
+ readDataRaw(data, pixels, bitDepth, step, offset);
725
+ }
726
+ else if (compression === 1 /* Compression.RleCompressed */) {
727
+ // const reader = createReader(data.buffer, data.byteOffset, data.byteLength);
728
+ readDataRLE(reader, pixels, width, height, bitDepth, step, [offset], large);
729
+ }
730
+ else if (compression === 2 /* Compression.ZipWithoutPrediction */) {
731
+ const data = readBytes(reader, length);
732
+ readDataZip(data, pixels, width, height, bitDepth, step, offset, false);
733
+ }
734
+ else if (compression === 3 /* Compression.ZipWithPrediction */) {
735
+ const data = readBytes(reader, length);
736
+ readDataZip(data, pixels, width, height, bitDepth, step, offset, true);
737
+ }
738
+ else {
739
+ throw new Error(`Invalid Compression type: ${compression}`);
740
+ }
741
+ }
742
+ function readGlobalLayerMaskInfo(reader) {
743
+ return readSection(reader, 1, left => {
744
+ if (!left())
745
+ return undefined;
746
+ const overlayColorSpace = readUint16(reader);
747
+ const colorSpace1 = readUint16(reader);
748
+ const colorSpace2 = readUint16(reader);
749
+ const colorSpace3 = readUint16(reader);
750
+ const colorSpace4 = readUint16(reader);
751
+ const opacity = readUint16(reader) / 0xff;
752
+ const kind = readUint8(reader);
753
+ skipBytes(reader, left()); // 3 bytes of padding ?
754
+ return { overlayColorSpace, colorSpace1, colorSpace2, colorSpace3, colorSpace4, opacity, kind };
755
+ });
756
+ }
757
+ const fixOffsets = [0, 1, -1, 2, -2, 3, -3, 4, -4];
758
+ function realignWithSignature(reader, isValid) {
759
+ const sigOffset = reader.offset;
760
+ let sig = '';
761
+ // attempt to fix broken document by realigning with the signature
762
+ for (const offset of fixOffsets) {
763
+ try {
764
+ reader.offset = sigOffset + offset;
765
+ sig = readSignature(reader);
766
+ }
767
+ catch (_a) { }
768
+ if (isValid(sig))
769
+ break;
770
+ }
771
+ if (!isValid(sig)) {
772
+ throw new Error(`Invalid signature: '${sig}' at 0x${(sigOffset).toString(16)}`);
773
+ }
774
+ return sig;
775
+ }
776
+ function isValidAdditionalInfoSignature(sig) {
777
+ return sig === '8BIM' || sig === '8B64';
778
+ }
779
+ function readAdditionalLayerInfo(reader, target, psd, imageResources) {
780
+ const sig = realignWithSignature(reader, isValidAdditionalInfoSignature);
781
+ const key = readSignature(reader);
782
+ // `largeAdditionalInfoKeys` fallback, because some keys don't have 8B64 signature even when they are 64bit
783
+ const u64 = sig === '8B64' || (reader.large && helpers_1.largeAdditionalInfoKeys.indexOf(key) !== -1);
784
+ readSection(reader, 2, left => {
785
+ const handler = additionalInfo_1.infoHandlersMap[key];
786
+ if (handler) {
787
+ try {
788
+ handler.read(reader, target, left, psd, imageResources);
789
+ }
790
+ catch (e) {
791
+ if (reader.throwForMissingFeatures)
792
+ throw e;
793
+ }
794
+ }
795
+ else {
796
+ reader.logMissingFeatures && reader.log(`Unhandled additional info: ${key}`);
797
+ skipBytes(reader, left());
798
+ }
799
+ if (left()) {
800
+ reader.logMissingFeatures && reader.log(`Unread ${left()} bytes left for additional info: ${key}`);
801
+ skipBytes(reader, left());
802
+ }
803
+ }, false, u64);
804
+ }
805
+ function createImageDataBitDepth(width, height, bitDepth, channels, memoryLimit) {
806
+ const sizeInBytes = width * height * channels * Math.max(1, bitDepth / 8);
807
+ if (memoryLimit !== undefined && sizeInBytes > memoryLimit)
808
+ throw new Error('Exceeded memory limit');
809
+ if (bitDepth === 1 || bitDepth === 8) {
810
+ if (channels === 4) {
811
+ return (0, helpers_1.createImageData)(width, height);
812
+ }
813
+ else {
814
+ return { width, height, data: new Uint8ClampedArray(width * height * channels) };
815
+ }
816
+ }
817
+ else if (bitDepth === 16) {
818
+ return { width, height, data: new Uint16Array(width * height * channels) };
819
+ }
820
+ else if (bitDepth === 32) {
821
+ return { width, height, data: new Float32Array(width * height * channels) };
822
+ }
823
+ else {
824
+ throw new Error(`Invalid bitDepth (${bitDepth})`);
825
+ }
826
+ }
827
+ function readImageData(reader, psd) {
828
+ var _a;
829
+ const compression = readUint16(reader);
830
+ const bitsPerChannel = (_a = psd.bitsPerChannel) !== null && _a !== void 0 ? _a : 8;
831
+ if (exports.supportedColorModes.indexOf(psd.colorMode) === -1)
832
+ throw new Error(`Color mode not supported: ${psd.colorMode}`);
833
+ if (compression !== 0 /* Compression.RawData */ && compression !== 1 /* Compression.RleCompressed */)
834
+ throw new Error(`Compression type not supported: ${compression}`);
835
+ const imageData = createImageDataBitDepth(psd.width, psd.height, bitsPerChannel, 4, reader.totalMemoryLimit);
836
+ if (reader.totalMemoryLimit !== undefined)
837
+ reader.totalMemoryLimit -= imageData.data.byteLength;
838
+ (0, helpers_1.resetImageData)(imageData);
839
+ switch (psd.colorMode) {
840
+ case 0 /* ColorMode.Bitmap */: {
841
+ if (bitsPerChannel !== 1)
842
+ throw new Error('Invalid bitsPerChannel for bitmap color mode');
843
+ let bytes;
844
+ if (compression === 0 /* Compression.RawData */) {
845
+ bytes = readBytes(reader, Math.ceil(psd.width / 8) * psd.height);
846
+ }
847
+ else if (compression === 1 /* Compression.RleCompressed */) {
848
+ bytes = new Uint8Array(psd.width * psd.height);
849
+ readDataRLE(reader, { data: bytes, width: psd.width, height: psd.height }, psd.width, psd.height, 8, 1, [0], reader.large);
850
+ }
851
+ else {
852
+ throw new Error(`Compression not supported: ${compression}`);
853
+ }
854
+ (0, helpers_1.decodeBitmap)(bytes, imageData.data, psd.width, psd.height);
855
+ break;
856
+ }
857
+ case 3 /* ColorMode.RGB */:
858
+ case 1 /* ColorMode.Grayscale */: {
859
+ const channels = psd.colorMode === 1 /* ColorMode.Grayscale */ ? [0] : [0, 1, 2];
860
+ if (psd.channels && psd.channels > 3) {
861
+ for (let i = 3; i < psd.channels; i++) {
862
+ // TODO: store these channels in additional image data
863
+ channels.push(i);
864
+ }
865
+ }
866
+ else if (reader.globalAlpha) {
867
+ channels.push(3);
868
+ }
869
+ if (compression === 0 /* Compression.RawData */) {
870
+ for (let i = 0; i < channels.length; i++) {
871
+ const data = readBytes(reader, psd.width * psd.height * Math.floor(bitsPerChannel / 8));
872
+ readDataRaw(data, imageData, bitsPerChannel, 4, channels[i]);
873
+ }
874
+ }
875
+ else if (compression === 1 /* Compression.RleCompressed */) {
876
+ const start = reader.offset;
877
+ readDataRLE(reader, imageData, psd.width, psd.height, bitsPerChannel, 4, channels, reader.large);
878
+ if (helpers_1.RAW_IMAGE_DATA)
879
+ psd.imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
880
+ }
881
+ else {
882
+ throw new Error(`Compression not supported: ${compression}`);
883
+ }
884
+ if (psd.colorMode === 1 /* ColorMode.Grayscale */) {
885
+ setupGrayscale(imageData);
886
+ }
887
+ break;
888
+ }
889
+ case 2 /* ColorMode.Indexed */: {
890
+ if (bitsPerChannel !== 8)
891
+ throw new Error('bitsPerChannel Not supproted');
892
+ if (psd.channels !== 1)
893
+ throw new Error('Invalid channel count');
894
+ if (!psd.palette)
895
+ throw new Error('Missing color palette');
896
+ if (compression === 0 /* Compression.RawData */) {
897
+ throw new Error(`Compression not supported: ${compression}`);
898
+ }
899
+ else if (compression === 1 /* Compression.RleCompressed */) {
900
+ const indexedImageData = {
901
+ width: imageData.width,
902
+ height: imageData.height,
903
+ data: new Uint8Array(imageData.width * imageData.height),
904
+ };
905
+ readDataRLE(reader, indexedImageData, psd.width, psd.height, bitsPerChannel, 1, [0], reader.large);
906
+ indexedToRgb(indexedImageData, imageData, psd.palette);
907
+ }
908
+ else {
909
+ throw new Error(`Compression not supported: ${compression}`);
910
+ }
911
+ break;
912
+ }
913
+ case 4 /* ColorMode.CMYK */: {
914
+ if (bitsPerChannel !== 8)
915
+ throw new Error('bitsPerChannel Not supproted');
916
+ if (psd.channels !== 4)
917
+ throw new Error(`Invalid channel count`);
918
+ const channels = [0, 1, 2, 3];
919
+ if (reader.globalAlpha)
920
+ channels.push(4);
921
+ if (compression === 0 /* Compression.RawData */) {
922
+ throw new Error(`Compression not supported: ${compression}`);
923
+ // TODO: ...
924
+ // for (let i = 0; i < channels.length; i++) {
925
+ // readDataRaw(reader, imageData, channels[i], psd.width, psd.height);
926
+ // }
927
+ }
928
+ else if (compression === 1 /* Compression.RleCompressed */) {
929
+ const cmykImageData = {
930
+ width: imageData.width,
931
+ height: imageData.height,
932
+ data: new Uint8Array(imageData.width * imageData.height * 5),
933
+ };
934
+ const start = reader.offset;
935
+ readDataRLE(reader, cmykImageData, psd.width, psd.height, bitsPerChannel, 5, channels, reader.large);
936
+ cmykToRgb(cmykImageData, imageData, true);
937
+ if (helpers_1.RAW_IMAGE_DATA)
938
+ psd.imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
939
+ }
940
+ else {
941
+ throw new Error(`Compression not supported: ${compression}`);
942
+ }
943
+ break;
944
+ }
945
+ default: throw new Error(`Color mode not supported: ${psd.colorMode}`);
946
+ }
947
+ // remove weird white matte
948
+ if (reader.globalAlpha) {
949
+ if (psd.bitsPerChannel !== 8)
950
+ throw new Error('bitsPerChannel Not supproted');
951
+ const p = imageData.data;
952
+ const size = imageData.width * imageData.height * 4;
953
+ for (let i = 0; i < size; i += 4) {
954
+ const pa = p[i + 3];
955
+ if (pa != 0 && pa != 255) {
956
+ const a = pa / 255;
957
+ const ra = 1 / a;
958
+ const invA = 255 * (1 - ra);
959
+ p[i + 0] = p[i + 0] * ra + invA;
960
+ p[i + 1] = p[i + 1] * ra + invA;
961
+ p[i + 2] = p[i + 2] * ra + invA;
962
+ }
963
+ }
964
+ }
965
+ return imageData;
966
+ }
967
+ function cmykToRgb(cmyk, rgb, reverseAlpha) {
968
+ const size = rgb.width * rgb.height * 4;
969
+ const srcData = cmyk.data;
970
+ const dstData = rgb.data;
971
+ for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
972
+ const c = srcData[src];
973
+ const m = srcData[src + 1];
974
+ const y = srcData[src + 2];
975
+ const k = srcData[src + 3];
976
+ dstData[dst] = ((((c * k) | 0) / 255) | 0);
977
+ dstData[dst + 1] = ((((m * k) | 0) / 255) | 0);
978
+ dstData[dst + 2] = ((((y * k) | 0) / 255) | 0);
979
+ dstData[dst + 3] = reverseAlpha ? 255 - srcData[src + 4] : srcData[src + 4];
980
+ }
981
+ // for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
982
+ // const c = 1 - (srcData[src + 0] / 255);
983
+ // const m = 1 - (srcData[src + 1] / 255);
984
+ // const y = 1 - (srcData[src + 2] / 255);
985
+ // // const k = srcData[src + 3] / 255;
986
+ // dstData[dst + 0] = ((1 - c * 0.8) * 255) | 0;
987
+ // dstData[dst + 1] = ((1 - m * 0.8) * 255) | 0;
988
+ // dstData[dst + 2] = ((1 - y * 0.8) * 255) | 0;
989
+ // dstData[dst + 3] = reverseAlpha ? 255 - srcData[src + 4] : srcData[src + 4];
990
+ // }
991
+ }
992
+ function indexedToRgb(indexed, rgb, palette) {
993
+ const size = indexed.width * indexed.height;
994
+ const srcData = indexed.data;
995
+ const dstData = rgb.data;
996
+ for (let src = 0, dst = 0; src < size; src++, dst += 4) {
997
+ const c = palette[srcData[src]];
998
+ dstData[dst + 0] = c.r;
999
+ dstData[dst + 1] = c.g;
1000
+ dstData[dst + 2] = c.b;
1001
+ dstData[dst + 3] = 255;
1002
+ }
1003
+ }
1004
+ function verifyCompatible(a, b) {
1005
+ if ((a.byteLength / a.length) !== (b.byteLength / b.length)) {
1006
+ throw new Error('Invalid array types');
1007
+ }
1008
+ }
1009
+ function bytesToArray(bytes, bitDepth) {
1010
+ if (bitDepth === 8) {
1011
+ return bytes;
1012
+ }
1013
+ else if (bitDepth === 16) {
1014
+ // PSD files store 16-bit channel data in big-endian byte order.
1015
+ // Swap each pair of bytes so that Uint16Array (native-endian) reads the correct values.
1016
+ for (let i = 0; i < bytes.byteLength; i += 2) {
1017
+ const tmp = bytes[i];
1018
+ bytes[i] = bytes[i + 1];
1019
+ bytes[i + 1] = tmp;
1020
+ }
1021
+ if (bytes.byteOffset % 2) {
1022
+ const result = new Uint16Array(bytes.byteLength / 2);
1023
+ new Uint8Array(result.buffer, result.byteOffset, result.byteLength).set(bytes);
1024
+ return result;
1025
+ }
1026
+ else {
1027
+ return new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 2);
1028
+ }
1029
+ }
1030
+ else if (bitDepth === 32) {
1031
+ if (bytes.byteOffset % 4) {
1032
+ const result = new Float32Array(bytes.byteLength / 4);
1033
+ new Uint8Array(result.buffer, result.byteOffset, result.byteLength).set(bytes);
1034
+ return result;
1035
+ }
1036
+ else {
1037
+ return new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength / 4);
1038
+ }
1039
+ }
1040
+ else {
1041
+ throw new Error(`Invalid bitDepth (${bitDepth})`);
1042
+ }
1043
+ }
1044
+ function copyChannelToPixelData(pixelData, channel, offset, step) {
1045
+ verifyCompatible(pixelData.data, channel);
1046
+ const size = pixelData.width * pixelData.height;
1047
+ const data = pixelData.data;
1048
+ for (let i = 0, p = offset | 0; i < size; i++, p = (p + step) | 0) {
1049
+ data[p] = channel[i];
1050
+ }
1051
+ }
1052
+ function readDataRaw(buffer, pixelData, bitDepth, step, offset) {
1053
+ if (bitDepth == 32) {
1054
+ for (let i = 0; i < buffer.byteLength; i += 4) {
1055
+ const a = buffer[i + 0];
1056
+ const b = buffer[i + 1];
1057
+ const c = buffer[i + 2];
1058
+ const d = buffer[i + 3];
1059
+ buffer[i + 0] = d;
1060
+ buffer[i + 1] = c;
1061
+ buffer[i + 2] = b;
1062
+ buffer[i + 3] = a;
1063
+ }
1064
+ }
1065
+ const array = bytesToArray(buffer, bitDepth);
1066
+ if (pixelData && offset < step) {
1067
+ copyChannelToPixelData(pixelData, array, offset, step);
1068
+ }
1069
+ }
1070
+ function decodePredicted(data, width, height, mod) {
1071
+ for (let y = 0; y < height; y++) {
1072
+ const offset = y * width;
1073
+ for (let x = 1, o = offset + 1; x < width; x++, o++) {
1074
+ data[o] = (data[o - 1] + data[o]) % mod;
1075
+ }
1076
+ }
1077
+ }
1078
+ function readDataZip(compressed, pixelData, width, height, bitDepth, step, offset, prediction) {
1079
+ const decompressed = (0, pako_1.inflate)(compressed);
1080
+ if (pixelData && offset < step) {
1081
+ const array = bytesToArray(decompressed, bitDepth);
1082
+ if (bitDepth === 8) {
1083
+ if (prediction)
1084
+ decodePredicted(decompressed, width, height, 0x100);
1085
+ copyChannelToPixelData(pixelData, decompressed, offset, step);
1086
+ }
1087
+ else if (bitDepth === 16) {
1088
+ if (prediction)
1089
+ decodePredicted(array, width, height, 0x10000);
1090
+ copyChannelToPixelData(pixelData, array, offset, step);
1091
+ }
1092
+ else if (bitDepth === 32) {
1093
+ if (prediction)
1094
+ decodePredicted(decompressed, width * 4, height, 0x100);
1095
+ let di = offset;
1096
+ const dst = new Uint32Array(pixelData.data.buffer, pixelData.data.byteOffset, pixelData.data.length);
1097
+ for (let y = 0; y < height; y++) {
1098
+ let a = width * 4 * y;
1099
+ for (let x = 0; x < width; x++, a++, di += step) {
1100
+ const b = a + width;
1101
+ const c = b + width;
1102
+ const d = c + width;
1103
+ dst[di] = ((decompressed[a] << 24) | (decompressed[b] << 16) | (decompressed[c] << 8) | decompressed[d]) >>> 0;
1104
+ }
1105
+ }
1106
+ }
1107
+ else {
1108
+ throw new Error('Invalid bitDepth');
1109
+ }
1110
+ }
1111
+ }
1112
+ function readDataRLE(reader, pixelData, width, height, _bitDepth, step, offsets, large) {
1113
+ const data = pixelData && pixelData.data;
1114
+ let lengths;
1115
+ if (large) {
1116
+ lengths = new Uint32Array(offsets.length * height);
1117
+ for (let o = 0, li = 0; o < offsets.length; o++) {
1118
+ for (let y = 0; y < height; y++, li++) {
1119
+ lengths[li] = readUint32(reader);
1120
+ }
1121
+ }
1122
+ }
1123
+ else {
1124
+ lengths = new Uint16Array(offsets.length * height);
1125
+ for (let o = 0, li = 0; o < offsets.length; o++) {
1126
+ for (let y = 0; y < height; y++, li++) {
1127
+ lengths[li] = readUint16(reader);
1128
+ }
1129
+ }
1130
+ }
1131
+ // if (bitDepth !== 1 && bitDepth !== 8) throw new Error(`Invalid bit depth (${bitDepth})`);
1132
+ const extraLimit = (step - 1) | 0; // 3 for rgb, 4 for cmyk
1133
+ for (let c = 0, li = 0; c < offsets.length; c++) {
1134
+ const offset = offsets[c] | 0;
1135
+ const extra = c > extraLimit || offset > extraLimit;
1136
+ if (!data || extra) {
1137
+ for (let y = 0; y < height; y++, li++) {
1138
+ skipBytes(reader, lengths[li]);
1139
+ }
1140
+ }
1141
+ else {
1142
+ for (let y = 0, p = offset | 0; y < height; y++, li++) {
1143
+ const length = lengths[li];
1144
+ const buffer = readBytes(reader, length);
1145
+ for (let i = 0, x = 0; i < length; i++) {
1146
+ let header = buffer[i];
1147
+ if (header > 128) {
1148
+ const value = buffer[++i];
1149
+ header = (256 - header) | 0;
1150
+ for (let j = 0; j <= header && x < width; j = (j + 1) | 0, x = (x + 1) | 0) {
1151
+ data[p] = value;
1152
+ p = (p + step) | 0;
1153
+ }
1154
+ }
1155
+ else if (header < 128) {
1156
+ for (let j = 0; j <= header && x < width; j = (j + 1) | 0, x = (x + 1) | 0) {
1157
+ data[p] = buffer[++i];
1158
+ p = (p + step) | 0;
1159
+ }
1160
+ }
1161
+ else {
1162
+ // ignore 128
1163
+ }
1164
+ // This showed up on some images from non-photoshop programs, ignoring it seems to work just fine.
1165
+ // if (i >= length) throw new Error(`Invalid RLE data: exceeded buffer size ${i}/${length}`);
1166
+ }
1167
+ }
1168
+ }
1169
+ }
1170
+ }
1171
+ function readSection(reader, round, func, skipEmpty = true, eightBytes = false) {
1172
+ let length = readUint32(reader);
1173
+ if (eightBytes) {
1174
+ if (length !== 0)
1175
+ throw new Error('Sizes larger than 4GB are not supported');
1176
+ length = readUint32(reader);
1177
+ }
1178
+ if (length <= 0 && skipEmpty)
1179
+ return undefined;
1180
+ let end = reader.offset + length;
1181
+ if (end > reader.view.byteLength)
1182
+ throw new Error('Section exceeds file size');
1183
+ const result = func(() => end - reader.offset);
1184
+ if (reader.offset !== end) {
1185
+ if (reader.offset > end) {
1186
+ warnOrThrow(reader, 'Exceeded section limits');
1187
+ }
1188
+ else {
1189
+ warnOrThrow(reader, `Unread section data`); // : ${end - reader.offset} bytes at 0x${reader.offset.toString(16)}`);
1190
+ }
1191
+ }
1192
+ while (length % round) {
1193
+ length++;
1194
+ end++;
1195
+ }
1196
+ // while (end % round) end++;
1197
+ reader.offset = end;
1198
+ return result;
1199
+ }
1200
+ function readColor(reader) {
1201
+ const colorSpace = readUint16(reader);
1202
+ switch (colorSpace) {
1203
+ case 0 /* ColorSpace.RGB */: {
1204
+ const r = readUint16(reader) / 257;
1205
+ const g = readUint16(reader) / 257;
1206
+ const b = readUint16(reader) / 257;
1207
+ skipBytes(reader, 2);
1208
+ return { r, g, b };
1209
+ }
1210
+ case 1 /* ColorSpace.HSB */: {
1211
+ const h = readUint16(reader) / 0xffff;
1212
+ const s = readUint16(reader) / 0xffff;
1213
+ const b = readUint16(reader) / 0xffff;
1214
+ skipBytes(reader, 2);
1215
+ return { h, s, b };
1216
+ }
1217
+ case 2 /* ColorSpace.CMYK */: {
1218
+ const c = readUint16(reader) / 257;
1219
+ const m = readUint16(reader) / 257;
1220
+ const y = readUint16(reader) / 257;
1221
+ const k = readUint16(reader) / 257;
1222
+ return { c, m, y, k };
1223
+ }
1224
+ case 7 /* ColorSpace.Lab */: {
1225
+ const l = readInt16(reader) / 10000;
1226
+ const ta = readInt16(reader);
1227
+ const tb = readInt16(reader);
1228
+ const a = ta < 0 ? (ta / 12800) : (ta / 12700);
1229
+ const b = tb < 0 ? (tb / 12800) : (tb / 12700);
1230
+ skipBytes(reader, 2);
1231
+ return { l, a, b };
1232
+ }
1233
+ case 8 /* ColorSpace.Grayscale */: {
1234
+ const k = readUint16(reader) * 255 / 10000;
1235
+ skipBytes(reader, 6);
1236
+ return { k };
1237
+ }
1238
+ default:
1239
+ throw new Error('Invalid color space');
1240
+ }
1241
+ }
1242
+ function readPattern(reader) {
1243
+ let length = readUint32(reader);
1244
+ while (length % 4)
1245
+ length++;
1246
+ const end = reader.offset + length;
1247
+ const version = readUint32(reader);
1248
+ if (version !== 1)
1249
+ throw new Error(`Invalid pattern version: ${version}`);
1250
+ const colorMode = readUint32(reader);
1251
+ const x = readInt16(reader);
1252
+ const y = readInt16(reader);
1253
+ // we only support RGB and grayscale for now
1254
+ if (colorMode !== 3 /* ColorMode.RGB */ && colorMode !== 1 /* ColorMode.Grayscale */ && colorMode !== 2 /* ColorMode.Indexed */) {
1255
+ throw new Error(`Unsupported pattern color mode: ${colorMode}`);
1256
+ }
1257
+ let name = readUnicodeString(reader);
1258
+ const id = readPascalString(reader, 1);
1259
+ const palette = [];
1260
+ if (colorMode === 2 /* ColorMode.Indexed */) {
1261
+ for (let i = 0; i < 256; i++) {
1262
+ palette.push({
1263
+ r: readUint8(reader),
1264
+ g: readUint8(reader),
1265
+ b: readUint8(reader),
1266
+ });
1267
+ }
1268
+ skipBytes(reader, 4); // no idea what this is
1269
+ }
1270
+ // virtual memory array list
1271
+ const version2 = readUint32(reader);
1272
+ if (version2 !== 3)
1273
+ throw new Error(`Invalid pattern VMAL version: ${version2}`);
1274
+ readUint32(reader); // length
1275
+ const top = readUint32(reader);
1276
+ const left = readUint32(reader);
1277
+ const bottom = readUint32(reader);
1278
+ const right = readUint32(reader);
1279
+ const channelsCount = readUint32(reader);
1280
+ const width = right - left;
1281
+ const height = bottom - top;
1282
+ const data = new Uint8Array(width * height * 4);
1283
+ for (let i = 3; i < data.byteLength; i += 4) {
1284
+ data[i] = 255;
1285
+ }
1286
+ for (let i = 0, ch = 0; i < (channelsCount + 2); i++) {
1287
+ const has = readUint32(reader);
1288
+ if (!has)
1289
+ continue;
1290
+ const length = readUint32(reader);
1291
+ const pixelDepth = readUint32(reader);
1292
+ const ctop = readUint32(reader);
1293
+ const cleft = readUint32(reader);
1294
+ const cbottom = readUint32(reader);
1295
+ const cright = readUint32(reader);
1296
+ const pixelDepth2 = readUint16(reader);
1297
+ const compressionMode = readUint8(reader); // 0 - raw, 1 - rle
1298
+ const dataLength = length - (4 + 16 + 2 + 1);
1299
+ const cdata = readBytes(reader, dataLength);
1300
+ if (pixelDepth !== 8 || pixelDepth2 !== 8) {
1301
+ throw new Error('16bit pixel depth not supported for patterns');
1302
+ }
1303
+ const w = cright - cleft;
1304
+ const h = cbottom - ctop;
1305
+ const ox = cleft - left;
1306
+ const oy = ctop - top;
1307
+ if (compressionMode === 0) {
1308
+ if (colorMode === 3 /* ColorMode.RGB */ && ch < 3) {
1309
+ for (let y = 0; y < h; y++) {
1310
+ for (let x = 0; x < w; x++) {
1311
+ const src = x + y * w;
1312
+ const dst = (ox + x + (y + oy) * width) * 4;
1313
+ data[dst + ch] = cdata[src];
1314
+ }
1315
+ }
1316
+ }
1317
+ else if (colorMode === 1 /* ColorMode.Grayscale */ && ch < 1) {
1318
+ for (let y = 0; y < h; y++) {
1319
+ for (let x = 0; x < w; x++) {
1320
+ const src = x + y * w;
1321
+ const dst = (ox + x + (y + oy) * width) * 4;
1322
+ const value = cdata[src];
1323
+ data[dst + 0] = value;
1324
+ data[dst + 1] = value;
1325
+ data[dst + 2] = value;
1326
+ }
1327
+ }
1328
+ }
1329
+ else if (colorMode === 2 /* ColorMode.Indexed */) {
1330
+ for (let y = 0; y < h; y++) {
1331
+ for (let x = 0; x < w; x++) {
1332
+ const src = x + y * w;
1333
+ const dst = (ox + x + (y + oy) * width) * 4;
1334
+ const index = cdata[src];
1335
+ const color = palette[index];
1336
+ data[dst + 0] = color.r;
1337
+ data[dst + 1] = color.g;
1338
+ data[dst + 2] = color.b;
1339
+ }
1340
+ }
1341
+ }
1342
+ else {
1343
+ if (reader.throwForMissingFeatures)
1344
+ throw new Error('Invalid color pattern');
1345
+ }
1346
+ }
1347
+ else if (compressionMode === 1) {
1348
+ const pixelData = { data, width, height };
1349
+ const tempData = { data: new Uint8Array(w * h), width: w, height: h };
1350
+ const cdataReader = createReader(cdata.buffer, cdata.byteOffset, cdata.byteLength);
1351
+ if (colorMode === 3 /* ColorMode.RGB */ && ch < 3) {
1352
+ readDataRLE(cdataReader, tempData, w, h, 8, 1, [0], false);
1353
+ copyChannelToRGBA(tempData, pixelData, ox, oy, ch);
1354
+ }
1355
+ if (colorMode === 1 /* ColorMode.Grayscale */ && ch < 1) {
1356
+ readDataRLE(cdataReader, tempData, w, h, 8, 1, [0], false);
1357
+ copyChannelToRGBA(tempData, pixelData, ox, oy, 0);
1358
+ setupGrayscale(pixelData);
1359
+ }
1360
+ if (colorMode === 2 /* ColorMode.Indexed */) {
1361
+ // TODO:
1362
+ throw new Error('Indexed pattern color mode not implemented');
1363
+ }
1364
+ }
1365
+ else {
1366
+ throw new Error('Invalid pattern compression mode');
1367
+ }
1368
+ ch++;
1369
+ }
1370
+ reader.offset = end;
1371
+ return { id, name, x, y, bounds: { x: left, y: top, w: width, h: height }, data };
1372
+ }
1373
+ function copyChannelToRGBA(srcData, dstData, ox, oy, offset) {
1374
+ const w = srcData.width;
1375
+ const h = srcData.height;
1376
+ const width = dstData.width;
1377
+ for (let y = 0; y < h; y++) {
1378
+ for (let x = 0; x < w; x++) {
1379
+ const src = x + y * w;
1380
+ const dst = (ox + x + (y + oy) * width) * 4;
1381
+ const value = srcData.data[src];
1382
+ dstData.data[dst + offset] = value;
1383
+ }
1384
+ }
1385
+ }
1245
1386
  //# sourceMappingURL=psdReader.js.map