ag-psd 30.2.0 → 31.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) hide show
  1. package/.v8-cache/v24.13.1-x64-cf738c9d/01e5e61b +0 -0
  2. package/.v8-cache/v24.13.1-x64-cf738c9d/05135617 +0 -0
  3. package/.v8-cache/v24.13.1-x64-cf738c9d/06423db9 +0 -0
  4. package/.v8-cache/v24.13.1-x64-cf738c9d/06e765df +0 -0
  5. package/.v8-cache/v24.13.1-x64-cf738c9d/0930679d +0 -0
  6. package/.v8-cache/v24.13.1-x64-cf738c9d/09519a62 +0 -0
  7. package/.v8-cache/v24.13.1-x64-cf738c9d/0a6607b0 +0 -0
  8. package/.v8-cache/v24.13.1-x64-cf738c9d/0ad8fa6e +0 -0
  9. package/.v8-cache/v24.13.1-x64-cf738c9d/0d390e10 +0 -0
  10. package/.v8-cache/v24.13.1-x64-cf738c9d/0dfa7b16 +0 -0
  11. package/.v8-cache/v24.13.1-x64-cf738c9d/0e9e09db +0 -0
  12. package/.v8-cache/v24.13.1-x64-cf738c9d/1130885f +0 -0
  13. package/.v8-cache/v24.13.1-x64-cf738c9d/1222cb8c +0 -0
  14. package/.v8-cache/v24.13.1-x64-cf738c9d/15e2c039 +0 -0
  15. package/.v8-cache/v24.13.1-x64-cf738c9d/1a2d469d +0 -0
  16. package/.v8-cache/v24.13.1-x64-cf738c9d/1b300c82 +0 -0
  17. package/.v8-cache/v24.13.1-x64-cf738c9d/1bc3d370 +0 -0
  18. package/.v8-cache/v24.13.1-x64-cf738c9d/1e44e5af +0 -0
  19. package/.v8-cache/v24.13.1-x64-cf738c9d/1efa10a1 +0 -0
  20. package/.v8-cache/v24.13.1-x64-cf738c9d/1f6c8743 +0 -0
  21. package/.v8-cache/v24.13.1-x64-cf738c9d/20b27e40 +0 -0
  22. package/.v8-cache/v24.13.1-x64-cf738c9d/257c62ba +0 -0
  23. package/.v8-cache/v24.13.1-x64-cf738c9d/25d60154 +0 -0
  24. package/.v8-cache/v24.13.1-x64-cf738c9d/26f822f3 +0 -0
  25. package/.v8-cache/v24.13.1-x64-cf738c9d/2a1e2a8d +0 -0
  26. package/.v8-cache/v24.13.1-x64-cf738c9d/2b02fded +0 -0
  27. package/.v8-cache/v24.13.1-x64-cf738c9d/2c76dc0d +0 -0
  28. package/.v8-cache/v24.13.1-x64-cf738c9d/2deb286a +0 -0
  29. package/.v8-cache/v24.13.1-x64-cf738c9d/32018e44 +0 -0
  30. package/.v8-cache/v24.13.1-x64-cf738c9d/341402c3 +0 -0
  31. package/.v8-cache/v24.13.1-x64-cf738c9d/34e0fa2e +0 -0
  32. package/.v8-cache/v24.13.1-x64-cf738c9d/3bbf643e +0 -0
  33. package/.v8-cache/v24.13.1-x64-cf738c9d/3ceff89e +0 -0
  34. package/.v8-cache/v24.13.1-x64-cf738c9d/404f5cdc +0 -0
  35. package/.v8-cache/v24.13.1-x64-cf738c9d/4087aa2b +0 -0
  36. package/.v8-cache/v24.13.1-x64-cf738c9d/4376c1f9 +0 -0
  37. package/.v8-cache/v24.13.1-x64-cf738c9d/44903df4 +0 -0
  38. package/.v8-cache/v24.13.1-x64-cf738c9d/44d58dc8 +0 -0
  39. package/.v8-cache/v24.13.1-x64-cf738c9d/4511bacf +0 -0
  40. package/.v8-cache/v24.13.1-x64-cf738c9d/47da0ce8 +0 -0
  41. package/.v8-cache/v24.13.1-x64-cf738c9d/48cd54a9 +0 -0
  42. package/.v8-cache/v24.13.1-x64-cf738c9d/4d938476 +0 -0
  43. package/.v8-cache/v24.13.1-x64-cf738c9d/4ec6d390 +0 -0
  44. package/.v8-cache/v24.13.1-x64-cf738c9d/4f5702bd +0 -0
  45. package/.v8-cache/v24.13.1-x64-cf738c9d/514cc428 +0 -0
  46. package/.v8-cache/v24.13.1-x64-cf738c9d/557d3b42 +0 -0
  47. package/.v8-cache/v24.13.1-x64-cf738c9d/56abbff7 +0 -0
  48. package/.v8-cache/v24.13.1-x64-cf738c9d/57b540ee +0 -0
  49. package/.v8-cache/v24.13.1-x64-cf738c9d/5e20c081 +0 -0
  50. package/.v8-cache/v24.13.1-x64-cf738c9d/651c4ada +0 -0
  51. package/.v8-cache/v24.13.1-x64-cf738c9d/652a0d59 +0 -0
  52. package/.v8-cache/v24.13.1-x64-cf738c9d/6a0e89ee +0 -0
  53. package/.v8-cache/v24.13.1-x64-cf738c9d/6af33b91 +0 -0
  54. package/.v8-cache/v24.13.1-x64-cf738c9d/6c2562d2 +0 -0
  55. package/.v8-cache/v24.13.1-x64-cf738c9d/6dae0cfa +0 -0
  56. package/.v8-cache/v24.13.1-x64-cf738c9d/6e2529ce +0 -0
  57. package/.v8-cache/v24.13.1-x64-cf738c9d/71df9cb3 +0 -0
  58. package/.v8-cache/v24.13.1-x64-cf738c9d/72e1d543 +0 -0
  59. package/.v8-cache/v24.13.1-x64-cf738c9d/75519c80 +0 -0
  60. package/.v8-cache/v24.13.1-x64-cf738c9d/79bf115c +0 -0
  61. package/.v8-cache/v24.13.1-x64-cf738c9d/7a39347c +0 -0
  62. package/.v8-cache/v24.13.1-x64-cf738c9d/7b83e3d3 +0 -0
  63. package/.v8-cache/v24.13.1-x64-cf738c9d/7cd71bc5 +0 -0
  64. package/.v8-cache/v24.13.1-x64-cf738c9d/7da78512 +0 -0
  65. package/.v8-cache/v24.13.1-x64-cf738c9d/7ea06cea +0 -0
  66. package/.v8-cache/v24.13.1-x64-cf738c9d/82c3b573 +0 -0
  67. package/.v8-cache/v24.13.1-x64-cf738c9d/84c186e4 +0 -0
  68. package/.v8-cache/v24.13.1-x64-cf738c9d/8607bd36 +0 -0
  69. package/.v8-cache/v24.13.1-x64-cf738c9d/87372817 +0 -0
  70. package/.v8-cache/v24.13.1-x64-cf738c9d/87cf2209 +0 -0
  71. package/.v8-cache/v24.13.1-x64-cf738c9d/882aaa05 +0 -0
  72. package/.v8-cache/v24.13.1-x64-cf738c9d/8a4d3de8 +0 -0
  73. package/.v8-cache/v24.13.1-x64-cf738c9d/8e223473 +0 -0
  74. package/.v8-cache/v24.13.1-x64-cf738c9d/92b7aefd +0 -0
  75. package/.v8-cache/v24.13.1-x64-cf738c9d/932f0770 +0 -0
  76. package/.v8-cache/v24.13.1-x64-cf738c9d/937c03a1 +0 -0
  77. package/.v8-cache/v24.13.1-x64-cf738c9d/991e4758 +0 -0
  78. package/.v8-cache/v24.13.1-x64-cf738c9d/9af658fb +0 -0
  79. package/.v8-cache/v24.13.1-x64-cf738c9d/9ed80ba5 +0 -0
  80. package/.v8-cache/v24.13.1-x64-cf738c9d/9f0dc993 +0 -0
  81. package/.v8-cache/v24.13.1-x64-cf738c9d/a19c0c4f +0 -0
  82. package/.v8-cache/v24.13.1-x64-cf738c9d/a6409d95 +0 -0
  83. package/.v8-cache/v24.13.1-x64-cf738c9d/a7e80865 +0 -0
  84. package/.v8-cache/v24.13.1-x64-cf738c9d/ac9802c6 +0 -0
  85. package/.v8-cache/v24.13.1-x64-cf738c9d/acc36e66 +0 -0
  86. package/.v8-cache/v24.13.1-x64-cf738c9d/ad11e2dc +0 -0
  87. package/.v8-cache/v24.13.1-x64-cf738c9d/b0c8fcd8 +0 -0
  88. package/.v8-cache/v24.13.1-x64-cf738c9d/b1762958 +0 -0
  89. package/.v8-cache/v24.13.1-x64-cf738c9d/b3c2fab7 +0 -0
  90. package/.v8-cache/v24.13.1-x64-cf738c9d/b5b3329b +0 -0
  91. package/.v8-cache/v24.13.1-x64-cf738c9d/b806679e +0 -0
  92. package/.v8-cache/v24.13.1-x64-cf738c9d/bc1cdd48 +0 -0
  93. package/.v8-cache/v24.13.1-x64-cf738c9d/bc7ebd1d +0 -0
  94. package/.v8-cache/v24.13.1-x64-cf738c9d/c0b789d2 +0 -0
  95. package/.v8-cache/v24.13.1-x64-cf738c9d/c314aece +0 -0
  96. package/.v8-cache/v24.13.1-x64-cf738c9d/c399a5dc +0 -0
  97. package/.v8-cache/v24.13.1-x64-cf738c9d/c681cbc8 +0 -0
  98. package/.v8-cache/v24.13.1-x64-cf738c9d/c6834ffc +0 -0
  99. package/.v8-cache/v24.13.1-x64-cf738c9d/c6f12ed5 +0 -0
  100. package/.v8-cache/v24.13.1-x64-cf738c9d/cb0f0a3d +0 -0
  101. package/.v8-cache/v24.13.1-x64-cf738c9d/cbcb7c95 +0 -0
  102. package/.v8-cache/v24.13.1-x64-cf738c9d/cdd9107c +0 -0
  103. package/.v8-cache/v24.13.1-x64-cf738c9d/cdf2c4a3 +0 -0
  104. package/.v8-cache/v24.13.1-x64-cf738c9d/cfc49f4f +0 -0
  105. package/.v8-cache/v24.13.1-x64-cf738c9d/cff9434a +0 -0
  106. package/.v8-cache/v24.13.1-x64-cf738c9d/d02dd6f7 +0 -0
  107. package/.v8-cache/v24.13.1-x64-cf738c9d/d0507bf3 +0 -0
  108. package/.v8-cache/v24.13.1-x64-cf738c9d/d60fce19 +0 -0
  109. package/.v8-cache/v24.13.1-x64-cf738c9d/d733d619 +0 -0
  110. package/.v8-cache/v24.13.1-x64-cf738c9d/d75b7803 +0 -0
  111. package/.v8-cache/v24.13.1-x64-cf738c9d/dc86f000 +0 -0
  112. package/.v8-cache/v24.13.1-x64-cf738c9d/defa4f7f +0 -0
  113. package/.v8-cache/v24.13.1-x64-cf738c9d/e03e2acd +0 -0
  114. package/.v8-cache/v24.13.1-x64-cf738c9d/e0e3f52c +0 -0
  115. package/.v8-cache/v24.13.1-x64-cf738c9d/e158d332 +0 -0
  116. package/.v8-cache/v24.13.1-x64-cf738c9d/e6735171 +0 -0
  117. package/.v8-cache/v24.13.1-x64-cf738c9d/e6745c2b +0 -0
  118. package/.v8-cache/v24.13.1-x64-cf738c9d/e6b99945 +0 -0
  119. package/.v8-cache/v24.13.1-x64-cf738c9d/e6d8ceb8 +0 -0
  120. package/.v8-cache/v24.13.1-x64-cf738c9d/e7ffec37 +0 -0
  121. package/.v8-cache/v24.13.1-x64-cf738c9d/ea33b6de +0 -0
  122. package/.v8-cache/v24.13.1-x64-cf738c9d/eaafa3c4 +0 -0
  123. package/.v8-cache/v24.13.1-x64-cf738c9d/ebb50fca +0 -0
  124. package/.v8-cache/v24.13.1-x64-cf738c9d/ec805f2e +0 -0
  125. package/.v8-cache/v24.13.1-x64-cf738c9d/edaef8f1 +0 -0
  126. package/.v8-cache/v24.13.1-x64-cf738c9d/ee4401c8 +0 -0
  127. package/.v8-cache/v24.13.1-x64-cf738c9d/eeeebdfe +0 -0
  128. package/.v8-cache/v24.13.1-x64-cf738c9d/f3d51676 +0 -0
  129. package/.v8-cache/v24.13.1-x64-cf738c9d/f7b50a75 +0 -0
  130. package/.v8-cache/v24.13.1-x64-cf738c9d/fa58ca72 +0 -0
  131. package/.v8-cache/v24.13.1-x64-cf738c9d/fc97d72d +0 -0
  132. package/.v8-cache/v24.13.1-x64-cf738c9d/fd0a2987 +0 -0
  133. package/CHANGELOG.md +6 -0
  134. package/README.md +64 -0
  135. package/TODO.md +2 -0
  136. package/dist/abr.d.ts +196 -196
  137. package/dist/abr.js +364 -365
  138. package/dist/abr.js.map +1 -1
  139. package/dist/additionalInfo.d.ts +26 -26
  140. package/dist/additionalInfo.js +3478 -3478
  141. package/dist/additionalInfo.js.map +1 -1
  142. package/dist/ase.d.ts +32 -32
  143. package/dist/ase.js +81 -82
  144. package/dist/ase.js.map +1 -1
  145. package/dist/bundle.js +12380 -12259
  146. package/dist/csh.d.ts +10 -10
  147. package/dist/csh.js +35 -36
  148. package/dist/csh.js.map +1 -1
  149. package/dist/descriptor.d.ts +601 -601
  150. package/dist/descriptor.js +2003 -2003
  151. package/dist/descriptor.js.map +1 -1
  152. package/dist/effectsHelpers.d.ts +5 -5
  153. package/dist/effectsHelpers.js +286 -287
  154. package/dist/effectsHelpers.js.map +1 -1
  155. package/dist/engineData.d.ts +2 -2
  156. package/dist/engineData.js +334 -335
  157. package/dist/engineData.js.map +1 -1
  158. package/dist/engineData2.d.ts +2 -2
  159. package/dist/engineData2.js +409 -410
  160. package/dist/engineData2.js.map +1 -1
  161. package/dist/helpers.d.ts +74 -74
  162. package/dist/helpers.js +353 -342
  163. package/dist/helpers.js.map +1 -1
  164. package/dist/imageResources.d.ts +17 -17
  165. package/dist/imageResources.js +1040 -1040
  166. package/dist/imageResources.js.map +1 -1
  167. package/dist/index.d.ts +20 -22
  168. package/dist/index.js +61 -56
  169. package/dist/index.js.map +1 -1
  170. package/dist/initializeCanvas.d.ts +1 -1
  171. package/dist/initializeCanvas.js +9 -10
  172. package/dist/initializeCanvas.js.map +1 -1
  173. package/dist/jpeg.d.ts +1 -1
  174. package/dist/jpeg.js +1020 -1021
  175. package/dist/jpeg.js.map +1 -1
  176. package/dist/psd.d.ts +1877 -1873
  177. package/dist/psd.js +45 -45
  178. package/dist/psd.js.map +1 -1
  179. package/dist/psdReader.d.ts +52 -45
  180. package/dist/psdReader.js +1385 -1282
  181. package/dist/psdReader.js.map +1 -1
  182. package/dist/psdWriter.d.ts +34 -34
  183. package/dist/psdWriter.js +834 -824
  184. package/dist/psdWriter.js.map +1 -1
  185. package/dist/text.d.ts +179 -179
  186. package/dist/text.js +552 -553
  187. package/dist/text.js.map +1 -1
  188. package/dist/utf8.d.ts +4 -6
  189. package/dist/utf8.js +156 -157
  190. package/dist/utf8.js.map +1 -1
  191. package/dist-es/abr.d.ts +196 -196
  192. package/dist-es/abr.js +364 -361
  193. package/dist-es/abr.js.map +1 -1
  194. package/dist-es/additionalInfo.d.ts +26 -26
  195. package/dist-es/additionalInfo.js +3478 -3472
  196. package/dist-es/additionalInfo.js.map +1 -1
  197. package/dist-es/ase.d.ts +32 -32
  198. package/dist-es/ase.js +81 -78
  199. package/dist-es/ase.js.map +1 -1
  200. package/dist-es/csh.d.ts +10 -10
  201. package/dist-es/csh.js +35 -32
  202. package/dist-es/csh.js.map +1 -1
  203. package/dist-es/descriptor.d.ts +601 -601
  204. package/dist-es/descriptor.js +2003 -1970
  205. package/dist-es/descriptor.js.map +1 -1
  206. package/dist-es/effectsHelpers.d.ts +5 -5
  207. package/dist-es/effectsHelpers.js +286 -282
  208. package/dist-es/effectsHelpers.js.map +1 -1
  209. package/dist-es/engineData.d.ts +2 -2
  210. package/dist-es/engineData.js +334 -330
  211. package/dist-es/engineData.js.map +1 -1
  212. package/dist-es/engineData2.d.ts +2 -2
  213. package/dist-es/engineData2.js +409 -406
  214. package/dist-es/engineData2.js.map +1 -1
  215. package/dist-es/helpers.d.ts +74 -74
  216. package/dist-es/helpers.js +353 -324
  217. package/dist-es/helpers.js.map +1 -1
  218. package/dist-es/imageResources.d.ts +17 -17
  219. package/dist-es/imageResources.js +1040 -1037
  220. package/dist-es/imageResources.js.map +1 -1
  221. package/dist-es/index.d.ts +20 -22
  222. package/dist-es/index.js +61 -33
  223. package/dist-es/index.js.map +1 -1
  224. package/dist-es/initializeCanvas.d.ts +1 -1
  225. package/dist-es/initializeCanvas.js +9 -6
  226. package/dist-es/initializeCanvas.js.map +1 -1
  227. package/dist-es/jpeg.d.ts +1 -1
  228. package/dist-es/jpeg.js +1020 -1017
  229. package/dist-es/jpeg.js.map +1 -1
  230. package/dist-es/psd.d.ts +1877 -1873
  231. package/dist-es/psd.js +45 -42
  232. package/dist-es/psd.js.map +1 -1
  233. package/dist-es/psdReader.d.ts +52 -45
  234. package/dist-es/psdReader.js +1385 -1244
  235. package/dist-es/psdReader.js.map +1 -1
  236. package/dist-es/psdWriter.d.ts +34 -34
  237. package/dist-es/psdWriter.js +834 -794
  238. package/dist-es/psdWriter.js.map +1 -1
  239. package/dist-es/text.d.ts +179 -179
  240. package/dist-es/text.js +552 -548
  241. package/dist-es/text.js.map +1 -1
  242. package/dist-es/utf8.d.ts +4 -6
  243. package/dist-es/utf8.js +156 -150
  244. package/dist-es/utf8.js.map +1 -1
  245. package/package.json +4 -3
  246. package/src/helpers.ts +13 -3
  247. package/src/index.ts +4 -6
  248. package/src/psd.ts +4 -0
  249. package/src/psdReader.ts +136 -43
  250. package/src/psdWriter.ts +42 -23
  251. package/tsconfig-es6.json +2 -1
  252. package/tsconfig.json +1 -0
@@ -1,795 +1,835 @@
1
- import { hasAlpha, createCanvas, writeDataRLE, offsetForChannel, createImageData, fromBlendMode, clamp, largeAdditionalInfoKeys, RAW_IMAGE_DATA, writeDataZipWithoutPrediction, imageDataToCanvas } from './helpers';
2
- import { infoHandlers } from './additionalInfo';
3
- import { resourceHandlers } from './imageResources';
4
- export function createWriter(size = 4096) {
5
- const buffer = new ArrayBuffer(size);
6
- const view = new DataView(buffer);
7
- const offset = 0;
8
- return { buffer, view, offset, tempBuffer: undefined };
9
- }
10
- export function getWriterBuffer(writer) {
11
- return writer.buffer.slice(0, writer.offset);
12
- }
13
- export function getWriterBufferNoCopy(writer) {
14
- return new Uint8Array(writer.buffer, 0, writer.offset);
15
- }
16
- export function writeUint8(writer, value) {
17
- const offset = addSize(writer, 1);
18
- writer.view.setUint8(offset, value);
19
- }
20
- export function writeInt16(writer, value) {
21
- const offset = addSize(writer, 2);
22
- writer.view.setInt16(offset, value, false);
23
- }
24
- export function writeUint16(writer, value) {
25
- const offset = addSize(writer, 2);
26
- writer.view.setUint16(offset, value, false);
27
- }
28
- export function writeUint16LE(writer, value) {
29
- const offset = addSize(writer, 2);
30
- writer.view.setUint16(offset, value, true);
31
- }
32
- export function writeInt32(writer, value) {
33
- const offset = addSize(writer, 4);
34
- writer.view.setInt32(offset, value, false);
35
- }
36
- export function writeInt32LE(writer, value) {
37
- const offset = addSize(writer, 4);
38
- writer.view.setInt32(offset, value, true);
39
- }
40
- export function writeUint32(writer, value) {
41
- const offset = addSize(writer, 4);
42
- writer.view.setUint32(offset, value, false);
43
- }
44
- export function writeFloat32(writer, value) {
45
- const offset = addSize(writer, 4);
46
- writer.view.setFloat32(offset, value, false);
47
- }
48
- export function writeFloat64(writer, value) {
49
- const offset = addSize(writer, 8);
50
- writer.view.setFloat64(offset, value, false);
51
- }
52
- // 32-bit fixed-point number 16.16
53
- export function writeFixedPoint32(writer, value) {
54
- writeInt32(writer, value * (1 << 16));
55
- }
56
- // 32-bit fixed-point number 8.24
57
- export function writeFixedPointPath32(writer, value) {
58
- writeInt32(writer, value * (1 << 24));
59
- }
60
- export function writeBytes(writer, buffer) {
61
- if (buffer) {
62
- ensureSize(writer, writer.offset + buffer.length);
63
- const bytes = new Uint8Array(writer.buffer);
64
- bytes.set(buffer, writer.offset);
65
- writer.offset += buffer.length;
66
- }
67
- }
68
- export function writeZeros(writer, count) {
69
- for (let i = 0; i < count; i++) {
70
- writeUint8(writer, 0);
71
- }
72
- }
73
- export function writeSignature(writer, signature) {
74
- if (signature.length !== 4)
75
- throw new Error(`Invalid signature: '${signature}'`);
76
- for (let i = 0; i < 4; i++) {
77
- writeUint8(writer, signature.charCodeAt(i));
78
- }
79
- }
80
- export function writeAsciiString(writer, text) {
81
- for (let i = 0; i < text.length; i++) {
82
- writeUint8(writer, text.charCodeAt(i));
83
- }
84
- }
85
- export function writePascalString(writer, text, padTo) {
86
- let length = text.length;
87
- if (length > 255)
88
- throw new Error(`String too long`);
89
- writeUint8(writer, length);
90
- for (let i = 0; i < length; i++) {
91
- const code = text.charCodeAt(i);
92
- // writeUint8(writer, code); // for testing
93
- writeUint8(writer, code < 128 ? code : '?'.charCodeAt(0));
94
- }
95
- while (++length % padTo) {
96
- writeUint8(writer, 0);
97
- }
98
- }
99
- export function writeUnicodeStringWithoutLength(writer, text) {
100
- for (let i = 0; i < text.length; i++) {
101
- writeUint16(writer, text.charCodeAt(i));
102
- }
103
- }
104
- export function writeUnicodeStringWithoutLengthLE(writer, text) {
105
- for (let i = 0; i < text.length; i++) {
106
- writeUint16LE(writer, text.charCodeAt(i));
107
- }
108
- }
109
- export function writeUnicodeString(writer, text) {
110
- writeUint32(writer, text.length);
111
- writeUnicodeStringWithoutLength(writer, text);
112
- }
113
- export function writeUnicodeStringWithPadding(writer, text) {
114
- writeUint32(writer, text.length + 1);
115
- for (let i = 0; i < text.length; i++) {
116
- writeUint16(writer, text.charCodeAt(i));
117
- }
118
- writeUint16(writer, 0);
119
- }
120
- function getLargestLayerSize(layers = []) {
121
- let max = 0;
122
- for (const layer of layers) {
123
- if (layer.canvas || layer.imageData) {
124
- const { width, height } = getLayerDimentions(layer);
125
- max = Math.max(max, 2 * height + 2 * width * height);
126
- }
127
- if (layer.children) {
128
- max = Math.max(max, getLargestLayerSize(layer.children));
129
- }
130
- }
131
- return max;
132
- }
133
- export function writeSection(writer, round, func, writeTotalLength = false, large = false) {
134
- if (large)
135
- writeUint32(writer, 0);
136
- const offset = writer.offset;
137
- writeUint32(writer, 0);
138
- func();
139
- let length = writer.offset - offset - 4;
140
- let len = length;
141
- while (len % round) {
142
- writeUint8(writer, 0);
143
- len++;
144
- }
145
- // while (writer.offset % round) {
146
- // writeUint8(writer, 0);
147
- // len++;
148
- // }
149
- if (writeTotalLength) {
150
- length = len;
151
- }
152
- writer.view.setUint32(offset, length, false);
153
- }
154
- function verifyBitCount(target) {
155
- var _a;
156
- (_a = target.children) === null || _a === void 0 ? void 0 : _a.forEach(verifyBitCount);
157
- const data = target.imageData;
158
- if (data && (data.data instanceof Uint32Array || data.data instanceof Uint16Array)) {
159
- throw new Error('imageData has incorrect bitDepth');
160
- }
161
- if ('mask' in target && target.mask) {
162
- const data = target.mask.imageData;
163
- if (data && (data.data instanceof Uint32Array || data.data instanceof Uint16Array)) {
164
- throw new Error('mask imageData has incorrect bitDepth');
165
- }
166
- }
167
- }
168
- export function writePsd(writer, psd, options = {}) {
169
- var _a;
170
- if (!(+psd.width > 0 && +psd.height > 0))
171
- throw new Error('Invalid document size');
172
- if ((psd.width > 30000 || psd.height > 30000) && !options.psb)
173
- throw new Error('Document size is too large (max is 30000x30000, use PSB format instead)');
174
- const bitsPerChannel = (_a = psd.bitsPerChannel) !== null && _a !== void 0 ? _a : 8;
175
- if (bitsPerChannel !== 8)
176
- throw new Error('bitsPerChannel other than 8 are not supported for writing');
177
- verifyBitCount(psd);
178
- const imageResources = Object.assign({}, psd.imageResources);
179
- const opt = Object.assign(Object.assign({}, options), { layerIds: new Set(), layerToId: new Map() });
180
- if (opt.generateThumbnail) {
181
- imageResources.thumbnail = createThumbnail(psd);
182
- }
183
- let imageData = psd.imageData;
184
- if (!imageData && psd.canvas) {
185
- imageData = psd.canvas.getContext('2d').getImageData(0, 0, psd.canvas.width, psd.canvas.height);
186
- }
187
- if (imageData && (psd.width !== imageData.width || psd.height !== imageData.height))
188
- throw new Error('Document canvas must have the same size as document');
189
- const globalAlpha = !!imageData && hasAlpha(imageData);
190
- const maxBufferSize = Math.max(getLargestLayerSize(psd.children), 4 * 2 * psd.width * psd.height + 2 * psd.height);
191
- writer.tempBuffer = new Uint8Array(maxBufferSize);
192
- // header
193
- writeSignature(writer, '8BPS');
194
- writeUint16(writer, options.psb ? 2 : 1); // version
195
- writeZeros(writer, 6);
196
- writeUint16(writer, globalAlpha ? 4 : 3); // channels
197
- writeUint32(writer, psd.height);
198
- writeUint32(writer, psd.width);
199
- writeUint16(writer, bitsPerChannel); // bits per channel
200
- writeUint16(writer, 3 /* ColorMode.RGB */); // we only support saving RGB right now
201
- // color mode data
202
- writeSection(writer, 1, () => {
203
- var _a, _b, _c;
204
- if (psd.palette) {
205
- for (let i = 0; i < 256; i++)
206
- writeUint8(writer, ((_a = psd.palette[i]) === null || _a === void 0 ? void 0 : _a.r) || 0);
207
- for (let i = 0; i < 256; i++)
208
- writeUint8(writer, ((_b = psd.palette[i]) === null || _b === void 0 ? void 0 : _b.g) || 0);
209
- for (let i = 0; i < 256; i++)
210
- writeUint8(writer, ((_c = psd.palette[i]) === null || _c === void 0 ? void 0 : _c.b) || 0);
211
- }
212
- // TODO: other data?
213
- });
214
- const layers = [];
215
- addChildren(layers, psd.children);
216
- if (!layers.length)
217
- layers.push({});
218
- // image resources
219
- imageResources.layersGroup = layers.map(l => l.linkGroup || 0);
220
- imageResources.layerGroupsEnabledId = layers.map(l => l.linkGroupEnabled == false ? 0 : 1);
221
- writeSection(writer, 1, () => {
222
- for (const handler of resourceHandlers) {
223
- const has = handler.has(imageResources);
224
- const count = has === false ? 0 : (has === true ? 1 : has);
225
- for (let i = 0; i < count; i++) {
226
- writeSignature(writer, '8BIM');
227
- writeUint16(writer, handler.key);
228
- writePascalString(writer, '', 2);
229
- writeSection(writer, 2, () => handler.write(writer, imageResources, i));
230
- }
231
- }
232
- });
233
- // layer and mask info
234
- writeSection(writer, 2, () => {
235
- writeLayerInfo(writer, layers, psd, globalAlpha, opt);
236
- writeGlobalLayerMaskInfo(writer, psd.globalLayerMaskInfo);
237
- writeAdditionalLayerInfo(writer, psd, psd, opt);
238
- }, undefined, !!opt.psb);
239
- // image data
240
- const channels = globalAlpha ? [0, 1, 2, 3] : [0, 1, 2];
241
- const width = imageData ? imageData.width : psd.width;
242
- const height = imageData ? imageData.height : psd.height;
243
- const data = { data: new Uint8Array(width * height * 4), width, height };
244
- writeUint16(writer, 1 /* Compression.RleCompressed */); // Photoshop doesn't support zip compression of composite image data
245
- if (RAW_IMAGE_DATA && psd.imageDataRaw) {
246
- console.log('writing raw image data');
247
- writeBytes(writer, psd.imageDataRaw);
248
- }
249
- else {
250
- if (imageData)
251
- data.data.set(new Uint8Array(imageData.data.buffer, imageData.data.byteOffset, imageData.data.byteLength));
252
- // add weird white matte
253
- if (globalAlpha) {
254
- const size = data.width * data.height * 4;
255
- const p = data.data;
256
- for (let i = 0; i < size; i += 4) {
257
- const pa = p[i + 3];
258
- if (pa != 0 && pa != 255) {
259
- const a = pa / 255;
260
- const ra = 255 * (1 - a);
261
- p[i + 0] = p[i + 0] * a + ra;
262
- p[i + 1] = p[i + 1] * a + ra;
263
- p[i + 2] = p[i + 2] * a + ra;
264
- }
265
- }
266
- }
267
- writeBytes(writer, writeDataRLE(writer.tempBuffer, data, channels, !!options.psb));
268
- }
269
- }
270
- function writeLayerInfo(writer, layers, psd, globalAlpha, options) {
271
- writeSection(writer, 4, () => {
272
- var _a;
273
- writeInt16(writer, globalAlpha ? -layers.length : layers.length);
274
- const layersData = layers.map((l, i) => getChannels(writer.tempBuffer, l, i === 0, options));
275
- // layer records
276
- for (const layerData of layersData) {
277
- const { layer, top, left, bottom, right, channels } = layerData;
278
- writeInt32(writer, top);
279
- writeInt32(writer, left);
280
- writeInt32(writer, bottom);
281
- writeInt32(writer, right);
282
- writeUint16(writer, channels.length);
283
- for (const c of channels) {
284
- writeInt16(writer, c.channelId);
285
- if (options.psb)
286
- writeUint32(writer, 0);
287
- writeUint32(writer, c.length);
288
- }
289
- writeSignature(writer, '8BIM');
290
- writeSignature(writer, fromBlendMode[layer.blendMode] || 'norm');
291
- writeUint8(writer, Math.round(clamp((_a = layer.opacity) !== null && _a !== void 0 ? _a : 1, 0, 1) * 255));
292
- writeUint8(writer, layer.clipping ? 1 : 0);
293
- let flags = 0x08; // 1 for Photoshop 5.0 and later, tells if bit 4 has useful information
294
- if (layer.transparencyProtected)
295
- flags |= 0x01;
296
- if (layer.hidden)
297
- flags |= 0x02;
298
- if (layer.vectorMask || (layer.sectionDivider && layer.sectionDivider.type !== 0 /* SectionDividerType.Other */) || layer.adjustment) {
299
- flags |= 0x10; // pixel data irrelevant to appearance of document
300
- }
301
- if (layer.effectsOpen)
302
- flags |= 0x20;
303
- writeUint8(writer, flags);
304
- writeUint8(writer, 0); // filler
305
- writeSection(writer, 1, () => {
306
- writeLayerMaskData(writer, layer, layerData);
307
- writeLayerBlendingRanges(writer, layer);
308
- writePascalString(writer, (layer.name || '').substring(0, 255), 4);
309
- writeAdditionalLayerInfo(writer, layer, psd, options);
310
- });
311
- }
312
- // layer channel image data
313
- for (const layerData of layersData) {
314
- for (const channel of layerData.channels) {
315
- writeUint16(writer, channel.compression);
316
- if (channel.buffer) {
317
- writeBytes(writer, channel.buffer);
318
- }
319
- }
320
- }
321
- }, true, options.psb);
322
- }
323
- function writeLayerMaskData(writer, { mask, realMask }, layerData) {
324
- writeSection(writer, 1, () => {
325
- if (!mask && !realMask)
326
- return;
327
- let params = 0, flags = 0, realFlags = 0;
328
- if (mask) {
329
- if (mask.userMaskDensity !== undefined)
330
- params |= 1 /* MaskParams.UserMaskDensity */;
331
- if (mask.userMaskFeather !== undefined)
332
- params |= 2 /* MaskParams.UserMaskFeather */;
333
- if (mask.vectorMaskDensity !== undefined)
334
- params |= 4 /* MaskParams.VectorMaskDensity */;
335
- if (mask.vectorMaskFeather !== undefined)
336
- params |= 8 /* MaskParams.VectorMaskFeather */;
337
- if (mask.disabled)
338
- flags |= 2 /* LayerMaskFlags.LayerMaskDisabled */;
339
- if (mask.positionRelativeToLayer)
340
- flags |= 1 /* LayerMaskFlags.PositionRelativeToLayer */;
341
- if (mask.fromVectorData)
342
- flags |= 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */;
343
- if (params)
344
- flags |= 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */;
345
- }
346
- const m = layerData.mask || {};
347
- writeInt32(writer, m.top || 0);
348
- writeInt32(writer, m.left || 0);
349
- writeInt32(writer, m.bottom || 0);
350
- writeInt32(writer, m.right || 0);
351
- writeUint8(writer, mask && mask.defaultColor || 0);
352
- writeUint8(writer, flags);
353
- if (realMask) {
354
- if (realMask.disabled)
355
- realFlags |= 2 /* LayerMaskFlags.LayerMaskDisabled */;
356
- if (realMask.positionRelativeToLayer)
357
- realFlags |= 1 /* LayerMaskFlags.PositionRelativeToLayer */;
358
- if (realMask.fromVectorData)
359
- realFlags |= 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */;
360
- const r = layerData.realMask || {};
361
- writeUint8(writer, realFlags);
362
- writeUint8(writer, realMask.defaultColor || 0);
363
- writeInt32(writer, r.top || 0);
364
- writeInt32(writer, r.left || 0);
365
- writeInt32(writer, r.bottom || 0);
366
- writeInt32(writer, r.right || 0);
367
- }
368
- if (params && mask) {
369
- writeUint8(writer, params);
370
- if (mask.userMaskDensity !== undefined)
371
- writeUint8(writer, Math.round(mask.userMaskDensity * 0xff));
372
- if (mask.userMaskFeather !== undefined)
373
- writeFloat64(writer, mask.userMaskFeather);
374
- if (mask.vectorMaskDensity !== undefined)
375
- writeUint8(writer, Math.round(mask.vectorMaskDensity * 0xff));
376
- if (mask.vectorMaskFeather !== undefined)
377
- writeFloat64(writer, mask.vectorMaskFeather);
378
- }
379
- writeZeros(writer, 2);
380
- });
381
- }
382
- function writerBlendingRange(writer, range) {
383
- writeUint8(writer, range[0]);
384
- writeUint8(writer, range[1]);
385
- writeUint8(writer, range[2]);
386
- writeUint8(writer, range[3]);
387
- }
388
- function writeLayerBlendingRanges(writer, layer) {
389
- writeSection(writer, 1, () => {
390
- const ranges = layer.blendingRanges;
391
- if (ranges) {
392
- writerBlendingRange(writer, ranges.compositeGrayBlendSource);
393
- writerBlendingRange(writer, ranges.compositeGraphBlendDestinationRange);
394
- for (const r of ranges.ranges) {
395
- writerBlendingRange(writer, r.sourceRange);
396
- writerBlendingRange(writer, r.destRange);
397
- }
398
- }
399
- });
400
- }
401
- function writeGlobalLayerMaskInfo(writer, info) {
402
- writeSection(writer, 1, () => {
403
- if (info) {
404
- writeUint16(writer, info.overlayColorSpace);
405
- writeUint16(writer, info.colorSpace1);
406
- writeUint16(writer, info.colorSpace2);
407
- writeUint16(writer, info.colorSpace3);
408
- writeUint16(writer, info.colorSpace4);
409
- writeUint16(writer, info.opacity * 0xff);
410
- writeUint8(writer, info.kind);
411
- writeZeros(writer, 3);
412
- }
413
- });
414
- }
415
- function writeAdditionalLayerInfo(writer, target, psd, options) {
416
- for (const handler of infoHandlers) {
417
- let key = handler.key;
418
- if (key === 'Txt2' && options.invalidateTextLayers)
419
- continue;
420
- if (key === 'vmsk' && options.psb)
421
- key = 'vsms';
422
- if (handler.has(target)) {
423
- const large = options.psb && largeAdditionalInfoKeys.indexOf(key) !== -1;
424
- const writeTotalLength = key !== 'Txt2' && key !== 'cinf' && key !== 'extn' && key !== 'CAI ' && key !== 'OCIO';
425
- const fourBytes = key === 'Txt2' || key === 'luni' || key === 'vmsk' || key === 'artb' || key === 'artd' ||
426
- key === 'vogk' || key === 'SoLd' || key === 'lnk2' || key === 'vscg' || key === 'vsms' || key === 'GdFl' ||
427
- key === 'lmfx' || key === 'lrFX' || key === 'cinf' || key === 'PlLd' || key === 'Anno' || key === 'CAI ' || key === 'OCIO' || key === 'GenI' || key === 'FEid' || key === 'curv' || key === 'CgEd' || key === 'vibA' || key === 'blwh' || key === 'grdm';
428
- writeSignature(writer, large ? '8B64' : '8BIM');
429
- writeSignature(writer, key);
430
- writeSection(writer, fourBytes ? 4 : 2, () => {
431
- handler.write(writer, target, psd, options);
432
- }, writeTotalLength, large);
433
- }
434
- }
435
- }
436
- function addChildren(layers, children) {
437
- if (!children)
438
- return;
439
- // const layerIds: number[] = [2];
440
- // const timestamps: number[] = [1740120767.0230637];
441
- for (const c of children) {
442
- if (c.children && c.canvas)
443
- throw new Error(`Invalid layer, cannot have both 'canvas' and 'children' properties`);
444
- if (c.children && c.imageData)
445
- throw new Error(`Invalid layer, cannot have both 'imageData' and 'children' properties`);
446
- if (c.children) {
447
- layers.push({
448
- name: '</Layer group>',
449
- sectionDivider: {
450
- type: 3 /* SectionDividerType.BoundingSectionDivider */,
451
- },
452
- // blendingRanges: children[0].blendingRanges,
453
- // nameSource: 'lset',
454
- // id: layerIds.shift(),
455
- // protected: {
456
- // transparency: false,
457
- // composite: false,
458
- // position: false,
459
- // },
460
- // layerColor: 'red',
461
- // timestamp: timestamps.shift(),
462
- // referencePoint: { x: 0, y: 0 },
463
- });
464
- addChildren(layers, c.children);
465
- layers.push(Object.assign(Object.assign({}, c), { blendMode: c.blendMode === 'pass through' ? 'normal' : c.blendMode, sectionDivider: {
466
- type: c.opened === false ? 2 /* SectionDividerType.ClosedFolder */ : 1 /* SectionDividerType.OpenFolder */,
467
- key: fromBlendMode[c.blendMode] || 'pass',
468
- subType: 0,
469
- } }));
470
- }
471
- else {
472
- layers.push(Object.assign({}, c));
473
- }
474
- }
475
- }
476
- function resizeBuffer(writer, size) {
477
- let newLength = writer.buffer.byteLength;
478
- do {
479
- newLength *= 2;
480
- } while (size > newLength);
481
- const newBuffer = new ArrayBuffer(newLength);
482
- const newBytes = new Uint8Array(newBuffer);
483
- const oldBytes = new Uint8Array(writer.buffer);
484
- newBytes.set(oldBytes);
485
- writer.buffer = newBuffer;
486
- writer.view = new DataView(writer.buffer);
487
- }
488
- function ensureSize(writer, size) {
489
- if (size > writer.buffer.byteLength) {
490
- resizeBuffer(writer, size);
491
- }
492
- }
493
- function addSize(writer, size) {
494
- const offset = writer.offset;
495
- ensureSize(writer, writer.offset += size);
496
- return offset;
497
- }
498
- function createThumbnail(psd) {
499
- const canvas = createCanvas(10, 10);
500
- let scale = 1;
501
- if (psd.width > psd.height) {
502
- canvas.width = 160;
503
- canvas.height = Math.floor(psd.height * (canvas.width / psd.width));
504
- scale = canvas.width / psd.width;
505
- }
506
- else {
507
- canvas.height = 160;
508
- canvas.width = Math.floor(psd.width * (canvas.height / psd.height));
509
- scale = canvas.height / psd.height;
510
- }
511
- const context = canvas.getContext('2d');
512
- context.scale(scale, scale);
513
- if (psd.imageData) {
514
- context.drawImage(imageDataToCanvas(psd.imageData), 0, 0);
515
- }
516
- else if (psd.canvas) {
517
- context.drawImage(psd.canvas, 0, 0);
518
- }
519
- return canvas;
520
- }
521
- function getMaskChannels(tempBuffer, layerData, layer, mask, options, realMask) {
522
- let top = mask.top | 0;
523
- let left = mask.left | 0;
524
- let right = mask.right | 0;
525
- let bottom = mask.bottom | 0;
526
- let { width, height } = getLayerDimentions(mask);
527
- let imageData = mask.imageData;
528
- if (!imageData && mask.canvas && width && height) {
529
- imageData = mask.canvas.getContext('2d').getImageData(0, 0, width, height);
530
- }
531
- if (imageData && (imageData.width !== width || imageData.height !== height)) {
532
- throw new Error('Invalid imageData dimentions');
533
- }
534
- right = left + width;
535
- bottom = top + height;
536
- let buffer;
537
- let compression;
538
- if (RAW_IMAGE_DATA && layer[realMask ? 'realMaskDataRaw' : 'maskDataRaw']) {
539
- buffer = layer[realMask ? 'realMaskDataRaw' : 'maskDataRaw'];
540
- compression = layer[realMask ? 'realMaskDataRawCompression' : 'maskDataRawCompression'];
541
- }
542
- else if (!imageData) {
543
- buffer = new Uint8Array(0);
544
- compression = 1 /* Compression.RleCompressed */;
545
- }
546
- else if (options.compress) {
547
- buffer = writeDataZipWithoutPrediction(imageData, [0]);
548
- compression = 2 /* Compression.ZipWithoutPrediction */;
549
- }
550
- else {
551
- buffer = writeDataRLE(tempBuffer, imageData, [0], !!options.psb);
552
- compression = 1 /* Compression.RleCompressed */;
553
- }
554
- layerData.channels.push({ channelId: realMask ? -3 /* ChannelID.RealUserMask */ : -2 /* ChannelID.UserMask */, compression, buffer, length: 2 + buffer.length });
555
- layerData[realMask ? 'realMask' : 'mask'] = { top, left, right, bottom };
556
- }
557
- function getChannels(tempBuffer, layer, background, options) {
558
- const layerData = getLayerChannels(tempBuffer, layer, background, options);
559
- if (layer.mask)
560
- getMaskChannels(tempBuffer, layerData, layer, layer.mask, options, false);
561
- if (layer.realMask)
562
- getMaskChannels(tempBuffer, layerData, layer, layer.realMask, options, true);
563
- return layerData;
564
- }
565
- function getLayerDimentions({ canvas, imageData }) {
566
- var _a, _b, _c, _d;
567
- // this way in case canvas/imageData are incorrect objects without width/height properties
568
- const width = (_b = (_a = imageData === null || imageData === void 0 ? void 0 : imageData.width) !== null && _a !== void 0 ? _a : canvas === null || canvas === void 0 ? void 0 : canvas.width) !== null && _b !== void 0 ? _b : 0;
569
- const height = (_d = (_c = imageData === null || imageData === void 0 ? void 0 : imageData.height) !== null && _c !== void 0 ? _c : canvas === null || canvas === void 0 ? void 0 : canvas.height) !== null && _d !== void 0 ? _d : 0;
570
- return { width, height };
571
- }
572
- function cropImageData(data, left, top, width, height) {
573
- if (data.data instanceof Uint32Array || data.data instanceof Uint16Array) {
574
- throw new Error('imageData has incorrect bit depth');
575
- }
576
- const croppedData = createImageData(width, height);
577
- const srcData = data.data;
578
- const dstData = croppedData.data;
579
- for (let y = 0; y < height; y++) {
580
- for (let x = 0; x < width; x++) {
581
- let src = ((x + left) + (y + top) * data.width) * 4;
582
- let dst = (x + y * width) * 4;
583
- dstData[dst] = srcData[src];
584
- dstData[dst + 1] = srcData[src + 1];
585
- dstData[dst + 2] = srcData[src + 2];
586
- dstData[dst + 3] = srcData[src + 3];
587
- }
588
- }
589
- return croppedData;
590
- }
591
- function getLayerChannels(tempBuffer, layer, background, options) {
592
- var _a;
593
- let top = layer.top | 0;
594
- let left = layer.left | 0;
595
- let right = layer.right | 0;
596
- let bottom = layer.bottom | 0;
597
- let channels = [
598
- { channelId: -1 /* ChannelID.Transparency */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
599
- { channelId: 0 /* ChannelID.Color0 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
600
- { channelId: 1 /* ChannelID.Color1 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
601
- { channelId: 2 /* ChannelID.Color2 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
602
- ];
603
- let { width, height } = getLayerDimentions(layer);
604
- if (!(layer.canvas || layer.imageData) || !width || !height) {
605
- right = left;
606
- bottom = top;
607
- return { layer, top, left, right, bottom, channels };
608
- }
609
- right = left + width;
610
- bottom = top + height;
611
- let data = layer.imageData || layer.canvas.getContext('2d').getImageData(0, 0, width, height);
612
- if (options.trimImageData) {
613
- const trimmed = trimData(data);
614
- if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== data.width || trimmed.bottom !== data.height) {
615
- left += trimmed.left;
616
- top += trimmed.top;
617
- right -= (data.width - trimmed.right);
618
- bottom -= (data.height - trimmed.bottom);
619
- width = right - left;
620
- height = bottom - top;
621
- if (!width || !height)
622
- return { layer, top, left, right, bottom, channels };
623
- data = cropImageData(data, trimmed.left, trimmed.top, width, height);
624
- }
625
- }
626
- const channelIds = [
627
- 0 /* ChannelID.Color0 */,
628
- 1 /* ChannelID.Color1 */,
629
- 2 /* ChannelID.Color2 */,
630
- ];
631
- if (!background || options.noBackground || layer.mask || hasAlpha(data) || (RAW_IMAGE_DATA && ((_a = layer.imageDataRaw) === null || _a === void 0 ? void 0 : _a['-1']))) {
632
- channelIds.unshift(-1 /* ChannelID.Transparency */);
633
- }
634
- channels = channelIds.map(channelId => {
635
- const offset = offsetForChannel(channelId, false); // TODO: psd.colorMode === ColorMode.CMYK);
636
- let buffer;
637
- let compression;
638
- if (RAW_IMAGE_DATA && layer.imageDataRaw) {
639
- // console.log('written raw layer image data');
640
- buffer = layer.imageDataRaw[channelId];
641
- compression = layer.imageDataRawCompression[channelId];
642
- }
643
- else if (options.compress) {
644
- buffer = writeDataZipWithoutPrediction(data, [offset]);
645
- compression = 2 /* Compression.ZipWithoutPrediction */;
646
- }
647
- else {
648
- buffer = writeDataRLE(tempBuffer, data, [offset], !!options.psb);
649
- compression = 1 /* Compression.RleCompressed */;
650
- }
651
- return { channelId, compression, buffer, length: 2 + buffer.length };
652
- });
653
- return { layer, top, left, right, bottom, channels };
654
- }
655
- function isRowEmpty({ data, width }, y, left, right) {
656
- const start = ((y * width + left) * 4 + 3) | 0;
657
- const end = (start + (right - left) * 4) | 0;
658
- for (let i = start; i < end; i = (i + 4) | 0) {
659
- if (data[i] !== 0) {
660
- return false;
661
- }
662
- }
663
- return true;
664
- }
665
- function isColEmpty({ data, width }, x, top, bottom) {
666
- const stride = (width * 4) | 0;
667
- const start = (top * stride + x * 4 + 3) | 0;
668
- for (let y = top, i = start; y < bottom; y++, i = (i + stride) | 0) {
669
- if (data[i] !== 0) {
670
- return false;
671
- }
672
- }
673
- return true;
674
- }
675
- function trimData(data) {
676
- let top = 0;
677
- let left = 0;
678
- let right = data.width;
679
- let bottom = data.height;
680
- while (top < bottom && isRowEmpty(data, top, left, right))
681
- top++;
682
- while (bottom > top && isRowEmpty(data, bottom - 1, left, right))
683
- bottom--;
684
- while (left < right && isColEmpty(data, left, top, bottom))
685
- left++;
686
- while (right > left && isColEmpty(data, right - 1, top, bottom))
687
- right--;
688
- return { top, left, right, bottom };
689
- }
690
- export function writeColor(writer, color) {
691
- if (!color) {
692
- writeUint16(writer, 0 /* ColorSpace.RGB */);
693
- writeZeros(writer, 8);
694
- }
695
- else if ('r' in color) {
696
- writeUint16(writer, 0 /* ColorSpace.RGB */);
697
- writeUint16(writer, Math.round(color.r * 257));
698
- writeUint16(writer, Math.round(color.g * 257));
699
- writeUint16(writer, Math.round(color.b * 257));
700
- writeUint16(writer, 0);
701
- }
702
- else if ('fr' in color) {
703
- writeUint16(writer, 0 /* ColorSpace.RGB */);
704
- writeUint16(writer, Math.round(color.fr * 255 * 257));
705
- writeUint16(writer, Math.round(color.fg * 255 * 257));
706
- writeUint16(writer, Math.round(color.fb * 255 * 257));
707
- writeUint16(writer, 0);
708
- }
709
- else if ('l' in color) {
710
- writeUint16(writer, 7 /* ColorSpace.Lab */);
711
- writeInt16(writer, Math.round(color.l * 10000));
712
- writeInt16(writer, Math.round(color.a < 0 ? (color.a * 12800) : (color.a * 12700)));
713
- writeInt16(writer, Math.round(color.b < 0 ? (color.b * 12800) : (color.b * 12700)));
714
- writeUint16(writer, 0);
715
- }
716
- else if ('h' in color) {
717
- writeUint16(writer, 1 /* ColorSpace.HSB */);
718
- writeUint16(writer, Math.round(color.h * 0xffff));
719
- writeUint16(writer, Math.round(color.s * 0xffff));
720
- writeUint16(writer, Math.round(color.b * 0xffff));
721
- writeUint16(writer, 0);
722
- }
723
- else if ('c' in color) {
724
- writeUint16(writer, 2 /* ColorSpace.CMYK */);
725
- writeUint16(writer, Math.round(color.c * 257));
726
- writeUint16(writer, Math.round(color.m * 257));
727
- writeUint16(writer, Math.round(color.y * 257));
728
- writeUint16(writer, Math.round(color.k * 257));
729
- }
730
- else {
731
- writeUint16(writer, 8 /* ColorSpace.Grayscale */);
732
- writeUint16(writer, Math.round(color.k * 10000 / 255));
733
- writeZeros(writer, 6);
734
- }
735
- }
736
- // ponytail: only round-trips RGB 8-bit patterns; source colorMode (16-bit/Indexed) is not preserved,
737
- // since readPattern already converted everything to RGBA. Upgrade if pattern colorMode must survive write.
738
- export function writePattern(writer, pattern) {
739
- const width = pattern.bounds.w;
740
- const height = pattern.bounds.h;
741
- const pixelData = { width, height, data: pattern.data };
742
- writeUint32(writer, 0); // length, fixed up below
743
- const pattsOffset = writer.offset;
744
- writeUint32(writer, 1); // version
745
- writeUint32(writer, 3 /* ColorMode.RGB */); // color mode - rgb only
746
- writeInt16(writer, pattern.x);
747
- writeInt16(writer, pattern.y);
748
- writeUnicodeString(writer, pattern.name + '\0'); // name
749
- writePascalString(writer, pattern.id, 1); // id
750
- // virtual memory array list
751
- writeUint32(writer, 3); // version
752
- writeUint32(writer, 0); // length, fixed up below
753
- const vlOffset = writer.offset;
754
- const top = pattern.bounds.y;
755
- const left = pattern.bounds.x;
756
- const bottom = top + height;
757
- const right = left + width;
758
- writeUint32(writer, top);
759
- writeUint32(writer, left);
760
- writeUint32(writer, bottom);
761
- writeUint32(writer, right);
762
- writeUint32(writer, 24); // channels count
763
- // channels: RGB at indices 0,1,2 and alpha at index 25
764
- for (let i = 0; i < 24 + 2; i++) {
765
- const offset = i < 3 ? i : (i === 25 ? 3 : -1);
766
- if (offset < 0) {
767
- writeUint32(writer, 0); // has
768
- continue;
769
- }
770
- // worst-case RLE size for a single channel: width + 1 per scanline, plus scanline length headers
771
- const buffer = new Uint8Array(width * height + 2 * height + 2 * width + 16);
772
- // ponytail: pattern channels always use small (2-byte) RLE scanline headers, matching
773
- // readPattern which reads them as non-large; `large` here only affects the header width.
774
- const data = writeDataRLE(buffer, pixelData, [offset], false);
775
- writeUint32(writer, 1); // has
776
- writeUint32(writer, data.length + 4 + 16 + 2 + 1); // length
777
- writeUint32(writer, 8); // pixelDepth
778
- writeUint32(writer, top);
779
- writeUint32(writer, left);
780
- writeUint32(writer, bottom);
781
- writeUint32(writer, right);
782
- writeUint16(writer, 8); // pixelDepth2
783
- writeUint8(writer, 1); // compressionMode - rle
784
- writeBytes(writer, data);
785
- }
786
- const vlLength = writer.offset - vlOffset;
787
- let pattsLength = writer.offset - pattsOffset;
788
- while (pattsLength % 4) {
789
- writeZeros(writer, 1);
790
- pattsLength++;
791
- }
792
- writer.view.setUint32(vlOffset - 4, vlLength, false);
793
- writer.view.setUint32(pattsOffset - 4, pattsLength, false);
794
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWriter = createWriter;
4
+ exports.getWriterBuffer = getWriterBuffer;
5
+ exports.getWriterBufferNoCopy = getWriterBufferNoCopy;
6
+ exports.writeUint8 = writeUint8;
7
+ exports.writeInt16 = writeInt16;
8
+ exports.writeUint16 = writeUint16;
9
+ exports.writeUint16LE = writeUint16LE;
10
+ exports.writeInt32 = writeInt32;
11
+ exports.writeInt32LE = writeInt32LE;
12
+ exports.writeUint32 = writeUint32;
13
+ exports.writeFloat32 = writeFloat32;
14
+ exports.writeFloat64 = writeFloat64;
15
+ exports.writeFixedPoint32 = writeFixedPoint32;
16
+ exports.writeFixedPointPath32 = writeFixedPointPath32;
17
+ exports.writeBytes = writeBytes;
18
+ exports.writeZeros = writeZeros;
19
+ exports.writeSignature = writeSignature;
20
+ exports.writeAsciiString = writeAsciiString;
21
+ exports.writePascalString = writePascalString;
22
+ exports.writeUnicodeStringWithoutLength = writeUnicodeStringWithoutLength;
23
+ exports.writeUnicodeStringWithoutLengthLE = writeUnicodeStringWithoutLengthLE;
24
+ exports.writeUnicodeString = writeUnicodeString;
25
+ exports.writeUnicodeStringWithPadding = writeUnicodeStringWithPadding;
26
+ exports.writeSection = writeSection;
27
+ exports.writePsd = writePsd;
28
+ exports.writeColor = writeColor;
29
+ exports.writePattern = writePattern;
30
+ const helpers_1 = require("./helpers");
31
+ const additionalInfo_1 = require("./additionalInfo");
32
+ const imageResources_1 = require("./imageResources");
33
+ function createWriter(size = 4096) {
34
+ const buffer = new ArrayBuffer(size);
35
+ const view = new DataView(buffer);
36
+ const offset = 0;
37
+ return { buffer, view, offset, tempBuffer: undefined };
38
+ }
39
+ function getWriterBuffer(writer) {
40
+ return writer.buffer.slice(0, writer.offset);
41
+ }
42
+ function getWriterBufferNoCopy(writer) {
43
+ return new Uint8Array(writer.buffer, 0, writer.offset);
44
+ }
45
+ function writeUint8(writer, value) {
46
+ const offset = addSize(writer, 1);
47
+ writer.view.setUint8(offset, value);
48
+ }
49
+ function writeInt16(writer, value) {
50
+ const offset = addSize(writer, 2);
51
+ writer.view.setInt16(offset, value, false);
52
+ }
53
+ function writeUint16(writer, value) {
54
+ const offset = addSize(writer, 2);
55
+ writer.view.setUint16(offset, value, false);
56
+ }
57
+ function writeUint16LE(writer, value) {
58
+ const offset = addSize(writer, 2);
59
+ writer.view.setUint16(offset, value, true);
60
+ }
61
+ function writeInt32(writer, value) {
62
+ const offset = addSize(writer, 4);
63
+ writer.view.setInt32(offset, value, false);
64
+ }
65
+ function writeInt32LE(writer, value) {
66
+ const offset = addSize(writer, 4);
67
+ writer.view.setInt32(offset, value, true);
68
+ }
69
+ function writeUint32(writer, value) {
70
+ const offset = addSize(writer, 4);
71
+ writer.view.setUint32(offset, value, false);
72
+ }
73
+ function writeFloat32(writer, value) {
74
+ const offset = addSize(writer, 4);
75
+ writer.view.setFloat32(offset, value, false);
76
+ }
77
+ function writeFloat64(writer, value) {
78
+ const offset = addSize(writer, 8);
79
+ writer.view.setFloat64(offset, value, false);
80
+ }
81
+ // 32-bit fixed-point number 16.16
82
+ function writeFixedPoint32(writer, value) {
83
+ writeInt32(writer, value * (1 << 16));
84
+ }
85
+ // 32-bit fixed-point number 8.24
86
+ function writeFixedPointPath32(writer, value) {
87
+ writeInt32(writer, value * (1 << 24));
88
+ }
89
+ function writeBytes(writer, buffer) {
90
+ if (buffer) {
91
+ ensureSize(writer, writer.offset + buffer.length);
92
+ const bytes = new Uint8Array(writer.buffer);
93
+ bytes.set(buffer, writer.offset);
94
+ writer.offset += buffer.length;
95
+ }
96
+ }
97
+ function writeZeros(writer, count) {
98
+ for (let i = 0; i < count; i++) {
99
+ writeUint8(writer, 0);
100
+ }
101
+ }
102
+ function writeSignature(writer, signature) {
103
+ if (signature.length !== 4)
104
+ throw new Error(`Invalid signature: '${signature}'`);
105
+ for (let i = 0; i < 4; i++) {
106
+ writeUint8(writer, signature.charCodeAt(i));
107
+ }
108
+ }
109
+ function writeAsciiString(writer, text) {
110
+ for (let i = 0; i < text.length; i++) {
111
+ writeUint8(writer, text.charCodeAt(i));
112
+ }
113
+ }
114
+ function writePascalString(writer, text, padTo) {
115
+ let length = text.length;
116
+ if (length > 255)
117
+ throw new Error(`String too long`);
118
+ writeUint8(writer, length);
119
+ for (let i = 0; i < length; i++) {
120
+ const code = text.charCodeAt(i);
121
+ // writeUint8(writer, code); // for testing
122
+ writeUint8(writer, code < 128 ? code : '?'.charCodeAt(0));
123
+ }
124
+ while (++length % padTo) {
125
+ writeUint8(writer, 0);
126
+ }
127
+ }
128
+ function writeUnicodeStringWithoutLength(writer, text) {
129
+ for (let i = 0; i < text.length; i++) {
130
+ writeUint16(writer, text.charCodeAt(i));
131
+ }
132
+ }
133
+ function writeUnicodeStringWithoutLengthLE(writer, text) {
134
+ for (let i = 0; i < text.length; i++) {
135
+ writeUint16LE(writer, text.charCodeAt(i));
136
+ }
137
+ }
138
+ function writeUnicodeString(writer, text) {
139
+ writeUint32(writer, text.length);
140
+ writeUnicodeStringWithoutLength(writer, text);
141
+ }
142
+ function writeUnicodeStringWithPadding(writer, text) {
143
+ writeUint32(writer, text.length + 1);
144
+ for (let i = 0; i < text.length; i++) {
145
+ writeUint16(writer, text.charCodeAt(i));
146
+ }
147
+ writeUint16(writer, 0);
148
+ }
149
+ function getLargestLayerSize(layers = []) {
150
+ let max = 0;
151
+ for (const layer of layers) {
152
+ if (layer.canvas || layer.imageData) {
153
+ const { width, height } = getLayerDimentions(layer);
154
+ max = Math.max(max, 2 * height + 2 * width * height);
155
+ }
156
+ if (layer.children) {
157
+ max = Math.max(max, getLargestLayerSize(layer.children));
158
+ }
159
+ }
160
+ return max;
161
+ }
162
+ function writeSection(writer, round, func, writeTotalLength = false, large = false) {
163
+ if (large)
164
+ writeUint32(writer, 0);
165
+ const offset = writer.offset;
166
+ writeUint32(writer, 0);
167
+ func();
168
+ let length = writer.offset - offset - 4;
169
+ let len = length;
170
+ while (len % round) {
171
+ writeUint8(writer, 0);
172
+ len++;
173
+ }
174
+ // while (writer.offset % round) {
175
+ // writeUint8(writer, 0);
176
+ // len++;
177
+ // }
178
+ if (writeTotalLength) {
179
+ length = len;
180
+ }
181
+ writer.view.setUint32(offset, length, false);
182
+ }
183
+ function verifyBitCount(target) {
184
+ var _a;
185
+ (_a = target.children) === null || _a === void 0 ? void 0 : _a.forEach(verifyBitCount);
186
+ const data = target.imageData;
187
+ if (data && (data.data instanceof Uint32Array || data.data instanceof Uint16Array)) {
188
+ throw new Error('imageData has incorrect bitDepth');
189
+ }
190
+ if ('mask' in target && target.mask) {
191
+ const data = target.mask.imageData;
192
+ if (data && (data.data instanceof Uint32Array || data.data instanceof Uint16Array)) {
193
+ throw new Error('mask imageData has incorrect bitDepth');
194
+ }
195
+ }
196
+ }
197
+ function writePsd(writer, psd, options = {}) {
198
+ var _a;
199
+ if (!(+psd.width > 0 && +psd.height > 0))
200
+ throw new Error('Invalid document size');
201
+ if ((psd.width > 30000 || psd.height > 30000) && !options.psb)
202
+ throw new Error('Document size is too large (max is 30000x30000, use PSB format instead)');
203
+ const bitsPerChannel = (_a = psd.bitsPerChannel) !== null && _a !== void 0 ? _a : 8;
204
+ if (bitsPerChannel !== 8)
205
+ throw new Error('bitsPerChannel other than 8 are not supported for writing');
206
+ verifyBitCount(psd);
207
+ const imageResources = Object.assign({}, psd.imageResources);
208
+ const opt = Object.assign(Object.assign({}, options), { layerIds: new Set(), layerToId: new Map() });
209
+ if (opt.generateThumbnail) {
210
+ imageResources.thumbnail = createThumbnail(psd);
211
+ }
212
+ let imageData = psd.imageData;
213
+ if (!imageData && psd.canvas) {
214
+ imageData = psd.canvas.getContext('2d').getImageData(0, 0, psd.canvas.width, psd.canvas.height);
215
+ }
216
+ if (imageData && (psd.width !== imageData.width || psd.height !== imageData.height))
217
+ throw new Error('Document canvas must have the same size as document');
218
+ const globalAlpha = !!imageData && (0, helpers_1.hasAlpha)(imageData);
219
+ const maxBufferSize = Math.max(getLargestLayerSize(psd.children), 4 * 2 * psd.width * psd.height + 2 * psd.height);
220
+ writer.tempBuffer = new Uint8Array(maxBufferSize);
221
+ // header
222
+ writeSignature(writer, '8BPS');
223
+ writeUint16(writer, options.psb ? 2 : 1); // version
224
+ writeZeros(writer, 6);
225
+ writeUint16(writer, globalAlpha ? 4 : 3); // channels
226
+ writeUint32(writer, psd.height);
227
+ writeUint32(writer, psd.width);
228
+ writeUint16(writer, bitsPerChannel); // bits per channel
229
+ writeUint16(writer, 3 /* ColorMode.RGB */); // we only support saving RGB right now
230
+ // color mode data
231
+ writeSection(writer, 1, () => {
232
+ var _a, _b, _c;
233
+ if (psd.palette) {
234
+ for (let i = 0; i < 256; i++)
235
+ writeUint8(writer, ((_a = psd.palette[i]) === null || _a === void 0 ? void 0 : _a.r) || 0);
236
+ for (let i = 0; i < 256; i++)
237
+ writeUint8(writer, ((_b = psd.palette[i]) === null || _b === void 0 ? void 0 : _b.g) || 0);
238
+ for (let i = 0; i < 256; i++)
239
+ writeUint8(writer, ((_c = psd.palette[i]) === null || _c === void 0 ? void 0 : _c.b) || 0);
240
+ }
241
+ // TODO: other data?
242
+ });
243
+ const layers = [];
244
+ addChildren(layers, psd.children);
245
+ if (!layers.length)
246
+ layers.push({});
247
+ // image resources
248
+ imageResources.layersGroup = layers.map(l => l.linkGroup || 0);
249
+ imageResources.layerGroupsEnabledId = layers.map(l => l.linkGroupEnabled == false ? 0 : 1);
250
+ writeSection(writer, 1, () => {
251
+ for (const handler of imageResources_1.resourceHandlers) {
252
+ const has = handler.has(imageResources);
253
+ const count = has === false ? 0 : (has === true ? 1 : has);
254
+ for (let i = 0; i < count; i++) {
255
+ writeSignature(writer, '8BIM');
256
+ writeUint16(writer, handler.key);
257
+ writePascalString(writer, '', 2);
258
+ writeSection(writer, 2, () => handler.write(writer, imageResources, i));
259
+ }
260
+ }
261
+ });
262
+ // layer and mask info
263
+ writeSection(writer, 2, () => {
264
+ writeLayerInfo(writer, layers, psd, globalAlpha, opt);
265
+ writeGlobalLayerMaskInfo(writer, psd.globalLayerMaskInfo);
266
+ writeAdditionalLayerInfo(writer, psd, psd, opt);
267
+ }, undefined, !!opt.psb);
268
+ // image data
269
+ const channels = globalAlpha ? [0, 1, 2, 3] : [0, 1, 2];
270
+ const width = imageData ? imageData.width : psd.width;
271
+ const height = imageData ? imageData.height : psd.height;
272
+ const data = { data: new Uint8Array(width * height * 4), width, height };
273
+ writeUint16(writer, 1 /* Compression.RleCompressed */); // Photoshop doesn't support zip compression of composite image data
274
+ if (helpers_1.RAW_IMAGE_DATA && psd.imageDataRaw) {
275
+ console.log('writing raw image data');
276
+ writeBytes(writer, psd.imageDataRaw);
277
+ }
278
+ else {
279
+ if (imageData)
280
+ data.data.set(new Uint8Array(imageData.data.buffer, imageData.data.byteOffset, imageData.data.byteLength));
281
+ // add weird white matte
282
+ if (globalAlpha) {
283
+ const size = data.width * data.height * 4;
284
+ const p = data.data;
285
+ for (let i = 0; i < size; i += 4) {
286
+ const pa = p[i + 3];
287
+ if (pa != 0 && pa != 255) {
288
+ const a = pa / 255;
289
+ const ra = 255 * (1 - a);
290
+ p[i + 0] = p[i + 0] * a + ra;
291
+ p[i + 1] = p[i + 1] * a + ra;
292
+ p[i + 2] = p[i + 2] * a + ra;
293
+ }
294
+ }
295
+ }
296
+ writeBytes(writer, (0, helpers_1.writeDataRLE)(writer.tempBuffer, data, channels, !!options.psb));
297
+ }
298
+ }
299
+ function writeLayerInfo(writer, layers, psd, globalAlpha, options) {
300
+ writeSection(writer, 4, () => {
301
+ var _a;
302
+ writeInt16(writer, globalAlpha ? -layers.length : layers.length);
303
+ const layersData = layers.map((l, i) => getChannels(writer.tempBuffer, l, i === 0, options));
304
+ // layer records
305
+ for (const layerData of layersData) {
306
+ const { layer, top, left, bottom, right, channels } = layerData;
307
+ writeInt32(writer, top);
308
+ writeInt32(writer, left);
309
+ writeInt32(writer, bottom);
310
+ writeInt32(writer, right);
311
+ writeUint16(writer, channels.length);
312
+ for (const c of channels) {
313
+ writeInt16(writer, c.id);
314
+ if (options.psb)
315
+ writeUint32(writer, 0);
316
+ writeUint32(writer, c.length);
317
+ }
318
+ writeSignature(writer, '8BIM');
319
+ writeSignature(writer, helpers_1.fromBlendMode[layer.blendMode] || 'norm');
320
+ writeUint8(writer, Math.round((0, helpers_1.clamp)((_a = layer.opacity) !== null && _a !== void 0 ? _a : 1, 0, 1) * 255));
321
+ writeUint8(writer, layer.clipping ? 1 : 0);
322
+ let flags = 0x08; // 1 for Photoshop 5.0 and later, tells if bit 4 has useful information
323
+ if (layer.transparencyProtected)
324
+ flags |= 0x01;
325
+ if (layer.hidden)
326
+ flags |= 0x02;
327
+ if (layer.vectorMask || (layer.sectionDivider && layer.sectionDivider.type !== 0 /* SectionDividerType.Other */) || layer.adjustment) {
328
+ flags |= 0x10; // pixel data irrelevant to appearance of document
329
+ }
330
+ if (layer.effectsOpen)
331
+ flags |= 0x20;
332
+ writeUint8(writer, flags);
333
+ writeUint8(writer, 0); // filler
334
+ writeSection(writer, 1, () => {
335
+ writeLayerMaskData(writer, layer, layerData);
336
+ writeLayerBlendingRanges(writer, layer);
337
+ writePascalString(writer, (layer.name || '').substring(0, 255), 4);
338
+ writeAdditionalLayerInfo(writer, layer, psd, options);
339
+ });
340
+ }
341
+ // layer channel image data
342
+ for (const layerData of layersData) {
343
+ for (const channel of layerData.channels) {
344
+ writeUint16(writer, channel.compression);
345
+ if (channel.data) {
346
+ writeBytes(writer, channel.data);
347
+ }
348
+ }
349
+ }
350
+ }, true, options.psb);
351
+ }
352
+ function writeLayerMaskData(writer, { mask, realMask }, layerData) {
353
+ writeSection(writer, 1, () => {
354
+ if (!mask && !realMask)
355
+ return;
356
+ let params = 0, flags = 0, realFlags = 0;
357
+ if (mask) {
358
+ if (mask.userMaskDensity !== undefined)
359
+ params |= 1 /* MaskParams.UserMaskDensity */;
360
+ if (mask.userMaskFeather !== undefined)
361
+ params |= 2 /* MaskParams.UserMaskFeather */;
362
+ if (mask.vectorMaskDensity !== undefined)
363
+ params |= 4 /* MaskParams.VectorMaskDensity */;
364
+ if (mask.vectorMaskFeather !== undefined)
365
+ params |= 8 /* MaskParams.VectorMaskFeather */;
366
+ if (mask.disabled)
367
+ flags |= 2 /* LayerMaskFlags.LayerMaskDisabled */;
368
+ if (mask.positionRelativeToLayer)
369
+ flags |= 1 /* LayerMaskFlags.PositionRelativeToLayer */;
370
+ if (mask.fromVectorData)
371
+ flags |= 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */;
372
+ if (params)
373
+ flags |= 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */;
374
+ }
375
+ const m = layerData.mask || {};
376
+ writeInt32(writer, m.top || 0);
377
+ writeInt32(writer, m.left || 0);
378
+ writeInt32(writer, m.bottom || 0);
379
+ writeInt32(writer, m.right || 0);
380
+ writeUint8(writer, mask && mask.defaultColor || 0);
381
+ writeUint8(writer, flags);
382
+ if (realMask) {
383
+ if (realMask.disabled)
384
+ realFlags |= 2 /* LayerMaskFlags.LayerMaskDisabled */;
385
+ if (realMask.positionRelativeToLayer)
386
+ realFlags |= 1 /* LayerMaskFlags.PositionRelativeToLayer */;
387
+ if (realMask.fromVectorData)
388
+ realFlags |= 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */;
389
+ const r = layerData.realMask || {};
390
+ writeUint8(writer, realFlags);
391
+ writeUint8(writer, realMask.defaultColor || 0);
392
+ writeInt32(writer, r.top || 0);
393
+ writeInt32(writer, r.left || 0);
394
+ writeInt32(writer, r.bottom || 0);
395
+ writeInt32(writer, r.right || 0);
396
+ }
397
+ if (params && mask) {
398
+ writeUint8(writer, params);
399
+ if (mask.userMaskDensity !== undefined)
400
+ writeUint8(writer, Math.round(mask.userMaskDensity * 0xff));
401
+ if (mask.userMaskFeather !== undefined)
402
+ writeFloat64(writer, mask.userMaskFeather);
403
+ if (mask.vectorMaskDensity !== undefined)
404
+ writeUint8(writer, Math.round(mask.vectorMaskDensity * 0xff));
405
+ if (mask.vectorMaskFeather !== undefined)
406
+ writeFloat64(writer, mask.vectorMaskFeather);
407
+ }
408
+ writeZeros(writer, 2);
409
+ });
410
+ }
411
+ function writerBlendingRange(writer, range) {
412
+ writeUint8(writer, range[0]);
413
+ writeUint8(writer, range[1]);
414
+ writeUint8(writer, range[2]);
415
+ writeUint8(writer, range[3]);
416
+ }
417
+ function writeLayerBlendingRanges(writer, layer) {
418
+ writeSection(writer, 1, () => {
419
+ const ranges = layer.blendingRanges;
420
+ if (ranges) {
421
+ writerBlendingRange(writer, ranges.compositeGrayBlendSource);
422
+ writerBlendingRange(writer, ranges.compositeGraphBlendDestinationRange);
423
+ for (const r of ranges.ranges) {
424
+ writerBlendingRange(writer, r.sourceRange);
425
+ writerBlendingRange(writer, r.destRange);
426
+ }
427
+ }
428
+ });
429
+ }
430
+ function writeGlobalLayerMaskInfo(writer, info) {
431
+ writeSection(writer, 1, () => {
432
+ if (info) {
433
+ writeUint16(writer, info.overlayColorSpace);
434
+ writeUint16(writer, info.colorSpace1);
435
+ writeUint16(writer, info.colorSpace2);
436
+ writeUint16(writer, info.colorSpace3);
437
+ writeUint16(writer, info.colorSpace4);
438
+ writeUint16(writer, info.opacity * 0xff);
439
+ writeUint8(writer, info.kind);
440
+ writeZeros(writer, 3);
441
+ }
442
+ });
443
+ }
444
+ function writeAdditionalLayerInfo(writer, target, psd, options) {
445
+ for (const handler of additionalInfo_1.infoHandlers) {
446
+ let key = handler.key;
447
+ if (key === 'Txt2' && options.invalidateTextLayers)
448
+ continue;
449
+ if (key === 'vmsk' && options.psb)
450
+ key = 'vsms';
451
+ if (handler.has(target)) {
452
+ const large = options.psb && helpers_1.largeAdditionalInfoKeys.indexOf(key) !== -1;
453
+ const writeTotalLength = key !== 'Txt2' && key !== 'cinf' && key !== 'extn' && key !== 'CAI ' && key !== 'OCIO';
454
+ const fourBytes = key === 'Txt2' || key === 'luni' || key === 'vmsk' || key === 'artb' || key === 'artd' ||
455
+ key === 'vogk' || key === 'SoLd' || key === 'lnk2' || key === 'vscg' || key === 'vsms' || key === 'GdFl' ||
456
+ key === 'lmfx' || key === 'lrFX' || key === 'cinf' || key === 'PlLd' || key === 'Anno' || key === 'CAI ' || key === 'OCIO' || key === 'GenI' || key === 'FEid' || key === 'curv' || key === 'CgEd' || key === 'vibA' || key === 'blwh' || key === 'grdm';
457
+ writeSignature(writer, large ? '8B64' : '8BIM');
458
+ writeSignature(writer, key);
459
+ writeSection(writer, fourBytes ? 4 : 2, () => {
460
+ handler.write(writer, target, psd, options);
461
+ }, writeTotalLength, large);
462
+ }
463
+ }
464
+ }
465
+ function addChildren(layers, children) {
466
+ if (!children)
467
+ return;
468
+ // const layerIds: number[] = [2];
469
+ // const timestamps: number[] = [1740120767.0230637];
470
+ for (const c of children) {
471
+ if (c.children && c.canvas)
472
+ throw new Error(`Invalid layer, cannot have both 'canvas' and 'children' properties`);
473
+ if (c.children && c.imageData)
474
+ throw new Error(`Invalid layer, cannot have both 'imageData' and 'children' properties`);
475
+ if (c.children) {
476
+ layers.push({
477
+ name: '</Layer group>',
478
+ sectionDivider: {
479
+ type: 3 /* SectionDividerType.BoundingSectionDivider */,
480
+ },
481
+ // blendingRanges: children[0].blendingRanges,
482
+ // nameSource: 'lset',
483
+ // id: layerIds.shift(),
484
+ // protected: {
485
+ // transparency: false,
486
+ // composite: false,
487
+ // position: false,
488
+ // },
489
+ // layerColor: 'red',
490
+ // timestamp: timestamps.shift(),
491
+ // referencePoint: { x: 0, y: 0 },
492
+ });
493
+ addChildren(layers, c.children);
494
+ layers.push(Object.assign(Object.assign({}, c), { blendMode: c.blendMode === 'pass through' ? 'normal' : c.blendMode, sectionDivider: {
495
+ type: c.opened === false ? 2 /* SectionDividerType.ClosedFolder */ : 1 /* SectionDividerType.OpenFolder */,
496
+ key: helpers_1.fromBlendMode[c.blendMode] || 'pass',
497
+ subType: 0,
498
+ } }));
499
+ }
500
+ else {
501
+ layers.push(Object.assign({}, c));
502
+ }
503
+ }
504
+ }
505
+ function resizeBuffer(writer, size) {
506
+ let newLength = writer.buffer.byteLength;
507
+ do {
508
+ newLength *= 2;
509
+ } while (size > newLength);
510
+ const newBuffer = new ArrayBuffer(newLength);
511
+ const newBytes = new Uint8Array(newBuffer);
512
+ const oldBytes = new Uint8Array(writer.buffer);
513
+ newBytes.set(oldBytes);
514
+ writer.buffer = newBuffer;
515
+ writer.view = new DataView(writer.buffer);
516
+ }
517
+ function ensureSize(writer, size) {
518
+ if (size > writer.buffer.byteLength) {
519
+ resizeBuffer(writer, size);
520
+ }
521
+ }
522
+ function addSize(writer, size) {
523
+ const offset = writer.offset;
524
+ ensureSize(writer, writer.offset += size);
525
+ return offset;
526
+ }
527
+ function createThumbnail(psd) {
528
+ const canvas = (0, helpers_1.createCanvas)(10, 10);
529
+ let scale = 1;
530
+ if (psd.width > psd.height) {
531
+ canvas.width = 160;
532
+ canvas.height = Math.floor(psd.height * (canvas.width / psd.width));
533
+ scale = canvas.width / psd.width;
534
+ }
535
+ else {
536
+ canvas.height = 160;
537
+ canvas.width = Math.floor(psd.width * (canvas.height / psd.height));
538
+ scale = canvas.height / psd.height;
539
+ }
540
+ const context = canvas.getContext('2d');
541
+ context.scale(scale, scale);
542
+ if (psd.imageData) {
543
+ context.drawImage((0, helpers_1.imageDataToCanvas)(psd.imageData), 0, 0);
544
+ }
545
+ else if (psd.canvas) {
546
+ context.drawImage(psd.canvas, 0, 0);
547
+ }
548
+ return canvas;
549
+ }
550
+ function getMaskChannels(tempBuffer, layerData, layer, mask, options, realMask) {
551
+ let top = mask.top | 0;
552
+ let left = mask.left | 0;
553
+ let right = mask.right | 0;
554
+ let bottom = mask.bottom | 0;
555
+ let { width, height } = getLayerDimentions(mask);
556
+ let imageData = mask.imageData;
557
+ if (!imageData && mask.canvas && width && height) {
558
+ imageData = mask.canvas.getContext('2d').getImageData(0, 0, width, height);
559
+ }
560
+ if (imageData && (imageData.width !== width || imageData.height !== height)) {
561
+ throw new Error('Invalid imageData dimentions');
562
+ }
563
+ right = left + width;
564
+ bottom = top + height;
565
+ let buffer;
566
+ let compression;
567
+ if (helpers_1.RAW_IMAGE_DATA && layer[realMask ? 'realMaskDataRaw' : 'maskDataRaw']) {
568
+ buffer = layer[realMask ? 'realMaskDataRaw' : 'maskDataRaw'];
569
+ compression = layer[realMask ? 'realMaskDataRawCompression' : 'maskDataRawCompression'];
570
+ }
571
+ else if (!imageData) {
572
+ buffer = new Uint8Array(0);
573
+ compression = 1 /* Compression.RleCompressed */;
574
+ }
575
+ else if (options.compress) {
576
+ buffer = (0, helpers_1.writeDataZipWithoutPrediction)(imageData, [0]);
577
+ compression = 2 /* Compression.ZipWithoutPrediction */;
578
+ }
579
+ else {
580
+ buffer = (0, helpers_1.writeDataRLE)(tempBuffer, imageData, [0], !!options.psb);
581
+ compression = 1 /* Compression.RleCompressed */;
582
+ }
583
+ layerData.channels.push({ id: realMask ? -3 /* ChannelID.RealUserMask */ : -2 /* ChannelID.UserMask */, compression, data: buffer, length: 2 + buffer.length });
584
+ layerData[realMask ? 'realMask' : 'mask'] = { top, left, right, bottom };
585
+ }
586
+ function bounds(obj) {
587
+ return obj ? {
588
+ top: obj.top || 0,
589
+ left: obj.left || 0,
590
+ right: obj.right || 0,
591
+ bottom: obj.bottom || 0,
592
+ } : undefined;
593
+ }
594
+ function getChannels(tempBuffer, layer, background, options) {
595
+ if (layer.rawData) {
596
+ return Object.assign(Object.assign({ layer, channels: layer.rawData.channels.map(c => { var _a, _b; return (Object.assign(Object.assign({}, c), { length: 2 + ((_b = (_a = c.data) === null || _a === void 0 ? void 0 : _a.byteLength) !== null && _b !== void 0 ? _b : 0) })); }) }, bounds(layer)), { mask: bounds(layer.mask), realMask: bounds(layer.realMask) });
597
+ }
598
+ const layerData = getLayerChannels(tempBuffer, layer, background, options);
599
+ if (layer.mask)
600
+ getMaskChannels(tempBuffer, layerData, layer, layer.mask, options, false);
601
+ if (layer.realMask)
602
+ getMaskChannels(tempBuffer, layerData, layer, layer.realMask, options, true);
603
+ return layerData;
604
+ }
605
+ function getLayerDimentions({ canvas, imageData }) {
606
+ var _a, _b, _c, _d;
607
+ // this way in case canvas/imageData are incorrect objects without width/height properties
608
+ const width = (_b = (_a = imageData === null || imageData === void 0 ? void 0 : imageData.width) !== null && _a !== void 0 ? _a : canvas === null || canvas === void 0 ? void 0 : canvas.width) !== null && _b !== void 0 ? _b : 0;
609
+ const height = (_d = (_c = imageData === null || imageData === void 0 ? void 0 : imageData.height) !== null && _c !== void 0 ? _c : canvas === null || canvas === void 0 ? void 0 : canvas.height) !== null && _d !== void 0 ? _d : 0;
610
+ return { width, height };
611
+ }
612
+ function cropImageData(data, left, top, width, height) {
613
+ if (data.data instanceof Uint32Array || data.data instanceof Uint16Array) {
614
+ throw new Error('imageData has incorrect bit depth');
615
+ }
616
+ const croppedData = (0, helpers_1.createImageData)(width, height);
617
+ const srcData = data.data;
618
+ const dstData = croppedData.data;
619
+ for (let y = 0; y < height; y++) {
620
+ for (let x = 0; x < width; x++) {
621
+ let src = ((x + left) + (y + top) * data.width) * 4;
622
+ let dst = (x + y * width) * 4;
623
+ dstData[dst] = srcData[src];
624
+ dstData[dst + 1] = srcData[src + 1];
625
+ dstData[dst + 2] = srcData[src + 2];
626
+ dstData[dst + 3] = srcData[src + 3];
627
+ }
628
+ }
629
+ return croppedData;
630
+ }
631
+ function getLayerChannels(tempBuffer, layer, background, options) {
632
+ var _a;
633
+ let top = layer.top | 0;
634
+ let left = layer.left | 0;
635
+ let right = layer.right | 0;
636
+ let bottom = layer.bottom | 0;
637
+ let channels = [
638
+ { id: -1 /* ChannelID.Transparency */, compression: 0 /* Compression.RawData */, data: undefined, length: 2 },
639
+ { id: 0 /* ChannelID.Color0 */, compression: 0 /* Compression.RawData */, data: undefined, length: 2 },
640
+ { id: 1 /* ChannelID.Color1 */, compression: 0 /* Compression.RawData */, data: undefined, length: 2 },
641
+ { id: 2 /* ChannelID.Color2 */, compression: 0 /* Compression.RawData */, data: undefined, length: 2 },
642
+ ];
643
+ let { width, height } = getLayerDimentions(layer);
644
+ if (!(layer.canvas || layer.imageData) || !width || !height) {
645
+ right = left;
646
+ bottom = top;
647
+ return { layer, top, left, right, bottom, channels };
648
+ }
649
+ right = left + width;
650
+ bottom = top + height;
651
+ let imageData = layer.imageData || layer.canvas.getContext('2d').getImageData(0, 0, width, height);
652
+ if (options.trimImageData) {
653
+ const trimmed = trimData(imageData);
654
+ if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== imageData.width || trimmed.bottom !== imageData.height) {
655
+ left += trimmed.left;
656
+ top += trimmed.top;
657
+ right -= (imageData.width - trimmed.right);
658
+ bottom -= (imageData.height - trimmed.bottom);
659
+ width = right - left;
660
+ height = bottom - top;
661
+ if (!width || !height)
662
+ return { layer, top, left, right, bottom, channels };
663
+ imageData = cropImageData(imageData, trimmed.left, trimmed.top, width, height);
664
+ }
665
+ }
666
+ const channelIds = [
667
+ 0 /* ChannelID.Color0 */,
668
+ 1 /* ChannelID.Color1 */,
669
+ 2 /* ChannelID.Color2 */,
670
+ ];
671
+ if (!background || options.noBackground || layer.mask || (0, helpers_1.hasAlpha)(imageData) || (helpers_1.RAW_IMAGE_DATA && ((_a = layer.imageDataRaw) === null || _a === void 0 ? void 0 : _a['-1']))) {
672
+ channelIds.unshift(-1 /* ChannelID.Transparency */);
673
+ }
674
+ channels = channelIds.map(id => {
675
+ const offset = (0, helpers_1.offsetForChannel)(id, false); // TODO: psd.colorMode === ColorMode.CMYK);
676
+ let data;
677
+ let compression;
678
+ if (helpers_1.RAW_IMAGE_DATA && layer.imageDataRaw) {
679
+ // console.log('written raw layer image data');
680
+ data = layer.imageDataRaw[id];
681
+ compression = layer.imageDataRawCompression[id];
682
+ }
683
+ else if (options.compress) {
684
+ data = (0, helpers_1.writeDataZipWithoutPrediction)(imageData, [offset]);
685
+ compression = 2 /* Compression.ZipWithoutPrediction */;
686
+ }
687
+ else {
688
+ data = (0, helpers_1.writeDataRLE)(tempBuffer, imageData, [offset], !!options.psb);
689
+ compression = 1 /* Compression.RleCompressed */;
690
+ }
691
+ return { id, compression, data, length: 2 + data.length };
692
+ });
693
+ return { layer, top, left, right, bottom, channels };
694
+ }
695
+ function isRowEmpty({ data, width }, y, left, right) {
696
+ const start = ((y * width + left) * 4 + 3) | 0;
697
+ const end = (start + (right - left) * 4) | 0;
698
+ for (let i = start; i < end; i = (i + 4) | 0) {
699
+ if (data[i] !== 0) {
700
+ return false;
701
+ }
702
+ }
703
+ return true;
704
+ }
705
+ function isColEmpty({ data, width }, x, top, bottom) {
706
+ const stride = (width * 4) | 0;
707
+ const start = (top * stride + x * 4 + 3) | 0;
708
+ for (let y = top, i = start; y < bottom; y++, i = (i + stride) | 0) {
709
+ if (data[i] !== 0) {
710
+ return false;
711
+ }
712
+ }
713
+ return true;
714
+ }
715
+ function trimData(data) {
716
+ let top = 0;
717
+ let left = 0;
718
+ let right = data.width;
719
+ let bottom = data.height;
720
+ while (top < bottom && isRowEmpty(data, top, left, right))
721
+ top++;
722
+ while (bottom > top && isRowEmpty(data, bottom - 1, left, right))
723
+ bottom--;
724
+ while (left < right && isColEmpty(data, left, top, bottom))
725
+ left++;
726
+ while (right > left && isColEmpty(data, right - 1, top, bottom))
727
+ right--;
728
+ return { top, left, right, bottom };
729
+ }
730
+ function writeColor(writer, color) {
731
+ if (!color) {
732
+ writeUint16(writer, 0 /* ColorSpace.RGB */);
733
+ writeZeros(writer, 8);
734
+ }
735
+ else if ('r' in color) {
736
+ writeUint16(writer, 0 /* ColorSpace.RGB */);
737
+ writeUint16(writer, Math.round(color.r * 257));
738
+ writeUint16(writer, Math.round(color.g * 257));
739
+ writeUint16(writer, Math.round(color.b * 257));
740
+ writeUint16(writer, 0);
741
+ }
742
+ else if ('fr' in color) {
743
+ writeUint16(writer, 0 /* ColorSpace.RGB */);
744
+ writeUint16(writer, Math.round(color.fr * 255 * 257));
745
+ writeUint16(writer, Math.round(color.fg * 255 * 257));
746
+ writeUint16(writer, Math.round(color.fb * 255 * 257));
747
+ writeUint16(writer, 0);
748
+ }
749
+ else if ('l' in color) {
750
+ writeUint16(writer, 7 /* ColorSpace.Lab */);
751
+ writeInt16(writer, Math.round(color.l * 10000));
752
+ writeInt16(writer, Math.round(color.a < 0 ? (color.a * 12800) : (color.a * 12700)));
753
+ writeInt16(writer, Math.round(color.b < 0 ? (color.b * 12800) : (color.b * 12700)));
754
+ writeUint16(writer, 0);
755
+ }
756
+ else if ('h' in color) {
757
+ writeUint16(writer, 1 /* ColorSpace.HSB */);
758
+ writeUint16(writer, Math.round(color.h * 0xffff));
759
+ writeUint16(writer, Math.round(color.s * 0xffff));
760
+ writeUint16(writer, Math.round(color.b * 0xffff));
761
+ writeUint16(writer, 0);
762
+ }
763
+ else if ('c' in color) {
764
+ writeUint16(writer, 2 /* ColorSpace.CMYK */);
765
+ writeUint16(writer, Math.round(color.c * 257));
766
+ writeUint16(writer, Math.round(color.m * 257));
767
+ writeUint16(writer, Math.round(color.y * 257));
768
+ writeUint16(writer, Math.round(color.k * 257));
769
+ }
770
+ else {
771
+ writeUint16(writer, 8 /* ColorSpace.Grayscale */);
772
+ writeUint16(writer, Math.round(color.k * 10000 / 255));
773
+ writeZeros(writer, 6);
774
+ }
775
+ }
776
+ // ponytail: only round-trips RGB 8-bit patterns; source colorMode (16-bit/Indexed) is not preserved,
777
+ // since readPattern already converted everything to RGBA. Upgrade if pattern colorMode must survive write.
778
+ function writePattern(writer, pattern) {
779
+ const width = pattern.bounds.w;
780
+ const height = pattern.bounds.h;
781
+ const pixelData = { width, height, data: pattern.data };
782
+ writeUint32(writer, 0); // length, fixed up below
783
+ const pattsOffset = writer.offset;
784
+ writeUint32(writer, 1); // version
785
+ writeUint32(writer, 3 /* ColorMode.RGB */); // color mode - rgb only
786
+ writeInt16(writer, pattern.x);
787
+ writeInt16(writer, pattern.y);
788
+ writeUnicodeString(writer, pattern.name + '\0'); // name
789
+ writePascalString(writer, pattern.id, 1); // id
790
+ // virtual memory array list
791
+ writeUint32(writer, 3); // version
792
+ writeUint32(writer, 0); // length, fixed up below
793
+ const vlOffset = writer.offset;
794
+ const top = pattern.bounds.y;
795
+ const left = pattern.bounds.x;
796
+ const bottom = top + height;
797
+ const right = left + width;
798
+ writeUint32(writer, top);
799
+ writeUint32(writer, left);
800
+ writeUint32(writer, bottom);
801
+ writeUint32(writer, right);
802
+ writeUint32(writer, 24); // channels count
803
+ // channels: RGB at indices 0,1,2 and alpha at index 25
804
+ for (let i = 0; i < 24 + 2; i++) {
805
+ const offset = i < 3 ? i : (i === 25 ? 3 : -1);
806
+ if (offset < 0) {
807
+ writeUint32(writer, 0); // has
808
+ continue;
809
+ }
810
+ // worst-case RLE size for a single channel: width + 1 per scanline, plus scanline length headers
811
+ const buffer = new Uint8Array(width * height + 2 * height + 2 * width + 16);
812
+ // ponytail: pattern channels always use small (2-byte) RLE scanline headers, matching
813
+ // readPattern which reads them as non-large; `large` here only affects the header width.
814
+ const data = (0, helpers_1.writeDataRLE)(buffer, pixelData, [offset], false);
815
+ writeUint32(writer, 1); // has
816
+ writeUint32(writer, data.length + 4 + 16 + 2 + 1); // length
817
+ writeUint32(writer, 8); // pixelDepth
818
+ writeUint32(writer, top);
819
+ writeUint32(writer, left);
820
+ writeUint32(writer, bottom);
821
+ writeUint32(writer, right);
822
+ writeUint16(writer, 8); // pixelDepth2
823
+ writeUint8(writer, 1); // compressionMode - rle
824
+ writeBytes(writer, data);
825
+ }
826
+ const vlLength = writer.offset - vlOffset;
827
+ let pattsLength = writer.offset - pattsOffset;
828
+ while (pattsLength % 4) {
829
+ writeZeros(writer, 1);
830
+ pattsLength++;
831
+ }
832
+ writer.view.setUint32(vlOffset - 4, vlLength, false);
833
+ writer.view.setUint32(pattsOffset - 4, pattsLength, false);
834
+ }
795
835
  //# sourceMappingURL=psdWriter.js.map