ag-psd 30.1.1 → 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.
- package/.v8-cache/v24.13.1-x64-cf738c9d/017325ac +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/01e5e61b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/043c7b90 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/05135617 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/059f8558 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/06423db9 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/06e765df +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0706ecb8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0930679d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/09519a62 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0a6607b0 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0ad8fa6e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0d390e10 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0db754a7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0dfa7b16 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/0e9e09db +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1130885f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1222cb8c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/15e2c039 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/15f0e479 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1a2d469d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1b300c82 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1bc3d370 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1e44e5af +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1efa10a1 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/1f6c8743 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/20477c23 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/20b27e40 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/20dfa422 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/257c62ba +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/25d60154 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/26f822f3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2a19133e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2a1e2a8d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2b02fded +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2b069ee0 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2c76dc0d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2de09439 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2deb286a +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2e44f5f0 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/2fb229a9 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/3144b401 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/32018e44 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/341402c3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/34e0fa2e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/37481985 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/3bbf643e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/3ceff89e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/404f5cdc +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4087aa2b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4376c1f9 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/44903df4 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/44d58dc8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4511bacf +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/47da0ce8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/48cd54a9 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/49d22b79 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4d938476 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4ec6d390 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/4f5702bd +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/514cc428 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/557d3b42 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/56abbff7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/57b540ee +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/57d3380b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/5e20c081 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6024ce3f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/61735b23 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/63dbdb75 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/651c4ada +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/652a0d59 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6a0e89ee +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6af33b91 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6c2562d2 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6cbfc0ec +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6dae0cfa +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6e2529ce +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/6f08372c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7100ee08 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/71df9cb3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/72e1d543 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/75519c80 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/75e41e43 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/79bf115c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7a39347c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7b83e3d3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7cd71bc5 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7da78512 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/7ea06cea +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/82c3b573 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/84c186e4 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/8568576b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/8607bd36 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/87372817 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/87cf2209 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/882aaa05 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/8a4d3de8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/8e223473 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/92b7aefd +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/932f0770 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/937c03a1 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/991e4758 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/9af658fb +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/9ed80ba5 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/9f0dc993 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/a19c0c4f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/a6409d95 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/a79a40bb +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/a7e80865 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/ac9802c6 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/acc36e66 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/ad11e2dc +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b0c8fcd8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b1762958 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b3c2fab7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b5b3329b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b69ed3a3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/b806679e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/bc1cdd48 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/bc7ebd1d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/bdff1628 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c0b789d2 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c314aece +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c399a5dc +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c681cbc8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c6834ffc +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/c6f12ed5 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cb0f0a3d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cbcb7c95 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cdd9107c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cdf2c4a3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cfc49f4f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/cff9434a +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/d02dd6f7 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/d0507bf3 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/d60fce19 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/d733d619 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/d75b7803 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/dc86f000 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/de74e659 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/defa4f7f +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e03e2acd +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e0e3f52c +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e158d332 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6735171 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6745c2b +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6b99945 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e6d8ceb8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/e7ffec37 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/ea33b6de +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/eaafa3c4 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/ebb50fca +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/ec805f2e +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/edaef8f1 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/ee4401c8 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/eeeebdfe +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/f3d51676 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/f7b50a75 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fa58ca72 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fbca6276 +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fc97d72d +0 -0
- package/.v8-cache/v24.13.1-x64-cf738c9d/fd0a2987 +0 -0
- package/CHANGELOG.md +9 -0
- package/README.md +65 -1
- package/README_PSD.md +1 -1
- package/TODO.md +2 -0
- package/dist/abr.d.ts +196 -196
- package/dist/abr.js +364 -378
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.d.ts +26 -26
- package/dist/additionalInfo.js +3478 -3516
- package/dist/additionalInfo.js.map +1 -1
- package/dist/ase.d.ts +32 -32
- package/dist/ase.js +81 -82
- package/dist/ase.js.map +1 -1
- package/dist/bundle.js +12380 -12445
- package/dist/csh.d.ts +10 -10
- package/dist/csh.js +35 -47
- package/dist/csh.js.map +1 -1
- package/dist/descriptor.d.ts +601 -601
- package/dist/descriptor.js +2003 -2038
- package/dist/descriptor.js.map +1 -1
- package/dist/effectsHelpers.d.ts +5 -5
- package/dist/effectsHelpers.js +286 -308
- package/dist/effectsHelpers.js.map +1 -1
- package/dist/engineData.d.ts +2 -2
- package/dist/engineData.js +334 -341
- package/dist/engineData.js.map +1 -1
- package/dist/engineData2.d.ts +2 -2
- package/dist/engineData2.js +409 -411
- package/dist/engineData2.js.map +1 -1
- package/dist/helpers.d.ts +74 -74
- package/dist/helpers.js +353 -348
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.d.ts +17 -17
- package/dist/imageResources.js +1040 -1079
- package/dist/imageResources.js.map +1 -1
- package/dist/index.d.ts +20 -22
- package/dist/index.js +61 -56
- package/dist/index.js.map +1 -1
- package/dist/initializeCanvas.d.ts +1 -1
- package/dist/initializeCanvas.js +9 -10
- package/dist/initializeCanvas.js.map +1 -1
- package/dist/jpeg.d.ts +1 -1
- package/dist/jpeg.js +1020 -1021
- package/dist/jpeg.js.map +1 -1
- package/dist/psd.d.ts +1877 -1873
- package/dist/psd.js +45 -45
- package/dist/psd.js.map +1 -1
- package/dist/psdReader.d.ts +52 -45
- package/dist/psdReader.js +1385 -1293
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +34 -33
- package/dist/psdWriter.js +834 -805
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.d.ts +179 -179
- package/dist/text.js +552 -577
- package/dist/text.js.map +1 -1
- package/dist/utf8.d.ts +4 -6
- package/dist/utf8.js +156 -157
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.d.ts +196 -196
- package/dist-es/abr.js +364 -374
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.d.ts +26 -26
- package/dist-es/additionalInfo.js +3478 -3510
- package/dist-es/additionalInfo.js.map +1 -1
- package/dist-es/ase.d.ts +32 -32
- package/dist-es/ase.js +81 -78
- package/dist-es/ase.js.map +1 -1
- package/dist-es/csh.d.ts +10 -10
- package/dist-es/csh.js +35 -43
- package/dist-es/csh.js.map +1 -1
- package/dist-es/descriptor.d.ts +601 -601
- package/dist-es/descriptor.js +2003 -2005
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/effectsHelpers.d.ts +5 -5
- package/dist-es/effectsHelpers.js +286 -303
- package/dist-es/effectsHelpers.js.map +1 -1
- package/dist-es/engineData.d.ts +2 -2
- package/dist-es/engineData.js +334 -336
- package/dist-es/engineData.js.map +1 -1
- package/dist-es/engineData2.d.ts +2 -2
- package/dist-es/engineData2.js +409 -407
- package/dist-es/engineData2.js.map +1 -1
- package/dist-es/helpers.d.ts +74 -74
- package/dist-es/helpers.js +353 -330
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.d.ts +17 -17
- package/dist-es/imageResources.js +1040 -1076
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/index.d.ts +20 -22
- package/dist-es/index.js +61 -33
- package/dist-es/index.js.map +1 -1
- package/dist-es/initializeCanvas.d.ts +1 -1
- package/dist-es/initializeCanvas.js +9 -6
- package/dist-es/initializeCanvas.js.map +1 -1
- package/dist-es/jpeg.d.ts +1 -1
- package/dist-es/jpeg.js +1020 -1017
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psd.d.ts +1877 -1873
- package/dist-es/psd.js +45 -42
- package/dist-es/psd.js.map +1 -1
- package/dist-es/psdReader.d.ts +52 -45
- package/dist-es/psdReader.js +1385 -1255
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +34 -33
- package/dist-es/psdWriter.js +834 -776
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.d.ts +179 -179
- package/dist-es/text.js +552 -572
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.d.ts +4 -6
- package/dist-es/utf8.js +156 -150
- package/dist-es/utf8.js.map +1 -1
- package/package.json +4 -3
- package/publish.js +24 -0
- package/src/additionalInfo.ts +15 -11
- package/src/helpers.ts +13 -3
- package/src/index.ts +4 -6
- package/src/psd.ts +4 -0
- package/src/psdReader.ts +136 -43
- package/src/psdWriter.ts +118 -24
- package/tsconfig-es6.json +2 -1
- package/tsconfig.json +5 -3
package/src/psd.ts
CHANGED
|
@@ -1788,6 +1788,7 @@ export interface Psd extends LayerAdditionalInfo {
|
|
|
1788
1788
|
children?: Layer[];
|
|
1789
1789
|
canvas?: HTMLCanvasElement;
|
|
1790
1790
|
imageData?: PixelData;
|
|
1791
|
+
rawCompositeData?: Uint8Array;
|
|
1791
1792
|
imageResources?: ImageResources;
|
|
1792
1793
|
linkedFiles?: LinkedFile[]; // used in smart objects
|
|
1793
1794
|
artboards?: {
|
|
@@ -1814,6 +1815,8 @@ export interface ReadOptions {
|
|
|
1814
1815
|
skipThumbnail?: boolean;
|
|
1815
1816
|
/** Does not load linked files (used in smart-objects). */
|
|
1816
1817
|
skipLinkedFilesData?: boolean;
|
|
1818
|
+
/** Total memory limit to use when decoding bitmaps (default: 2GB). */
|
|
1819
|
+
totalMemoryLimit?: number;
|
|
1817
1820
|
/** Throws exception if features are missing. */
|
|
1818
1821
|
throwForMissingFeatures?: boolean;
|
|
1819
1822
|
/** Logs if features are missing. */
|
|
@@ -1822,6 +1825,7 @@ export interface ReadOptions {
|
|
|
1822
1825
|
* (image data will appear in `imageData` fields instead of `canvas` fields)
|
|
1823
1826
|
* This avoids issues with canvas premultiplied alpha corrupting image data. */
|
|
1824
1827
|
useImageData?: boolean;
|
|
1828
|
+
/** Skips decoding layer and composite bitmaps, they can be later decoded using helper functions */
|
|
1825
1829
|
useRawData?: boolean;
|
|
1826
1830
|
/** Loads thumbnail raw data instead of decoding it's content into canvas.
|
|
1827
1831
|
* `thumnailRaw` field is used instead. */
|
package/src/psdReader.ts
CHANGED
|
@@ -234,6 +234,7 @@ export function readPsd(reader: PsdReader, readOptions: ReadOptions = {}) {
|
|
|
234
234
|
Object.assign(reader, readOptions);
|
|
235
235
|
reader.large = version === 2;
|
|
236
236
|
reader.globalAlpha = false;
|
|
237
|
+
if (!reader.totalMemoryLimit) reader.totalMemoryLimit = 2 * 1024 * 1024 * 1024; // default 2GB memory limit
|
|
237
238
|
|
|
238
239
|
// color mode data
|
|
239
240
|
readSection(reader, 1, left => {
|
|
@@ -327,7 +328,16 @@ export function readPsd(reader: PsdReader, readOptions: ReadOptions = {}) {
|
|
|
327
328
|
const skipComposite = reader.skipCompositeImageData && (reader.skipLayerImageData || hasChildren);
|
|
328
329
|
|
|
329
330
|
if (!skipComposite) {
|
|
330
|
-
|
|
331
|
+
if (reader.useRawData) {
|
|
332
|
+
psd.rawCompositeData = new Uint8Array(reader.view.buffer, reader.view.byteOffset + reader.offset);
|
|
333
|
+
} else {
|
|
334
|
+
const imageData = readImageData(reader, psd);
|
|
335
|
+
if (reader.useImageData) {
|
|
336
|
+
psd.imageData = imageData;
|
|
337
|
+
} else {
|
|
338
|
+
psd.canvas = imageDataToCanvas(imageData);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
331
341
|
}
|
|
332
342
|
|
|
333
343
|
// TODO: show converted color mode instead of original PSD file color mode
|
|
@@ -556,7 +566,7 @@ function readLayerChannelImageData(reader: PsdReader, psd: Psd, layer: Layer, ch
|
|
|
556
566
|
}
|
|
557
567
|
|
|
558
568
|
if (!reader.useRawData) {
|
|
559
|
-
decodeLayerImageData(layer,
|
|
569
|
+
decodeLayerImageData(layer, reader);
|
|
560
570
|
}
|
|
561
571
|
}
|
|
562
572
|
|
|
@@ -571,8 +581,91 @@ function resetAlpha({ data }: PixelData, cmyk: boolean) {
|
|
|
571
581
|
}
|
|
572
582
|
}
|
|
573
583
|
|
|
574
|
-
export function
|
|
575
|
-
|
|
584
|
+
export function getCompositeImageData(psd: Psd) {
|
|
585
|
+
const data = psd.rawCompositeData;
|
|
586
|
+
if (!data) return undefined;
|
|
587
|
+
|
|
588
|
+
const reader = createReader(data.buffer, data.byteOffset, data.byteLength);
|
|
589
|
+
const imageData = readImageData(reader, psd);
|
|
590
|
+
return imageData;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export function getCompositeCanvas(psd: Psd) {
|
|
594
|
+
return imageDataToCanvasSafe(getCompositeImageData(psd));
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
export function getLayerImageData(layer: Layer) {
|
|
598
|
+
return getDataFromLayer(layer, LayerDataType.Layer, false, undefined);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
export function getLayerMaskImageData(layer: Layer) {
|
|
602
|
+
return getDataFromLayer(layer, LayerDataType.Mask, false, undefined);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
export function getLayerRealMaskImageData(layer: Layer) {
|
|
606
|
+
return getDataFromLayer(layer, LayerDataType.RealMask, false, undefined);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
export function getLayerCanvas(layer: Layer) {
|
|
610
|
+
return imageDataToCanvasSafe(getLayerImageData(layer));
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
export function getLayerMaskCanvas(layer: Layer) {
|
|
614
|
+
return imageDataToCanvasSafe(getLayerMaskImageData(layer));
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
export function getLayerRealMaskCanvas(layer: Layer) {
|
|
618
|
+
return imageDataToCanvasSafe(getLayerRealMaskImageData(layer));
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
function imageDataToCanvasSafe(imageData: PixelData | undefined) {
|
|
622
|
+
return imageData && imageDataToCanvas(imageData);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
function setImageDataOrCanvas(obj: Layer | LayerMaskData, imageData: PixelData | undefined, useImageData: boolean | undefined) {
|
|
626
|
+
if (!imageData) return;
|
|
627
|
+
|
|
628
|
+
if (useImageData) {
|
|
629
|
+
obj.imageData = imageData;
|
|
630
|
+
} else {
|
|
631
|
+
obj.canvas = imageDataToCanvas(imageData);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export function decodeLayerPixels(layer: Layer, useImageData?: boolean) {
|
|
636
|
+
decodeLayerImageData(layer, { useImageData });
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
function decodeLayerImageData(layer: Layer, options: { useImageData?: boolean, throwForMissingFeatures?: boolean, memoryLimit?: number }) {
|
|
640
|
+
let { throwForMissingFeatures, useImageData } = options;
|
|
641
|
+
|
|
642
|
+
const imageData = getDataFromLayer(layer, LayerDataType.Layer, throwForMissingFeatures, options.memoryLimit);
|
|
643
|
+
setImageDataOrCanvas(layer, imageData, useImageData);
|
|
644
|
+
if (options.memoryLimit !== undefined) options.memoryLimit -= imageData?.data.byteLength ?? 0;
|
|
645
|
+
|
|
646
|
+
if (layer.mask) {
|
|
647
|
+
const maskData = getDataFromLayer(layer, LayerDataType.Mask, throwForMissingFeatures, options.memoryLimit);
|
|
648
|
+
setImageDataOrCanvas(layer.mask, maskData, useImageData);
|
|
649
|
+
if (options.memoryLimit !== undefined) options.memoryLimit -= maskData?.data.byteLength ?? 0;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
if (layer.realMask) {
|
|
653
|
+
const maskData = getDataFromLayer(layer, LayerDataType.RealMask, throwForMissingFeatures, options.memoryLimit);
|
|
654
|
+
setImageDataOrCanvas(layer.realMask, maskData, useImageData);
|
|
655
|
+
if (options.memoryLimit !== undefined) options.memoryLimit -= maskData?.data.byteLength ?? 0;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
delete layer.rawData;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
enum LayerDataType {
|
|
662
|
+
Layer,
|
|
663
|
+
Mask,
|
|
664
|
+
RealMask,
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function getDataFromLayer(layer: Layer, read: LayerDataType, throwForMissingFeatures?: boolean, memoryLimit?: number) {
|
|
668
|
+
if (!layer.rawData) return undefined;
|
|
576
669
|
|
|
577
670
|
const { colorMode, bitsPerChannel, channels, large } = layer.rawData;
|
|
578
671
|
const layerWidth = (layer.right || 0) - (layer.left || 0);
|
|
@@ -580,14 +673,15 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
|
|
|
580
673
|
const cmyk = colorMode === ColorMode.CMYK;
|
|
581
674
|
|
|
582
675
|
let imageData: PixelData | undefined;
|
|
676
|
+
let maskData: PixelData | undefined;
|
|
583
677
|
let initializedAlpha = false;
|
|
584
678
|
|
|
585
|
-
if (layerWidth && layerHeight) {
|
|
679
|
+
if (layerWidth && layerHeight && read === LayerDataType.Layer) {
|
|
586
680
|
if (cmyk) {
|
|
587
681
|
if (bitsPerChannel !== 8) throw new Error('bitsPerChannel Not supproted');
|
|
588
682
|
imageData = { width: layerWidth, height: layerHeight, data: new Uint8ClampedArray(layerWidth * layerHeight * 5) } as any as ImageData;
|
|
589
683
|
} else {
|
|
590
|
-
imageData = createImageDataBitDepth(layerWidth, layerHeight, bitsPerChannel);
|
|
684
|
+
imageData = createImageDataBitDepth(layerWidth, layerHeight, bitsPerChannel, 4, memoryLimit);
|
|
591
685
|
}
|
|
592
686
|
}
|
|
593
687
|
|
|
@@ -602,6 +696,9 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
|
|
|
602
696
|
const dataReader = createReader(data.buffer, data.byteOffset, data.byteLength);
|
|
603
697
|
|
|
604
698
|
if (id === ChannelID.UserMask || id === ChannelID.RealUserMask) {
|
|
699
|
+
if (id === ChannelID.UserMask && read !== LayerDataType.Mask) continue;
|
|
700
|
+
if (id === ChannelID.RealUserMask && read !== LayerDataType.RealMask) continue;
|
|
701
|
+
|
|
605
702
|
const mask = id === ChannelID.UserMask ? layer.mask : layer.realMask;
|
|
606
703
|
if (!mask) throw new Error(`Missing layer ${id === ChannelID.UserMask ? 'mask' : 'real mask'} data`);
|
|
607
704
|
|
|
@@ -610,10 +707,8 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
|
|
|
610
707
|
if (maskWidth < 0 || maskHeight < 0 || maskWidth > 30000 || maskHeight > 30000) throw new Error('Invalid mask size');
|
|
611
708
|
|
|
612
709
|
if (maskWidth && maskHeight) {
|
|
613
|
-
|
|
614
|
-
|
|
710
|
+
maskData = createImageDataBitDepth(maskWidth, maskHeight, bitsPerChannel, 4, memoryLimit);
|
|
615
711
|
readData(dataReader, data.byteLength, maskData, compression, maskWidth, maskHeight, bitsPerChannel, 0, large, 4);
|
|
616
|
-
|
|
617
712
|
if (RAW_IMAGE_DATA) { // TODO: use layer.rawData instead
|
|
618
713
|
if (id === ChannelID.UserMask) {
|
|
619
714
|
(layer as any).maskDataRawCompression = compression;
|
|
@@ -623,17 +718,12 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
|
|
|
623
718
|
(layer as any).realMaskDataRaw = data;
|
|
624
719
|
}
|
|
625
720
|
}
|
|
626
|
-
|
|
627
721
|
setupGrayscale(maskData);
|
|
628
722
|
resetAlpha(maskData, false);
|
|
629
|
-
|
|
630
|
-
if (useImageData) {
|
|
631
|
-
mask.imageData = maskData;
|
|
632
|
-
} else {
|
|
633
|
-
mask.canvas = imageDataToCanvas(maskData);
|
|
634
|
-
}
|
|
635
723
|
}
|
|
636
724
|
} else {
|
|
725
|
+
if (read !== LayerDataType.Layer) continue;
|
|
726
|
+
|
|
637
727
|
const offset = offsetForChannel(id, cmyk);
|
|
638
728
|
let targetData = imageData;
|
|
639
729
|
|
|
@@ -670,15 +760,9 @@ export function decodeLayerImageData(layer: Layer, useImageData?: boolean, throw
|
|
|
670
760
|
imageData = createImageData(cmykData.width, cmykData.height);
|
|
671
761
|
cmykToRgb(cmykData, imageData, false);
|
|
672
762
|
}
|
|
673
|
-
|
|
674
|
-
if (useImageData) {
|
|
675
|
-
layer.imageData = imageData;
|
|
676
|
-
} else {
|
|
677
|
-
layer.canvas = imageDataToCanvas(imageData);
|
|
678
|
-
}
|
|
679
763
|
}
|
|
680
764
|
|
|
681
|
-
|
|
765
|
+
return read === LayerDataType.Layer ? imageData : maskData;
|
|
682
766
|
}
|
|
683
767
|
|
|
684
768
|
function readData(reader: PsdReader, length: number, pixels: PixelData | undefined, compression: Compression, width: number, height: number, bitDepth: number, offset: number, large: boolean, step: number) {
|
|
@@ -774,7 +858,10 @@ export function readAdditionalLayerInfo(reader: PsdReader, target: LayerAddition
|
|
|
774
858
|
}, false, u64);
|
|
775
859
|
}
|
|
776
860
|
|
|
777
|
-
|
|
861
|
+
function createImageDataBitDepth(width: number, height: number, bitDepth: number, channels: number, memoryLimit: number | undefined): PixelData {
|
|
862
|
+
const sizeInBytes = width * height * channels * Math.max(1, bitDepth / 8);
|
|
863
|
+
if (memoryLimit !== undefined && sizeInBytes > memoryLimit) throw new Error('Exceeded memory limit');
|
|
864
|
+
|
|
778
865
|
if (bitDepth === 1 || bitDepth === 8) {
|
|
779
866
|
if (channels === 4) {
|
|
780
867
|
return createImageData(width, height);
|
|
@@ -800,7 +887,8 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
800
887
|
if (compression !== Compression.RawData && compression !== Compression.RleCompressed)
|
|
801
888
|
throw new Error(`Compression type not supported: ${compression}`);
|
|
802
889
|
|
|
803
|
-
const imageData = createImageDataBitDepth(psd.width, psd.height, bitsPerChannel);
|
|
890
|
+
const imageData = createImageDataBitDepth(psd.width, psd.height, bitsPerChannel, 4, reader.totalMemoryLimit);
|
|
891
|
+
if (reader.totalMemoryLimit !== undefined) reader.totalMemoryLimit -= imageData.data.byteLength;
|
|
804
892
|
resetImageData(imageData);
|
|
805
893
|
|
|
806
894
|
switch (psd.colorMode) {
|
|
@@ -815,7 +903,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
815
903
|
bytes = new Uint8Array(psd.width * psd.height);
|
|
816
904
|
readDataRLE(reader, { data: bytes, width: psd.width, height: psd.height }, psd.width, psd.height, 8, 1, [0], reader.large);
|
|
817
905
|
} else {
|
|
818
|
-
throw new Error(`
|
|
906
|
+
throw new Error(`Compression not supported: ${compression}`);
|
|
819
907
|
}
|
|
820
908
|
|
|
821
909
|
decodeBitmap(bytes, imageData.data, psd.width, psd.height);
|
|
@@ -843,6 +931,8 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
843
931
|
const start = reader.offset;
|
|
844
932
|
readDataRLE(reader, imageData, psd.width, psd.height, bitsPerChannel, 4, channels, reader.large);
|
|
845
933
|
if (RAW_IMAGE_DATA) (psd as any).imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
|
|
934
|
+
} else {
|
|
935
|
+
throw new Error(`Compression not supported: ${compression}`);
|
|
846
936
|
}
|
|
847
937
|
|
|
848
938
|
if (psd.colorMode === ColorMode.Grayscale) {
|
|
@@ -856,7 +946,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
856
946
|
if (!psd.palette) throw new Error('Missing color palette');
|
|
857
947
|
|
|
858
948
|
if (compression === Compression.RawData) {
|
|
859
|
-
throw new Error(`
|
|
949
|
+
throw new Error(`Compression not supported: ${compression}`);
|
|
860
950
|
} else if (compression === Compression.RleCompressed) {
|
|
861
951
|
const indexedImageData: PixelData = {
|
|
862
952
|
width: imageData.width,
|
|
@@ -866,7 +956,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
866
956
|
readDataRLE(reader, indexedImageData, psd.width, psd.height, bitsPerChannel, 1, [0], reader.large);
|
|
867
957
|
indexedToRgb(indexedImageData, imageData, psd.palette);
|
|
868
958
|
} else {
|
|
869
|
-
throw new Error(`
|
|
959
|
+
throw new Error(`Compression not supported: ${compression}`);
|
|
870
960
|
}
|
|
871
961
|
|
|
872
962
|
break;
|
|
@@ -879,7 +969,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
879
969
|
if (reader.globalAlpha) channels.push(4);
|
|
880
970
|
|
|
881
971
|
if (compression === Compression.RawData) {
|
|
882
|
-
throw new Error(`
|
|
972
|
+
throw new Error(`Compression not supported: ${compression}`);
|
|
883
973
|
// TODO: ...
|
|
884
974
|
// for (let i = 0; i < channels.length; i++) {
|
|
885
975
|
// readDataRaw(reader, imageData, channels[i], psd.width, psd.height);
|
|
@@ -897,7 +987,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
897
987
|
|
|
898
988
|
if (RAW_IMAGE_DATA) (psd as any).imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
|
|
899
989
|
} else {
|
|
900
|
-
throw new Error(`
|
|
990
|
+
throw new Error(`Compression not supported: ${compression}`);
|
|
901
991
|
}
|
|
902
992
|
|
|
903
993
|
break;
|
|
@@ -923,11 +1013,7 @@ function readImageData(reader: PsdReader, psd: Psd) {
|
|
|
923
1013
|
}
|
|
924
1014
|
}
|
|
925
1015
|
|
|
926
|
-
|
|
927
|
-
psd.imageData = imageData;
|
|
928
|
-
} else {
|
|
929
|
-
psd.canvas = imageDataToCanvas(imageData);
|
|
930
|
-
}
|
|
1016
|
+
return imageData;
|
|
931
1017
|
}
|
|
932
1018
|
|
|
933
1019
|
function cmykToRgb(cmyk: PixelData, rgb: PixelData, reverseAlpha: boolean) {
|
|
@@ -1310,9 +1396,7 @@ export function readPattern(reader: PsdReader): PatternInfo {
|
|
|
1310
1396
|
data[dst + ch] = cdata[src];
|
|
1311
1397
|
}
|
|
1312
1398
|
}
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
|
-
if (colorMode === ColorMode.Grayscale && ch < 1) {
|
|
1399
|
+
} else if (colorMode === ColorMode.Grayscale && ch < 1) {
|
|
1316
1400
|
for (let y = 0; y < h; y++) {
|
|
1317
1401
|
for (let x = 0; x < w; x++) {
|
|
1318
1402
|
const src = x + y * w;
|
|
@@ -1323,11 +1407,20 @@ export function readPattern(reader: PsdReader): PatternInfo {
|
|
|
1323
1407
|
data[dst + 2] = value;
|
|
1324
1408
|
}
|
|
1325
1409
|
}
|
|
1326
|
-
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1410
|
+
} else if (colorMode === ColorMode.Indexed) {
|
|
1411
|
+
for (let y = 0; y < h; y++) {
|
|
1412
|
+
for (let x = 0; x < w; x++) {
|
|
1413
|
+
const src = x + y * w;
|
|
1414
|
+
const dst = (ox + x + (y + oy) * width) * 4;
|
|
1415
|
+
const index = cdata[src];
|
|
1416
|
+
const color = palette[index];
|
|
1417
|
+
data[dst + 0] = color.r;
|
|
1418
|
+
data[dst + 1] = color.g;
|
|
1419
|
+
data[dst + 2] = color.b;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
} else {
|
|
1423
|
+
if (reader.throwForMissingFeatures) throw new Error('Invalid color pattern');
|
|
1331
1424
|
}
|
|
1332
1425
|
} else if (compressionMode === 1) {
|
|
1333
1426
|
const pixelData: PixelData = { data, width, height };
|
package/src/psdWriter.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Psd, Layer, LayerAdditionalInfo, ColorMode, SectionDividerType, WriteOptions, Color, GlobalLayerMaskInfo, PixelData, LayerMaskData, Compression, ChannelID } from './psd';
|
|
1
|
+
import { Psd, Layer, LayerAdditionalInfo, ColorMode, SectionDividerType, WriteOptions, Color, GlobalLayerMaskInfo, PixelData, LayerMaskData, Compression, ChannelID, PatternInfo } from './psd';
|
|
2
2
|
import { hasAlpha, createCanvas, writeDataRLE, LayerChannelData, ChannelData, offsetForChannel, createImageData, fromBlendMode, clamp, LayerMaskFlags, MaskParams, ColorSpace, Bounds, largeAdditionalInfoKeys, RAW_IMAGE_DATA, writeDataZipWithoutPrediction, imageDataToCanvas } from './helpers';
|
|
3
3
|
import { ExtendedWriteOptions, infoHandlers } from './additionalInfo';
|
|
4
4
|
import { InternalImageResources, resourceHandlers } from './imageResources';
|
|
@@ -348,7 +348,7 @@ function writeLayerInfo(writer: PsdWriter, layers: Layer[], psd: Psd, globalAlph
|
|
|
348
348
|
writeUint16(writer, channels.length);
|
|
349
349
|
|
|
350
350
|
for (const c of channels) {
|
|
351
|
-
writeInt16(writer, c.
|
|
351
|
+
writeInt16(writer, c.id);
|
|
352
352
|
if (options.psb) writeUint32(writer, 0);
|
|
353
353
|
writeUint32(writer, c.length);
|
|
354
354
|
}
|
|
@@ -381,8 +381,8 @@ function writeLayerInfo(writer: PsdWriter, layers: Layer[], psd: Psd, globalAlph
|
|
|
381
381
|
for (const channel of layerData.channels) {
|
|
382
382
|
writeUint16(writer, channel.compression);
|
|
383
383
|
|
|
384
|
-
if (channel.
|
|
385
|
-
writeBytes(writer, channel.
|
|
384
|
+
if (channel.data) {
|
|
385
|
+
writeBytes(writer, channel.data);
|
|
386
386
|
}
|
|
387
387
|
}
|
|
388
388
|
}
|
|
@@ -635,12 +635,31 @@ function getMaskChannels(tempBuffer: Uint8Array, layerData: LayerChannelData, la
|
|
|
635
635
|
compression = Compression.RleCompressed;
|
|
636
636
|
}
|
|
637
637
|
|
|
638
|
-
layerData.channels.push({
|
|
638
|
+
layerData.channels.push({ id: realMask ? ChannelID.RealUserMask : ChannelID.UserMask, compression, data: buffer, length: 2 + buffer.length });
|
|
639
639
|
|
|
640
640
|
layerData[realMask ? 'realMask' : 'mask'] = { top, left, right, bottom };
|
|
641
641
|
}
|
|
642
642
|
|
|
643
|
+
function bounds(obj: { top?: number; left?: number; bottom?: number; right?: number; } | undefined) {
|
|
644
|
+
return obj ? {
|
|
645
|
+
top: obj.top || 0,
|
|
646
|
+
left: obj.left || 0,
|
|
647
|
+
right: obj.right || 0,
|
|
648
|
+
bottom: obj.bottom || 0,
|
|
649
|
+
} : undefined;
|
|
650
|
+
}
|
|
651
|
+
|
|
643
652
|
function getChannels(tempBuffer: Uint8Array, layer: Layer, background: boolean, options: WriteOptions): LayerChannelData {
|
|
653
|
+
if (layer.rawData) {
|
|
654
|
+
return {
|
|
655
|
+
layer,
|
|
656
|
+
channels: layer.rawData.channels.map(c => ({ ...c, length: 2 + (c.data?.byteLength ?? 0) })),
|
|
657
|
+
...bounds(layer)!,
|
|
658
|
+
mask: bounds(layer.mask),
|
|
659
|
+
realMask: bounds(layer.realMask),
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
|
|
644
663
|
const layerData = getLayerChannels(tempBuffer, layer, background, options);
|
|
645
664
|
if (layer.mask) getMaskChannels(tempBuffer, layerData, layer, layer.mask, options, false);
|
|
646
665
|
if (layer.realMask) getMaskChannels(tempBuffer, layerData, layer, layer.realMask, options, true);
|
|
@@ -683,10 +702,10 @@ function getLayerChannels(tempBuffer: Uint8Array, layer: Layer, background: bool
|
|
|
683
702
|
let right = (layer.right as any) | 0;
|
|
684
703
|
let bottom = (layer.bottom as any) | 0;
|
|
685
704
|
let channels: ChannelData[] = [
|
|
686
|
-
{
|
|
687
|
-
{
|
|
688
|
-
{
|
|
689
|
-
{
|
|
705
|
+
{ id: ChannelID.Transparency, compression: Compression.RawData, data: undefined, length: 2 },
|
|
706
|
+
{ id: ChannelID.Color0, compression: Compression.RawData, data: undefined, length: 2 },
|
|
707
|
+
{ id: ChannelID.Color1, compression: Compression.RawData, data: undefined, length: 2 },
|
|
708
|
+
{ id: ChannelID.Color2, compression: Compression.RawData, data: undefined, length: 2 },
|
|
690
709
|
];
|
|
691
710
|
let { width, height } = getLayerDimentions(layer);
|
|
692
711
|
|
|
@@ -699,22 +718,22 @@ function getLayerChannels(tempBuffer: Uint8Array, layer: Layer, background: bool
|
|
|
699
718
|
right = left + width;
|
|
700
719
|
bottom = top + height;
|
|
701
720
|
|
|
702
|
-
let
|
|
721
|
+
let imageData = layer.imageData || layer.canvas!.getContext('2d')!.getImageData(0, 0, width, height);
|
|
703
722
|
|
|
704
723
|
if (options.trimImageData) {
|
|
705
|
-
const trimmed = trimData(
|
|
724
|
+
const trimmed = trimData(imageData);
|
|
706
725
|
|
|
707
|
-
if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !==
|
|
726
|
+
if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== imageData.width || trimmed.bottom !== imageData.height) {
|
|
708
727
|
left += trimmed.left;
|
|
709
728
|
top += trimmed.top;
|
|
710
|
-
right -= (
|
|
711
|
-
bottom -= (
|
|
729
|
+
right -= (imageData.width - trimmed.right);
|
|
730
|
+
bottom -= (imageData.height - trimmed.bottom);
|
|
712
731
|
width = right - left;
|
|
713
732
|
height = bottom - top;
|
|
714
733
|
|
|
715
734
|
if (!width || !height) return { layer, top, left, right, bottom, channels };
|
|
716
735
|
|
|
717
|
-
|
|
736
|
+
imageData = cropImageData(imageData, trimmed.left, trimmed.top, width, height);
|
|
718
737
|
}
|
|
719
738
|
}
|
|
720
739
|
|
|
@@ -724,28 +743,28 @@ function getLayerChannels(tempBuffer: Uint8Array, layer: Layer, background: bool
|
|
|
724
743
|
ChannelID.Color2,
|
|
725
744
|
];
|
|
726
745
|
|
|
727
|
-
if (!background || options.noBackground || layer.mask || hasAlpha(
|
|
746
|
+
if (!background || options.noBackground || layer.mask || hasAlpha(imageData) || (RAW_IMAGE_DATA && (layer as any).imageDataRaw?.['-1'])) {
|
|
728
747
|
channelIds.unshift(ChannelID.Transparency);
|
|
729
748
|
}
|
|
730
749
|
|
|
731
|
-
channels = channelIds.map(
|
|
732
|
-
const offset = offsetForChannel(
|
|
733
|
-
let
|
|
750
|
+
channels = channelIds.map(id => {
|
|
751
|
+
const offset = offsetForChannel(id, false); // TODO: psd.colorMode === ColorMode.CMYK);
|
|
752
|
+
let data: Uint8Array;
|
|
734
753
|
let compression: Compression;
|
|
735
754
|
|
|
736
755
|
if (RAW_IMAGE_DATA && (layer as any).imageDataRaw) {
|
|
737
756
|
// console.log('written raw layer image data');
|
|
738
|
-
|
|
739
|
-
compression = (layer as any).imageDataRawCompression[
|
|
757
|
+
data = (layer as any).imageDataRaw[id];
|
|
758
|
+
compression = (layer as any).imageDataRawCompression[id];
|
|
740
759
|
} else if (options.compress) {
|
|
741
|
-
|
|
760
|
+
data = writeDataZipWithoutPrediction(imageData, [offset]);
|
|
742
761
|
compression = Compression.ZipWithoutPrediction;
|
|
743
762
|
} else {
|
|
744
|
-
|
|
763
|
+
data = writeDataRLE(tempBuffer, imageData, [offset], !!options.psb)!;
|
|
745
764
|
compression = Compression.RleCompressed;
|
|
746
765
|
}
|
|
747
766
|
|
|
748
|
-
return {
|
|
767
|
+
return { id, compression, data, length: 2 + data.length };
|
|
749
768
|
});
|
|
750
769
|
|
|
751
770
|
return { layer, top, left, right, bottom, channels };
|
|
@@ -835,3 +854,78 @@ export function writeColor(writer: PsdWriter, color: Color | undefined) {
|
|
|
835
854
|
writeZeros(writer, 6);
|
|
836
855
|
}
|
|
837
856
|
}
|
|
857
|
+
|
|
858
|
+
// ponytail: only round-trips RGB 8-bit patterns; source colorMode (16-bit/Indexed) is not preserved,
|
|
859
|
+
// since readPattern already converted everything to RGBA. Upgrade if pattern colorMode must survive write.
|
|
860
|
+
export function writePattern(writer: PsdWriter, pattern: PatternInfo) {
|
|
861
|
+
const width = pattern.bounds.w;
|
|
862
|
+
const height = pattern.bounds.h;
|
|
863
|
+
const pixelData: PixelData = { width, height, data: pattern.data };
|
|
864
|
+
|
|
865
|
+
writeUint32(writer, 0); // length, fixed up below
|
|
866
|
+
const pattsOffset = writer.offset;
|
|
867
|
+
|
|
868
|
+
writeUint32(writer, 1); // version
|
|
869
|
+
writeUint32(writer, ColorMode.RGB); // color mode - rgb only
|
|
870
|
+
|
|
871
|
+
writeInt16(writer, pattern.x);
|
|
872
|
+
writeInt16(writer, pattern.y);
|
|
873
|
+
|
|
874
|
+
writeUnicodeString(writer, pattern.name + '\0'); // name
|
|
875
|
+
writePascalString(writer, pattern.id, 1); // id
|
|
876
|
+
|
|
877
|
+
// virtual memory array list
|
|
878
|
+
writeUint32(writer, 3); // version
|
|
879
|
+
writeUint32(writer, 0); // length, fixed up below
|
|
880
|
+
const vlOffset = writer.offset;
|
|
881
|
+
|
|
882
|
+
const top = pattern.bounds.y;
|
|
883
|
+
const left = pattern.bounds.x;
|
|
884
|
+
const bottom = top + height;
|
|
885
|
+
const right = left + width;
|
|
886
|
+
|
|
887
|
+
writeUint32(writer, top);
|
|
888
|
+
writeUint32(writer, left);
|
|
889
|
+
writeUint32(writer, bottom);
|
|
890
|
+
writeUint32(writer, right);
|
|
891
|
+
|
|
892
|
+
writeUint32(writer, 24); // channels count
|
|
893
|
+
|
|
894
|
+
// channels: RGB at indices 0,1,2 and alpha at index 25
|
|
895
|
+
for (let i = 0; i < 24 + 2; i++) {
|
|
896
|
+
const offset = i < 3 ? i : (i === 25 ? 3 : -1);
|
|
897
|
+
|
|
898
|
+
if (offset < 0) {
|
|
899
|
+
writeUint32(writer, 0); // has
|
|
900
|
+
continue;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
// worst-case RLE size for a single channel: width + 1 per scanline, plus scanline length headers
|
|
904
|
+
const buffer = new Uint8Array(width * height + 2 * height + 2 * width + 16);
|
|
905
|
+
// ponytail: pattern channels always use small (2-byte) RLE scanline headers, matching
|
|
906
|
+
// readPattern which reads them as non-large; `large` here only affects the header width.
|
|
907
|
+
const data = writeDataRLE(buffer, pixelData, [offset], false)!;
|
|
908
|
+
|
|
909
|
+
writeUint32(writer, 1); // has
|
|
910
|
+
writeUint32(writer, data.length + 4 + 16 + 2 + 1); // length
|
|
911
|
+
writeUint32(writer, 8); // pixelDepth
|
|
912
|
+
writeUint32(writer, top);
|
|
913
|
+
writeUint32(writer, left);
|
|
914
|
+
writeUint32(writer, bottom);
|
|
915
|
+
writeUint32(writer, right);
|
|
916
|
+
writeUint16(writer, 8); // pixelDepth2
|
|
917
|
+
writeUint8(writer, 1); // compressionMode - rle
|
|
918
|
+
writeBytes(writer, data);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
const vlLength = writer.offset - vlOffset;
|
|
922
|
+
let pattsLength = writer.offset - pattsOffset;
|
|
923
|
+
|
|
924
|
+
while (pattsLength % 4) {
|
|
925
|
+
writeZeros(writer, 1);
|
|
926
|
+
pattsLength++;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
writer.view.setUint32(vlOffset - 4, vlLength, false);
|
|
930
|
+
writer.view.setUint32(pattsOffset - 4, pattsLength, false);
|
|
931
|
+
}
|
package/tsconfig-es6.json
CHANGED
package/tsconfig.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
|
-
"moduleResolution": "
|
|
4
|
-
"target": "
|
|
5
|
-
"module": "
|
|
3
|
+
"moduleResolution": "node16",
|
|
4
|
+
"target": "es2016",
|
|
5
|
+
"module": "node16",
|
|
6
6
|
"lib": ["es2016", "dom"],
|
|
7
7
|
"noUnusedLocals": true,
|
|
8
8
|
"noUnusedParameters": true,
|
|
9
9
|
"preserveConstEnums": true,
|
|
10
10
|
"declaration": true,
|
|
11
11
|
"useUnknownInCatchVariables": false,
|
|
12
|
+
"types": ["node", "mocha"],
|
|
12
13
|
"strict": true,
|
|
13
14
|
"sourceMap": true,
|
|
14
15
|
"sourceRoot": "../src",
|
|
16
|
+
"rootDir": "src",
|
|
15
17
|
"outDir": "dist"
|
|
16
18
|
},
|
|
17
19
|
"include": [
|