ag-psd 32.0.0 → 33.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 (103) hide show
  1. package/.v8-cache/v24.7.0-x64-ef5a0af0/03e19709 +0 -0
  2. package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
  3. package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
  4. package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
  5. package/.v8-cache/v24.7.0-x64-ef5a0af0/2a19133e +0 -0
  6. package/.v8-cache/v24.7.0-x64-ef5a0af0/4511bacf +0 -0
  7. package/.v8-cache/v24.7.0-x64-ef5a0af0/68416cb2 +0 -0
  8. package/.v8-cache/v24.7.0-x64-ef5a0af0/71df9cb3 +0 -0
  9. package/.v8-cache/v24.7.0-x64-ef5a0af0/7ea06cea +0 -0
  10. package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
  11. package/.v8-cache/v24.7.0-x64-ef5a0af0/acc36e66 +0 -0
  12. package/.v8-cache/v24.7.0-x64-ef5a0af0/b3c2fab7 +0 -0
  13. package/.v8-cache/v24.7.0-x64-ef5a0af0/c314aece +0 -0
  14. package/.v8-cache/v24.7.0-x64-ef5a0af0/cfc49f4f +0 -0
  15. package/.v8-cache/v24.7.0-x64-ef5a0af0/cff9434a +0 -0
  16. package/.v8-cache/v24.7.0-x64-ef5a0af0/dc86f000 +0 -0
  17. package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +0 -0
  18. package/.v8-cache/v24.7.0-x64-ef5a0af0/e6745c2b +0 -0
  19. package/.v8-cache/v24.7.0-x64-ef5a0af0/e6b99945 +0 -0
  20. package/.v8-cache/v24.7.0-x64-ef5a0af0/eeeebdfe +0 -0
  21. package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
  22. package/CHANGELOG.md +78 -0
  23. package/LICENSE +5 -0
  24. package/README.md +3 -6
  25. package/README_PSD.md +242 -81
  26. package/dist/abr.d.ts +11 -4
  27. package/dist/abr.js +357 -230
  28. package/dist/abr.js.map +1 -1
  29. package/dist/additionalInfo.d.ts +54 -2
  30. package/dist/additionalInfo.js +487 -306
  31. package/dist/additionalInfo.js.map +1 -1
  32. package/dist/ase.d.ts +6 -1
  33. package/dist/ase.js +61 -61
  34. package/dist/ase.js.map +1 -1
  35. package/dist/bundle.js +1937 -1115
  36. package/dist/descriptor.d.ts +14 -8
  37. package/dist/descriptor.js +202 -186
  38. package/dist/descriptor.js.map +1 -1
  39. package/dist/helpers.d.ts +1 -1
  40. package/dist/helpers.js +4 -2
  41. package/dist/helpers.js.map +1 -1
  42. package/dist/imageResources.d.ts +15 -3
  43. package/dist/imageResources.js +503 -142
  44. package/dist/imageResources.js.map +1 -1
  45. package/dist/jpeg.js +8 -8
  46. package/dist/jpeg.js.map +1 -1
  47. package/dist/psd.d.ts +148 -17
  48. package/dist/psd.js.map +1 -1
  49. package/dist/psdReader.d.ts +10 -0
  50. package/dist/psdReader.js +278 -166
  51. package/dist/psdReader.js.map +1 -1
  52. package/dist/psdWriter.d.ts +1 -0
  53. package/dist/psdWriter.js +77 -62
  54. package/dist/psdWriter.js.map +1 -1
  55. package/dist/text.js +17 -6
  56. package/dist/text.js.map +1 -1
  57. package/dist/utf8.js +0 -3
  58. package/dist/utf8.js.map +1 -1
  59. package/dist-es/abr.d.ts +11 -4
  60. package/dist-es/abr.js +357 -230
  61. package/dist-es/abr.js.map +1 -1
  62. package/dist-es/additionalInfo.d.ts +54 -2
  63. package/dist-es/additionalInfo.js +487 -306
  64. package/dist-es/additionalInfo.js.map +1 -1
  65. package/dist-es/ase.d.ts +6 -1
  66. package/dist-es/ase.js +61 -61
  67. package/dist-es/ase.js.map +1 -1
  68. package/dist-es/descriptor.d.ts +14 -8
  69. package/dist-es/descriptor.js +202 -186
  70. package/dist-es/descriptor.js.map +1 -1
  71. package/dist-es/helpers.d.ts +1 -1
  72. package/dist-es/helpers.js +4 -2
  73. package/dist-es/helpers.js.map +1 -1
  74. package/dist-es/imageResources.d.ts +15 -3
  75. package/dist-es/imageResources.js +503 -142
  76. package/dist-es/imageResources.js.map +1 -1
  77. package/dist-es/jpeg.js +8 -8
  78. package/dist-es/jpeg.js.map +1 -1
  79. package/dist-es/psd.d.ts +148 -17
  80. package/dist-es/psd.js.map +1 -1
  81. package/dist-es/psdReader.d.ts +10 -0
  82. package/dist-es/psdReader.js +278 -166
  83. package/dist-es/psdReader.js.map +1 -1
  84. package/dist-es/psdWriter.d.ts +1 -0
  85. package/dist-es/psdWriter.js +77 -62
  86. package/dist-es/psdWriter.js.map +1 -1
  87. package/dist-es/text.js +17 -6
  88. package/dist-es/text.js.map +1 -1
  89. package/dist-es/utf8.js +0 -3
  90. package/dist-es/utf8.js.map +1 -1
  91. package/package.json +2 -2
  92. package/src/abr.ts +375 -235
  93. package/src/additionalInfo.ts +663 -420
  94. package/src/ase.ts +66 -61
  95. package/src/descriptor.ts +199 -195
  96. package/src/helpers.ts +4 -1
  97. package/src/imageResources.ts +632 -168
  98. package/src/jpeg.ts +8 -8
  99. package/src/psd.ts +156 -30
  100. package/src/psdReader.ts +273 -172
  101. package/src/psdWriter.ts +95 -58
  102. package/src/text.ts +17 -6
  103. package/src/utf8.ts +0 -4
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resourceHandlersMap = exports.resourceHandlers = void 0;
4
4
  const base64_js_1 = require("base64-js");
5
+ const additionalInfo_1 = require("./additionalInfo");
5
6
  const psdReader_1 = require("./psdReader");
6
7
  const psdWriter_1 = require("./psdWriter");
7
8
  const helpers_1 = require("./helpers");
@@ -9,10 +10,12 @@ const utf8_1 = require("./utf8");
9
10
  const descriptor_1 = require("./descriptor");
10
11
  exports.resourceHandlers = [];
11
12
  exports.resourceHandlersMap = {};
12
- function addHandler(key, has, read, write) {
13
- const handler = { key, has, read, write };
13
+ function addHandler(key, has, read, write, options = {}) {
14
+ var _a;
15
+ const handler = { key, keyCount: (_a = options.keyCount) !== null && _a !== void 0 ? _a : 1, has, read, write, name: options.name };
14
16
  exports.resourceHandlers.push(handler);
15
- exports.resourceHandlersMap[handler.key] = handler;
17
+ for (let i = 0; i < handler.keyCount; i++)
18
+ exports.resourceHandlersMap[handler.key + i] = handler;
16
19
  }
17
20
  const LOG_MOCK_HANDLERS = false;
18
21
  const RESOLUTION_UNITS = [undefined, 'PPI', 'PPCM'];
@@ -30,27 +33,18 @@ function byteAt(value, index) {
30
33
  }
31
34
  function readUtf8String(reader, length) {
32
35
  const buffer = (0, psdReader_1.readBytes)(reader, length);
33
- return (0, utf8_1.decodeString)(buffer);
36
+ return (0, psdReader_1.decodeUtf8)(reader, buffer);
34
37
  }
35
38
  function writeUtf8String(writer, value) {
36
39
  const buffer = (0, utf8_1.encodeString)(value);
37
40
  (0, psdWriter_1.writeBytes)(writer, buffer);
38
41
  }
39
- let gbkDecoder;
40
- function getGbkDecoder() {
41
- if (gbkDecoder === undefined) {
42
- try {
43
- gbkDecoder = new TextDecoder('gbk');
44
- }
45
- catch (_a) {
46
- gbkDecoder = null;
47
- }
48
- }
49
- return gbkDecoder;
50
- }
51
42
  function readEncodedString(reader) {
52
43
  const length = (0, psdReader_1.readUint8)(reader);
53
44
  const buffer = (0, psdReader_1.readBytes)(reader, length);
45
+ return decodeEncodedString(reader, buffer);
46
+ }
47
+ function decodeEncodedString(reader, buffer) {
54
48
  let notAscii = false;
55
49
  for (let i = 0; i < buffer.byteLength; i++) {
56
50
  if (buffer[i] & 0x80) {
@@ -59,17 +53,20 @@ function readEncodedString(reader) {
59
53
  }
60
54
  }
61
55
  if (notAscii) {
62
- const decoder = getGbkDecoder();
63
- if (decoder) {
64
- try {
65
- return decoder.decode(buffer);
56
+ // encoding is ambiguous, many GBK strings are also valid UTF-8 and vice versa, GBK is preferred,
57
+ // UTF-8 is only used if the string is not valid GBK
58
+ for (const decoder of [(0, psdReader_1.getGbkStrictDecoder)(reader), (0, psdReader_1.getUtf8StrictDecoder)(reader)]) {
59
+ if (decoder) {
60
+ try {
61
+ return decoder.decode(buffer);
62
+ }
63
+ catch (_a) { }
66
64
  }
67
- catch (_a) { }
68
65
  }
69
66
  }
70
- return (0, utf8_1.decodeString)(buffer);
67
+ return (0, psdReader_1.decodeUtf8)(reader, buffer);
71
68
  }
72
- function writeEncodedString(writer, value) {
69
+ function toShortAsciiString(value) {
73
70
  let ascii = '';
74
71
  for (let i = 0; i < value.length;) {
75
72
  const code = value.codePointAt(i);
@@ -77,19 +74,19 @@ function writeEncodedString(writer, value) {
77
74
  i += code > 0xffff ? 2 : 1; // skip low surrogate of astral characters
78
75
  }
79
76
  // length is stored in a single byte
80
- if (ascii.length > 255)
81
- ascii = ascii.substring(0, 255);
82
- const buffer = (0, utf8_1.encodeString)(ascii);
77
+ return ascii.length > 255 ? ascii.substring(0, 255) : ascii;
78
+ }
79
+ function writeEncodedString(writer, value) {
80
+ const buffer = (0, utf8_1.encodeString)(toShortAsciiString(value));
83
81
  (0, psdWriter_1.writeUint8)(writer, buffer.byteLength);
84
82
  (0, psdWriter_1.writeBytes)(writer, buffer);
85
83
  }
86
- helpers_1.MOCK_HANDLERS && addHandler(1028, // IPTC-NAA record
84
+ addHandler(1028, // IPTC-NAA record
87
85
  // IPTC-NAA record
88
- target => target._ir1028 !== undefined, (reader, target, left) => {
89
- LOG_MOCK_HANDLERS && console.log('image resource 1028', left());
90
- target._ir1028 = (0, psdReader_1.readBytes)(reader, left());
86
+ target => target.iptcData !== undefined, (reader, target, left) => {
87
+ target.iptcData = (0, psdReader_1.readBytes)(reader, left());
91
88
  }, (writer, target) => {
92
- (0, psdWriter_1.writeBytes)(writer, target._ir1028);
89
+ (0, psdWriter_1.writeBytes)(writer, target.iptcData);
93
90
  });
94
91
  addHandler(1061, target => target.captionDigest !== undefined, (reader, target) => {
95
92
  let captionDigest = '';
@@ -115,12 +112,12 @@ const Inte = (0, helpers_1.createEnum)('Inte', 'perceptual', {
115
112
  'relative colorimetric': 'Clrm',
116
113
  'absolute colorimetric': 'AClr',
117
114
  });
118
- helpers_1.MOCK_HANDLERS && addHandler(1085, // Windows DEVMODE. Variable OS specific info for Windows.
115
+ addHandler(1085, // Windows DEVMODE. Variable OS specific info for Windows.
119
116
  // Windows DEVMODE. Variable OS specific info for Windows.
120
- target => target._ir1085 !== undefined, (reader, target, left) => {
121
- target._ir1085 = (0, psdReader_1.readBytes)(reader, left());
117
+ target => target.windowsDevMode !== undefined, (reader, target, left) => {
118
+ target.windowsDevMode = (0, psdReader_1.readBytes)(reader, left());
122
119
  }, (writer, target) => {
123
- (0, psdWriter_1.writeBytes)(writer, target._ir1085);
120
+ (0, psdWriter_1.writeBytes)(writer, target.windowsDevMode);
124
121
  });
125
122
  addHandler(1082, target => target.printInformation !== undefined, (reader, target) => {
126
123
  var _a, _b;
@@ -132,6 +129,8 @@ addHandler(1082, target => target.printInformation !== undefined, (reader, targe
132
129
  const info = target.printInformation;
133
130
  if (desc.PstS !== undefined)
134
131
  info.printerManagesColors = desc.PstS;
132
+ if (desc.ClrS === 'ClrS.Grys')
133
+ info.printerProfileColorSpace = 'grayscale';
135
134
  if (desc['Nm '] !== undefined)
136
135
  info.printerProfile = desc['Nm '];
137
136
  if (desc.MpBl !== undefined)
@@ -154,7 +153,6 @@ addHandler(1082, target => target.printInformation !== undefined, (reader, targe
154
153
  }
155
154
  }
156
155
  }, (writer, target) => {
157
- var _a, _b;
158
156
  const info = target.printInformation;
159
157
  const desc = {};
160
158
  if (info.printerManagesColors) {
@@ -163,11 +161,12 @@ addHandler(1082, target => target.printInformation !== undefined, (reader, targe
163
161
  else {
164
162
  if (info.hardProof !== undefined)
165
163
  desc.hardProof = !!info.hardProof;
166
- desc.ClrS = 'ClrS.RGBC'; // TODO: ???
167
- desc['Nm '] = (_a = info.printerProfile) !== null && _a !== void 0 ? _a : 'CIE RGB';
164
+ desc.ClrS = info.printerProfileColorSpace === 'grayscale' ? 'ClrS.Grys' : 'ClrS.RGBC';
165
+ if (info.printerProfile !== undefined)
166
+ desc['Nm '] = info.printerProfile;
168
167
  }
169
168
  desc.Inte = Inte.encode(info.renderingIntent);
170
- if (!info.printerManagesColors)
169
+ if (!info.printerManagesColors && info.blackPointCompensation !== undefined)
171
170
  desc.MpBl = !!info.blackPointCompensation;
172
171
  desc.printSixteenBit = !!info.printSixteenBit;
173
172
  desc.printerName = info.printerName || '';
@@ -179,23 +178,77 @@ addHandler(1082, target => target.printInformation !== undefined, (reader, targe
179
178
  paperWhite: !!info.proofSetup.paperWhite,
180
179
  };
181
180
  }
182
- else {
181
+ else if (info.proofSetup) {
183
182
  desc.printProofSetup = {
184
- Bltn: ((_b = info.proofSetup) === null || _b === void 0 ? void 0 : _b.builtin) ? `builtinProof.${info.proofSetup.builtin}` : 'builtinProof.proofCMYK',
183
+ Bltn: `builtinProof.${info.proofSetup.builtin || 'proofCMYK'}`,
185
184
  };
186
185
  }
187
186
  (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'printOutput', desc);
188
187
  });
189
- helpers_1.MOCK_HANDLERS && addHandler(1083, // Print style
188
+ addHandler(1083, // Print style
190
189
  // Print style
191
- target => target._ir1083 !== undefined, (reader, target, left) => {
192
- LOG_MOCK_HANDLERS && console.log('image resource 1083', left());
193
- target._ir1083 = (0, psdReader_1.readBytes)(reader, left());
194
- // TODO:
195
- // const desc = readVersionAndDescriptor(reader);
196
- // console.log('1083', require('util').inspect(desc, false, 99, true));
190
+ target => target.printStyle !== undefined, (reader, target) => {
191
+ const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
192
+ target.printStyle = {
193
+ caption: desc.Cptn,
194
+ calibrationBars: desc.Clbr,
195
+ registrationMarks: desc.RgsM,
196
+ cornerCropMarks: desc.CrnC,
197
+ centerCropMarks: desc.CntC,
198
+ labels: desc.Lbls,
199
+ negative: desc.Ngtv,
200
+ emulsionDown: desc.EmlD,
201
+ interpolate: desc.Intr,
202
+ backgroundColor: (0, descriptor_1.parseColor)(desc.Bckg),
203
+ border: (0, descriptor_1.parseUnits)(desc.BrdT),
204
+ bleed: (0, descriptor_1.parseUnits)(desc['Bld ']),
205
+ resolution: (0, descriptor_1.parseUnits)(desc.Rslt),
206
+ vectorData: desc.vectorData,
207
+ pagePosition: desc.PgPs === 'PgPs.PgPC' ? 'centered' : desc.PgPs,
208
+ left: (0, descriptor_1.parseUnits)(desc.Left),
209
+ top: (0, descriptor_1.parseUnits)(desc['Top ']),
210
+ scale: (0, descriptor_1.parsePercent)(desc['Scl ']),
211
+ };
212
+ if (desc.cropWhenPrinting !== undefined) {
213
+ target.printStyle.cropWhenPrinting = desc.cropWhenPrinting;
214
+ target.printStyle.cropRect = {
215
+ top: desc.cropRectTop || 0,
216
+ left: desc.cropRectLeft || 0,
217
+ bottom: desc.cropRectBottom || 0,
218
+ right: desc.cropRectRight || 0,
219
+ };
220
+ }
197
221
  }, (writer, target) => {
198
- (0, psdWriter_1.writeBytes)(writer, target._ir1083);
222
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
223
+ const style = target.printStyle;
224
+ const desc = {
225
+ Cptn: !!style.caption,
226
+ Clbr: !!style.calibrationBars,
227
+ RgsM: !!style.registrationMarks,
228
+ CrnC: !!style.cornerCropMarks,
229
+ CntC: !!style.centerCropMarks,
230
+ Lbls: !!style.labels,
231
+ Ngtv: !!style.negative,
232
+ EmlD: !!style.emulsionDown,
233
+ Intr: !!style.interpolate,
234
+ Bckg: (0, descriptor_1.serializeColor)(style.backgroundColor || { r: 255, g: 255, b: 255 }),
235
+ BrdT: (0, descriptor_1.unitsValue)(style.border || { units: 'Distance', value: 0 }, 'border'),
236
+ 'Bld ': (0, descriptor_1.unitsValue)(style.bleed || { units: 'Distance', value: 0 }, 'bleed'),
237
+ Rslt: (0, descriptor_1.unitsValue)(style.resolution || { units: 'Pixels', value: 72 }, 'resolution'),
238
+ vectorData: (_a = style.vectorData) !== null && _a !== void 0 ? _a : true,
239
+ PgPs: (!style.pagePosition || style.pagePosition === 'centered') ? 'PgPs.PgPC' : style.pagePosition,
240
+ Left: (0, descriptor_1.unitsValue)(style.left || { units: 'Distance', value: 0 }, 'left'),
241
+ 'Top ': (0, descriptor_1.unitsValue)(style.top || { units: 'Distance', value: 0 }, 'top'),
242
+ 'Scl ': (0, descriptor_1.unitsPercentF)((_b = style.scale) !== null && _b !== void 0 ? _b : 1),
243
+ };
244
+ if (style.cropWhenPrinting !== undefined || style.cropRect) {
245
+ desc.cropWhenPrinting = !!style.cropWhenPrinting;
246
+ desc.cropRectBottom = (_d = (_c = style.cropRect) === null || _c === void 0 ? void 0 : _c.bottom) !== null && _d !== void 0 ? _d : 0;
247
+ desc.cropRectLeft = (_f = (_e = style.cropRect) === null || _e === void 0 ? void 0 : _e.left) !== null && _f !== void 0 ? _f : 0;
248
+ desc.cropRectRight = (_h = (_g = style.cropRect) === null || _g === void 0 ? void 0 : _g.right) !== null && _h !== void 0 ? _h : 0;
249
+ desc.cropRectTop = (_k = (_j = style.cropRect) === null || _j === void 0 ? void 0 : _j.top) !== null && _k !== void 0 ? _k : 0;
250
+ }
251
+ (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'printOutputOptions', desc);
199
252
  });
200
253
  addHandler(1005, target => target.resolutionInfo !== undefined, (reader, target) => {
201
254
  const horizontalResolution = (0, psdReader_1.readFixedPoint32)(reader);
@@ -264,11 +317,61 @@ addHandler(1045, target => target.alphaChannelNames !== undefined, (reader, targ
264
317
  (0, psdWriter_1.writeUnicodeStringWithPadding)(writer, name);
265
318
  }
266
319
  });
267
- helpers_1.MOCK_HANDLERS && addHandler(1077, target => target._ir1077 !== undefined, (reader, target, left) => {
268
- LOG_MOCK_HANDLERS && console.log('image resource 1077', left());
269
- target._ir1077 = (0, psdReader_1.readBytes)(reader, left());
320
+ const displayInfoKinds = ['selected', 'protected', 'spot'];
321
+ const supportedColorSpaces = [0 /* ColorSpace.RGB */, 1 /* ColorSpace.HSB */, 2 /* ColorSpace.CMYK */, 7 /* ColorSpace.Lab */, 8 /* ColorSpace.Grayscale */];
322
+ function readDisplayInfo(reader) {
323
+ const info = { opacity: 0, kind: 'selected' };
324
+ const colorSpace = reader.view.getUint16(reader.offset);
325
+ if (supportedColorSpaces.indexOf(colorSpace) !== -1) {
326
+ info.color = (0, psdReader_1.readColor)(reader);
327
+ }
328
+ else {
329
+ // keep color in unknown color space as it is, so the channel info is not lost or misaligned
330
+ (0, psdReader_1.skipBytes)(reader, 2);
331
+ info.rawColor = { colorSpace, values: [(0, psdReader_1.readUint16)(reader), (0, psdReader_1.readUint16)(reader), (0, psdReader_1.readUint16)(reader), (0, psdReader_1.readUint16)(reader)] };
332
+ }
333
+ info.opacity = (0, psdReader_1.readUint16)(reader) / 100;
334
+ const kind = displayInfoKinds[(0, psdReader_1.readUint8)(reader)];
335
+ if (!kind)
336
+ throw new Error('Invalid display info kind');
337
+ info.kind = kind;
338
+ return info;
339
+ }
340
+ addHandler(1007, // Display info (obsolete, replaced by 1077), written back as 1077
341
+ () => false, (reader, target, left) => {
342
+ const info = [];
343
+ while (left() >= 14) {
344
+ info.push(readDisplayInfo(reader));
345
+ (0, psdReader_1.skipBytes)(reader, 1); // padding
346
+ }
347
+ // 1077 resource has more precise data and is used if present
348
+ if (!target.alphaChannelDisplayInfo)
349
+ target.alphaChannelDisplayInfo = info;
350
+ }, () => { });
351
+ addHandler(1077, // Display info (alpha and spot channels)
352
+ // Display info (alpha and spot channels)
353
+ target => target.alphaChannelDisplayInfo !== undefined, (reader, target, left) => {
354
+ const version = (0, psdReader_1.readUint32)(reader);
355
+ if (version !== 1)
356
+ throw new Error(`Invalid display info version: ${version}`);
357
+ target.alphaChannelDisplayInfo = [];
358
+ while (left() >= 13) {
359
+ target.alphaChannelDisplayInfo.push(readDisplayInfo(reader));
360
+ }
270
361
  }, (writer, target) => {
271
- (0, psdWriter_1.writeBytes)(writer, target._ir1077);
362
+ (0, psdWriter_1.writeUint32)(writer, 1); // version
363
+ for (const info of target.alphaChannelDisplayInfo) {
364
+ if (!info.color && info.rawColor) {
365
+ (0, psdWriter_1.writeUint16)(writer, info.rawColor.colorSpace);
366
+ for (let i = 0; i < 4; i++)
367
+ (0, psdWriter_1.writeUint16)(writer, info.rawColor.values[i] | 0);
368
+ }
369
+ else {
370
+ (0, psdWriter_1.writeColor)(writer, info.color || { r: 255, g: 0, b: 0 });
371
+ }
372
+ (0, psdWriter_1.writeUint16)(writer, Math.round((0, helpers_1.clamp)(info.opacity, 0, 1) * 100));
373
+ (0, psdWriter_1.writeUint8)(writer, Math.max(0, displayInfoKinds.indexOf(info.kind)));
374
+ }
272
375
  });
273
376
  addHandler(1053, target => target.alphaIdentifiers !== undefined, (reader, target, left) => {
274
377
  target.alphaIdentifiers = [];
@@ -321,30 +424,101 @@ target => target.url !== undefined, (reader, target, left) => {
321
424
  }, (writer, target) => {
322
425
  (0, psdWriter_1.writeAsciiString)(writer, target.url);
323
426
  });
324
- helpers_1.MOCK_HANDLERS && addHandler(10000, // Print flags
325
- // Print flags
326
- target => target._ir10000 !== undefined, (reader, target, left) => {
327
- LOG_MOCK_HANDLERS && console.log('image resource 10000', left());
328
- target._ir10000 = (0, psdReader_1.readBytes)(reader, left());
427
+ addHandler(10000, // Print flags information
428
+ // Print flags information
429
+ target => target.printFlagsInfo !== undefined, (reader, target) => {
430
+ const version = (0, psdReader_1.readUint16)(reader);
431
+ if (version !== 1)
432
+ throw new Error(`Invalid print flags information version: ${version}`);
433
+ const centerCropMarks = !!(0, psdReader_1.readUint8)(reader);
434
+ (0, psdReader_1.skipBytes)(reader, 1);
435
+ const bleedWidth = (0, psdReader_1.readUint32)(reader);
436
+ const bleedWidthScale = (0, psdReader_1.readUint16)(reader);
437
+ target.printFlagsInfo = { centerCropMarks, bleedWidth, bleedWidthScale };
329
438
  }, (writer, target) => {
330
- (0, psdWriter_1.writeBytes)(writer, target._ir10000);
439
+ const info = target.printFlagsInfo;
440
+ (0, psdWriter_1.writeUint16)(writer, 1); // version
441
+ (0, psdWriter_1.writeUint8)(writer, info.centerCropMarks ? 1 : 0);
442
+ (0, psdWriter_1.writeUint8)(writer, 0);
443
+ (0, psdWriter_1.writeUint32)(writer, info.bleedWidth | 0);
444
+ (0, psdWriter_1.writeUint16)(writer, info.bleedWidthScale | 0);
331
445
  });
332
- helpers_1.MOCK_HANDLERS && addHandler(1013, // Color halftoning
333
- // Color halftoning
334
- target => target._ir1013 !== undefined, (reader, target, left) => {
335
- LOG_MOCK_HANDLERS && console.log('image resource 1013', left());
336
- target._ir1013 = (0, psdReader_1.readBytes)(reader, left());
446
+ addHandler(1046, // Indexed color table count
447
+ // Indexed color table count
448
+ target => target.indexedColorCount !== undefined, (reader, target) => {
449
+ target.indexedColorCount = (0, psdReader_1.readUint16)(reader);
337
450
  }, (writer, target) => {
338
- (0, psdWriter_1.writeBytes)(writer, target._ir1013);
451
+ (0, psdWriter_1.writeUint16)(writer, target.indexedColorCount);
339
452
  });
340
- helpers_1.MOCK_HANDLERS && addHandler(1016, // Color transfer functions
341
- // Color transfer functions
342
- target => target._ir1016 !== undefined, (reader, target, left) => {
343
- LOG_MOCK_HANDLERS && console.log('image resource 1016', left());
344
- target._ir1016 = (0, psdReader_1.readBytes)(reader, left());
453
+ addHandler(1047, // Transparency index
454
+ // Transparency index
455
+ target => target.transparencyIndex !== undefined, (reader, target) => {
456
+ target.transparencyIndex = (0, psdReader_1.readUint16)(reader);
345
457
  }, (writer, target) => {
346
- (0, psdWriter_1.writeBytes)(writer, target._ir1016);
458
+ (0, psdWriter_1.writeUint16)(writer, target.transparencyIndex);
347
459
  });
460
+ const halftoneFrequencyUnits = ['lines/inch', 'lines/cm']; // 1, 2
461
+ const halftoneShapes = ['round', 'ellipse', 'line', 'square', 'cross', undefined, 'diamond']; // 0 - 6
462
+ function readHalftoneScreens(reader, left) {
463
+ const screens = [];
464
+ while (left() >= 18) {
465
+ const frequency = (0, psdReader_1.readFixedPoint32)(reader);
466
+ const frequencyUnits = halftoneFrequencyUnits[(0, psdReader_1.readUint16)(reader) - 1];
467
+ if (!frequencyUnits)
468
+ throw new Error('Invalid halftone screen frequency units');
469
+ const angle = (0, psdReader_1.readFixedPoint32)(reader);
470
+ const shape = halftoneShapes[(0, psdReader_1.readInt16)(reader)];
471
+ if (!shape)
472
+ throw new Error('Invalid halftone screen shape');
473
+ (0, psdReader_1.skipBytes)(reader, 4);
474
+ const accurateScreens = !!(0, psdReader_1.readUint8)(reader);
475
+ const printerDefaultScreens = !!(0, psdReader_1.readUint8)(reader);
476
+ screens.push({ frequency, frequencyUnits, angle, shape, accurateScreens, printerDefaultScreens });
477
+ }
478
+ return screens;
479
+ }
480
+ function writeHalftoneScreens(writer, screens) {
481
+ for (const screen of screens) {
482
+ (0, psdWriter_1.writeFixedPoint32)(writer, screen.frequency);
483
+ (0, psdWriter_1.writeUint16)(writer, Math.max(0, halftoneFrequencyUnits.indexOf(screen.frequencyUnits)) + 1);
484
+ (0, psdWriter_1.writeFixedPoint32)(writer, screen.angle);
485
+ (0, psdWriter_1.writeInt16)(writer, Math.max(0, halftoneShapes.indexOf(screen.shape)));
486
+ (0, psdWriter_1.writeZeros)(writer, 4);
487
+ (0, psdWriter_1.writeUint8)(writer, screen.accurateScreens ? 1 : 0);
488
+ (0, psdWriter_1.writeUint8)(writer, screen.printerDefaultScreens ? 1 : 0);
489
+ }
490
+ }
491
+ addHandler(1012, // Grayscale and multichannel halftoning information
492
+ // Grayscale and multichannel halftoning information
493
+ target => target.grayscaleHalftoneScreens !== undefined, (reader, target, left) => target.grayscaleHalftoneScreens = readHalftoneScreens(reader, left), (writer, target) => writeHalftoneScreens(writer, target.grayscaleHalftoneScreens));
494
+ addHandler(1013, // Color halftoning information
495
+ // Color halftoning information
496
+ target => target.colorHalftoneScreens !== undefined, (reader, target, left) => target.colorHalftoneScreens = readHalftoneScreens(reader, left), (writer, target) => writeHalftoneScreens(writer, target.colorHalftoneScreens));
497
+ function readTransferFunctions(reader, left) {
498
+ const functions = [];
499
+ while (left() >= 28) {
500
+ const curve = [];
501
+ for (let i = 0; i < 13; i++)
502
+ curve.push((0, psdReader_1.readInt16)(reader));
503
+ const override = !!(0, psdReader_1.readUint16)(reader);
504
+ functions.push({ curve, override });
505
+ }
506
+ return functions;
507
+ }
508
+ function writeTransferFunctions(writer, functions) {
509
+ var _a;
510
+ for (const f of functions) {
511
+ for (let i = 0; i < 13; i++)
512
+ (0, psdWriter_1.writeInt16)(writer, (_a = f.curve[i]) !== null && _a !== void 0 ? _a : -1);
513
+ (0, psdWriter_1.writeUint16)(writer, f.override ? 1 : 0);
514
+ }
515
+ }
516
+ addHandler(1015, // Grayscale and multichannel transfer function
517
+ // Grayscale and multichannel transfer function
518
+ target => target.grayscaleTransferFunctions !== undefined, (reader, target, left) => target.grayscaleTransferFunctions = readTransferFunctions(reader, left), (writer, target) => writeTransferFunctions(writer, target.grayscaleTransferFunctions));
519
+ addHandler(1016, // Color transfer functions
520
+ // Color transfer functions
521
+ target => target.colorTransferFunctions !== undefined, (reader, target, left) => target.colorTransferFunctions = readTransferFunctions(reader, left), (writer, target) => writeTransferFunctions(writer, target.colorTransferFunctions));
348
522
  addHandler(1080, // Count Information
349
523
  // Count Information
350
524
  target => target.countInformation !== undefined, (reader, target) => {
@@ -407,22 +581,27 @@ addHandler(1069, target => target.layerSelectionIds !== undefined, (reader, targ
407
581
  }
408
582
  });
409
583
  addHandler(1032, target => target.gridAndGuidesInformation !== undefined, (reader, target) => {
584
+ var _a;
410
585
  const version = (0, psdReader_1.readUint32)(reader);
411
586
  const horizontal = (0, psdReader_1.readUint32)(reader);
412
587
  const vertical = (0, psdReader_1.readUint32)(reader);
413
588
  const count = (0, psdReader_1.readUint32)(reader);
414
589
  if (version !== 1)
415
590
  throw new Error(`Invalid 1032 resource version: ${version}`);
416
- target.gridAndGuidesInformation = {
417
- grid: { horizontal, vertical },
418
- guides: [],
419
- };
591
+ const previous = (_a = target.gridAndGuidesInformation) === null || _a === void 0 ? void 0 : _a.guides; // in case guides were already read from 1092
592
+ const guides = [];
420
593
  for (let i = 0; i < count; i++) {
421
- target.gridAndGuidesInformation.guides.push({
594
+ const guide = {
422
595
  location: (0, psdReader_1.readInt32)(reader) / 32,
423
596
  direction: (0, psdReader_1.readUint8)(reader) ? 'horizontal' : 'vertical'
424
- });
597
+ };
598
+ if ((previous === null || previous === void 0 ? void 0 : previous.length) === count && previous[i].color)
599
+ guide.color = previous[i].color;
600
+ if ((previous === null || previous === void 0 ? void 0 : previous.length) === count && previous[i].id)
601
+ guide.id = previous[i].id;
602
+ guides.push(guide);
425
603
  }
604
+ target.gridAndGuidesInformation = { grid: { horizontal, vertical }, guides };
426
605
  }, (writer, target) => {
427
606
  const info = target.gridAndGuidesInformation;
428
607
  const grid = info.grid || { horizontal: 18 * 32, vertical: 18 * 32 };
@@ -436,6 +615,76 @@ addHandler(1032, target => target.gridAndGuidesInformation !== undefined, (reade
436
615
  (0, psdWriter_1.writeUint8)(writer, g.direction === 'horizontal' ? 1 : 0);
437
616
  }
438
617
  });
618
+ const defaultGuideColor = { r: 74, g: 255, b: 255 }; // Photoshop default (cyan)
619
+ addHandler(1092, // Grid and guides information with guide colors (same as 1032 with color of each guide)
620
+ // Grid and guides information with guide colors (same as 1032 with color of each guide)
621
+ target => target.gridAndGuidesInformation !== undefined, (reader, target) => {
622
+ var _a;
623
+ const version = (0, psdReader_1.readUint32)(reader);
624
+ if (version !== 2)
625
+ throw new Error(`Invalid 1092 resource version: ${version}`);
626
+ const horizontal = (0, psdReader_1.readUint32)(reader);
627
+ const vertical = (0, psdReader_1.readUint32)(reader);
628
+ const count = (0, psdReader_1.readUint32)(reader);
629
+ const guides = [];
630
+ for (let i = 0; i < count; i++) {
631
+ const location = (0, psdReader_1.readInt32)(reader) / 32;
632
+ const direction = (0, psdReader_1.readUint8)(reader) ? 'horizontal' : 'vertical';
633
+ (0, psdReader_1.skipBytes)(reader, 1);
634
+ const color = { r: (0, psdReader_1.readUint8)(reader), g: (0, psdReader_1.readUint8)(reader), b: (0, psdReader_1.readUint8)(reader) };
635
+ guides.push({ location, direction, color });
636
+ }
637
+ const existing = (_a = target.gridAndGuidesInformation) === null || _a === void 0 ? void 0 : _a.guides;
638
+ if (existing && existing.length === count) {
639
+ existing.forEach((guide, i) => guide.color = guides[i].color);
640
+ }
641
+ else {
642
+ target.gridAndGuidesInformation = { grid: { horizontal, vertical }, guides };
643
+ }
644
+ }, (writer, target) => {
645
+ const info = target.gridAndGuidesInformation;
646
+ const grid = info.grid || { horizontal: 18 * 32, vertical: 18 * 32 };
647
+ const guides = info.guides || [];
648
+ (0, psdWriter_1.writeUint32)(writer, 2); // version
649
+ (0, psdWriter_1.writeUint32)(writer, Math.round(grid.horizontal));
650
+ (0, psdWriter_1.writeUint32)(writer, Math.round(grid.vertical));
651
+ (0, psdWriter_1.writeUint32)(writer, guides.length);
652
+ for (const g of guides) {
653
+ const color = g.color || defaultGuideColor;
654
+ (0, psdWriter_1.writeInt32)(writer, Math.round(g.location * 32));
655
+ (0, psdWriter_1.writeUint8)(writer, g.direction === 'horizontal' ? 1 : 0);
656
+ (0, psdWriter_1.writeUint8)(writer, 0);
657
+ (0, psdWriter_1.writeUint8)(writer, Math.round(color.r));
658
+ (0, psdWriter_1.writeUint8)(writer, Math.round(color.g));
659
+ (0, psdWriter_1.writeUint8)(writer, Math.round(color.b));
660
+ }
661
+ });
662
+ const emptyGuid = '00000000-0000-0000-0000-000000000000';
663
+ addHandler(1097, // Guide ids
664
+ // Guide ids
665
+ target => !!target.gridAndGuidesInformation && (target.gridAndGuidesInformation.guides || []).every(g => g.id), (reader, target) => {
666
+ var _a;
667
+ const count = (0, psdReader_1.readUint32)(reader);
668
+ const ids = [];
669
+ for (let i = 0; i < count; i++) {
670
+ ids.push((0, psdReader_1.readAsciiString)(reader, (0, psdReader_1.readUint32)(reader)));
671
+ (0, psdReader_1.readUint32)(reader); // unknown, always 0
672
+ (0, psdReader_1.readAsciiString)(reader, (0, psdReader_1.readUint32)(reader)); // unknown, always empty guid
673
+ }
674
+ const guides = (_a = target.gridAndGuidesInformation) === null || _a === void 0 ? void 0 : _a.guides;
675
+ if (guides && guides.length === count)
676
+ guides.forEach((guide, i) => guide.id = ids[i]);
677
+ }, (writer, target) => {
678
+ const guides = target.gridAndGuidesInformation.guides || [];
679
+ (0, psdWriter_1.writeUint32)(writer, guides.length);
680
+ for (const g of guides) {
681
+ (0, psdWriter_1.writeUint32)(writer, g.id.length);
682
+ (0, psdWriter_1.writeAsciiString)(writer, g.id);
683
+ (0, psdWriter_1.writeUint32)(writer, 0);
684
+ (0, psdWriter_1.writeUint32)(writer, emptyGuid.length);
685
+ (0, psdWriter_1.writeAsciiString)(writer, emptyGuid);
686
+ }
687
+ });
439
688
  addHandler(1065, // Layer Comps
440
689
  // Layer Comps
441
690
  target => target.layerComps !== undefined, (reader, target) => {
@@ -816,27 +1065,78 @@ addHandler(1041, target => target.iccUntaggedProfile !== undefined, (reader, tar
816
1065
  }, (writer, target) => {
817
1066
  (0, psdWriter_1.writeUint8)(writer, target.iccUntaggedProfile ? 1 : 0);
818
1067
  });
819
- helpers_1.MOCK_HANDLERS && addHandler(1039, // ICC Profile
1068
+ addHandler(1039, // ICC Profile
820
1069
  // ICC Profile
821
- target => target._ir1039 !== undefined, (reader, target, left) => {
822
- // TODO: this is raw bytes, just return as a byte array
823
- LOG_MOCK_HANDLERS && console.log('image resource 1039', left());
824
- target._ir1039 = (0, psdReader_1.readBytes)(reader, left());
1070
+ target => target.iccProfile !== undefined, (reader, target, left) => {
1071
+ target.iccProfile = (0, psdReader_1.readBytes)(reader, left());
825
1072
  }, (writer, target) => {
826
- (0, psdWriter_1.writeBytes)(writer, target._ir1039);
1073
+ (0, psdWriter_1.writeBytes)(writer, target.iccProfile);
827
1074
  });
828
1075
  addHandler(1044, target => target.idsSeedNumber !== undefined, (reader, target) => target.idsSeedNumber = (0, psdReader_1.readUint32)(reader), (writer, target) => (0, psdWriter_1.writeUint32)(writer, target.idsSeedNumber));
1076
+ addHandler(1038, // Color samplers (Photoshop 5.0, replaced by 1073 in CS3)
1077
+ // Color samplers (Photoshop 5.0, replaced by 1073 in CS3)
1078
+ target => target.colorSamplers !== undefined, (reader, target, left) => {
1079
+ const version = (0, psdReader_1.readUint32)(reader);
1080
+ if (version !== 1)
1081
+ throw new Error(`Invalid color samplers version: ${version}`);
1082
+ const count = (0, psdReader_1.readUint32)(reader);
1083
+ target.colorSamplers = [];
1084
+ for (let i = 0; i < count && left() >= 10; i++) {
1085
+ // vertical and horizontal position in 1/16 pixel (inferred from sample files, the specification describes
1086
+ // these values as horizontal and vertical fixed point numbers)
1087
+ const y = (0, psdReader_1.readInt32)(reader) / 16;
1088
+ const x = (0, psdReader_1.readInt32)(reader) / 16;
1089
+ const colorSpace = (0, psdReader_1.readInt16)(reader);
1090
+ target.colorSamplers.push({ x, y, colorSpace });
1091
+ }
1092
+ }, (writer, target) => {
1093
+ (0, psdWriter_1.writeUint32)(writer, 1); // version
1094
+ (0, psdWriter_1.writeUint32)(writer, target.colorSamplers.length);
1095
+ for (const sampler of target.colorSamplers) {
1096
+ (0, psdWriter_1.writeInt32)(writer, Math.round(sampler.y * 16));
1097
+ (0, psdWriter_1.writeInt32)(writer, Math.round(sampler.x * 16));
1098
+ (0, psdWriter_1.writeInt16)(writer, sampler.colorSpace);
1099
+ }
1100
+ });
1101
+ addHandler(1042, // Effects visible (only present when effects are hidden)
1102
+ // Effects visible (only present when effects are hidden)
1103
+ target => target.effectsVisible !== undefined, (reader, target) => {
1104
+ target.effectsVisible = !!(0, psdReader_1.readUint8)(reader);
1105
+ }, (writer, target) => {
1106
+ (0, psdWriter_1.writeUint8)(writer, target.effectsVisible ? 1 : 0);
1107
+ });
829
1108
  addHandler(1036, target => target.thumbnail !== undefined || target.thumbnailRaw !== undefined, (reader, target, left) => {
830
1109
  const format = (0, psdReader_1.readUint32)(reader); // 1 = kJpegRGB, 0 = kRawRGB
831
1110
  const width = (0, psdReader_1.readUint32)(reader);
832
1111
  const height = (0, psdReader_1.readUint32)(reader);
833
- (0, psdReader_1.readUint32)(reader); // widthBytes = (width * bits_per_pixel + 31) / 32 * 4.
1112
+ const widthBytes = (0, psdReader_1.readUint32)(reader); // widthBytes = (width * bits_per_pixel + 31) / 32 * 4.
834
1113
  (0, psdReader_1.readUint32)(reader); // totalSize = widthBytes * height * planes
835
1114
  (0, psdReader_1.readUint32)(reader); // sizeAfterCompression
836
1115
  const bitsPerPixel = (0, psdReader_1.readUint16)(reader); // 24
837
- const planes = (0, psdReader_1.readUint16)(reader); // 1
838
- if (format !== 1 || bitsPerPixel !== 24 || planes !== 1) {
839
- reader.logMissingFeatures && reader.log(`Invalid thumbnail data (format: ${format}, bitsPerPixel: ${bitsPerPixel}, planes: ${planes})`);
1116
+ (0, psdReader_1.readUint16)(reader); // planes, should be 1 (some applications write 3)
1117
+ if (format === 0 && bitsPerPixel === 24 && widthBytes >= width * 3 && widthBytes * height <= left()) {
1118
+ // raw RGB data, rows are padded to 4 bytes
1119
+ if (reader.useRawThumbnail) {
1120
+ reader.logMissingFeatures && reader.log('Raw thumbnail data is not supported with useRawThumbnail option');
1121
+ (0, psdReader_1.skipBytes)(reader, left());
1122
+ return;
1123
+ }
1124
+ const data = (0, psdReader_1.readBytes)(reader, widthBytes * height);
1125
+ const imageData = (0, helpers_1.createImageData)(width, height);
1126
+ for (let y = 0, dst = 0; y < height; y++) {
1127
+ for (let x = 0, src = y * widthBytes; x < width; x++, src += 3, dst += 4) {
1128
+ imageData.data[dst + 0] = data[src + 0];
1129
+ imageData.data[dst + 1] = data[src + 1];
1130
+ imageData.data[dst + 2] = data[src + 2];
1131
+ imageData.data[dst + 3] = 255;
1132
+ }
1133
+ }
1134
+ target.thumbnail = (0, helpers_1.imageDataToCanvas)(imageData);
1135
+ (0, psdReader_1.skipBytes)(reader, left());
1136
+ return;
1137
+ }
1138
+ if (format !== 1 || bitsPerPixel !== 24) {
1139
+ reader.logMissingFeatures && reader.log(`Invalid thumbnail data (format: ${format}, bitsPerPixel: ${bitsPerPixel})`);
840
1140
  (0, psdReader_1.skipBytes)(reader, left());
841
1141
  return;
842
1142
  }
@@ -903,13 +1203,12 @@ addHandler(1057, target => target.versionInfo !== undefined, (reader, target, le
903
1203
  (0, psdWriter_1.writeUnicodeString)(writer, versionInfo.readerName);
904
1204
  (0, psdWriter_1.writeUint32)(writer, versionInfo.fileVersion);
905
1205
  });
906
- helpers_1.MOCK_HANDLERS && addHandler(1058, // EXIF data 1.
907
- // EXIF data 1.
908
- target => target._ir1058 !== undefined, (reader, target, left) => {
909
- LOG_MOCK_HANDLERS && console.log('image resource 1058', left());
910
- target._ir1058 = (0, psdReader_1.readBytes)(reader, left());
1206
+ addHandler(1058, // EXIF data 1
1207
+ // EXIF data 1
1208
+ target => target.exifData !== undefined, (reader, target, left) => {
1209
+ target.exifData = (0, psdReader_1.readBytes)(reader, left());
911
1210
  }, (writer, target) => {
912
- (0, psdWriter_1.writeBytes)(writer, target._ir1058);
1211
+ (0, psdWriter_1.writeBytes)(writer, target.exifData);
913
1212
  });
914
1213
  addHandler(7000, target => target.imageReadyVariables !== undefined, (reader, target, left) => {
915
1214
  target.imageReadyVariables = readUtf8String(reader, left());
@@ -928,22 +1227,101 @@ addHandler(1088, target => target.pathSelectionState !== undefined, (reader, tar
928
1227
  const desc = { 'null': (0, descriptor_1.pathSelectionStateToReference)(target.pathSelectionState) };
929
1228
  (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
930
1229
  });
931
- helpers_1.MOCK_HANDLERS && addHandler(1025, target => target._ir1025 !== undefined, (reader, target, left) => {
932
- LOG_MOCK_HANDLERS && console.log('image resource 1025', left());
933
- target._ir1025 = (0, psdReader_1.readBytes)(reader, left());
1230
+ addHandler(1025, // Work path
1231
+ // Work path
1232
+ target => target.workPath !== undefined, (reader, target, left, { width, height }) => {
1233
+ target.workPath = { paths: [] };
1234
+ (0, additionalInfo_1.readVectorMask)(reader, target.workPath, width, height, left());
1235
+ (0, psdReader_1.skipBytes)(reader, left());
1236
+ }, (writer, target, _index, { width, height }) => {
1237
+ (0, additionalInfo_1.writeVectorMask)(writer, target.workPath, width, height);
1238
+ });
1239
+ const MAX_SAVED_PATHS = 999; // ids 2000-2998
1240
+ addHandler(2000, // Saved paths (one resource for each path, named after the path)
1241
+ // Saved paths (one resource for each path, named after the path)
1242
+ target => target.savedPaths ? Math.min(target.savedPaths.length, MAX_SAVED_PATHS) : 0, (reader, target, left, { signature, id, name, width, height }) => {
1243
+ var _a, _b;
1244
+ if (signature !== '8BIM') { // ImageReady ('MeSa') resources use the same ids for other data
1245
+ reader.logMissingFeatures && reader.log(`Unhandled image resource: ${signature} ${id}`);
1246
+ (0, psdReader_1.skipBytes)(reader, left());
1247
+ return;
1248
+ }
1249
+ const savedPaths = (_a = target.savedPaths) !== null && _a !== void 0 ? _a : (target.savedPaths = []);
1250
+ const path = { name: decodeEncodedString(reader, name), paths: [] };
1251
+ (0, additionalInfo_1.readVectorMask)(reader, path, width, height, left());
1252
+ (0, psdReader_1.skipBytes)(reader, left());
1253
+ const keyDescriptorList = (_b = target.savedPathsOrigination) === null || _b === void 0 ? void 0 : _b[savedPaths.length];
1254
+ if (keyDescriptorList)
1255
+ path.vectorOrigination = { keyDescriptorList };
1256
+ savedPaths.push(path);
1257
+ }, (writer, target, index, { width, height }) => {
1258
+ (0, additionalInfo_1.writeVectorMask)(writer, target.savedPaths[index], width, height);
1259
+ }, { keyCount: MAX_SAVED_PATHS, name: (target, index) => toShortAsciiString(target.savedPaths[index].name) });
1260
+ addHandler(3000, // Origin path info (origination data of saved paths)
1261
+ // Origin path info (origination data of saved paths)
1262
+ target => { var _a; return !!((_a = target.savedPaths) === null || _a === void 0 ? void 0 : _a.some(path => path.vectorOrigination)); }, (reader, target, left) => {
1263
+ const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
1264
+ desc.keyRootDescriptorList.forEach((item, i) => {
1265
+ var _a, _b;
1266
+ const keyDescriptorList = (0, additionalInfo_1.parseKeyDescriptorList)(item);
1267
+ if (!keyDescriptorList.length)
1268
+ return; // written for paths without origination data
1269
+ const path = (_a = target.savedPaths) === null || _a === void 0 ? void 0 : _a[i];
1270
+ if (path) {
1271
+ path.vectorOrigination = { keyDescriptorList };
1272
+ }
1273
+ else { // saved paths are stored after this resource
1274
+ ((_b = target.savedPathsOrigination) !== null && _b !== void 0 ? _b : (target.savedPathsOrigination = []))[i] = keyDescriptorList;
1275
+ }
1276
+ });
1277
+ (0, psdReader_1.skipBytes)(reader, left());
934
1278
  }, (writer, target) => {
935
- (0, psdWriter_1.writeBytes)(writer, target._ir1025);
1279
+ const desc = {
1280
+ keyRootDescriptorList: target.savedPaths.slice(0, MAX_SAVED_PATHS)
1281
+ .map(path => { var _a, _b; return (0, additionalInfo_1.serializeKeyDescriptorList)((_b = (_a = path.vectorOrigination) === null || _a === void 0 ? void 0 : _a.keyDescriptorList) !== null && _b !== void 0 ? _b : []); }),
1282
+ };
1283
+ (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
1284
+ }, { name: () => 'OriginDataIRB' });
1285
+ addHandler(2999, // Clipping path
1286
+ // Clipping path
1287
+ target => target.clippingPath !== undefined, (reader, target, left) => {
1288
+ const name = readEncodedString(reader);
1289
+ const flatness = (0, psdReader_1.readFixedPoint32)(reader);
1290
+ (0, psdReader_1.skipBytes)(reader, left()); // fill rule (ignored by Photoshop)
1291
+ target.clippingPath = { name, flatness };
1292
+ }, (writer, target) => {
1293
+ writeEncodedString(writer, target.clippingPath.name);
1294
+ (0, psdWriter_1.writeFixedPoint32)(writer, target.clippingPath.flatness);
1295
+ (0, psdWriter_1.writeUint16)(writer, 1); // fill rule (ignored by Photoshop)
936
1296
  });
937
1297
  const FrmD = (0, helpers_1.createEnum)('FrmD', 'auto', {
938
1298
  auto: 'Auto',
939
1299
  none: 'None',
940
1300
  dispose: 'Disp',
941
1301
  });
942
- addHandler(4000, // Plug-In resource(s)
943
- // Plug-In resource(s)
944
- target => target.animations !== undefined, (reader, target, left) => {
1302
+ // plug-in resources are written with consecutive ids starting at 4000, in the same order as Photoshop writes them
1303
+ function pluginResourceKeys(target) {
1304
+ const keys = [];
1305
+ if (target.outputSettings !== undefined)
1306
+ keys.push('mset');
1307
+ if (target.animations !== undefined)
1308
+ keys.push('mani', 'mfri');
1309
+ return keys;
1310
+ }
1311
+ addHandler(4000, // Plug-In resource(s), identified by key stored in the data (ids 4000-4999)
1312
+ // Plug-In resource(s), identified by key stored in the data (ids 4000-4999)
1313
+ target => pluginResourceKeys(target).length, (reader, target, left) => {
945
1314
  const key = (0, psdReader_1.readSignature)(reader);
946
- if (key === 'mani') {
1315
+ if (key === 'mset') {
1316
+ // Save for Web output settings
1317
+ target.outputSettings = (0, descriptor_1.readVersionAndDescriptor)(reader, true);
1318
+ (0, psdReader_1.skipBytes)(reader, left());
1319
+ }
1320
+ else if (key === 'mfri') {
1321
+ // frame count, active frame and animation count, same data as in animations (mani)
1322
+ (0, psdReader_1.skipBytes)(reader, left());
1323
+ }
1324
+ else if (key === 'mani') {
947
1325
  (0, psdReader_1.checkSignature)(reader, 'IRFR');
948
1326
  (0, psdReader_1.readSection)(reader, 1, left => {
949
1327
  while (left() > 0) {
@@ -969,6 +1347,7 @@ target => target.animations !== undefined, (reader, target, left) => {
969
1347
  };
970
1348
  // console.log('#4000 AnDs', require('util').inspect(desc, false, 99, true));
971
1349
  // console.log('#4000 AnDs:result', require('util').inspect(target.animations, false, 99, true));
1350
+ (0, psdReader_1.skipBytes)(reader, left()); // padding
972
1351
  }
973
1352
  else if (key === 'Roll') {
974
1353
  const bytes = (0, psdReader_1.readBytes)(reader, left());
@@ -976,20 +1355,39 @@ target => target.animations !== undefined, (reader, target, left) => {
976
1355
  }
977
1356
  else {
978
1357
  reader.logMissingFeatures && reader.log('Unhandled subsection in #4000', key);
1358
+ (0, psdReader_1.skipBytes)(reader, left());
979
1359
  }
980
1360
  });
981
1361
  }
982
1362
  });
1363
+ (0, psdReader_1.skipBytes)(reader, left()); // unknown data after animations section
983
1364
  }
984
1365
  else if (key === 'mopt') {
985
1366
  const bytes = (0, psdReader_1.readBytes)(reader, left());
986
1367
  reader.logDevFeatures && reader.log('#4000 mopt', bytes);
987
1368
  }
988
1369
  else {
989
- reader.logMissingFeatures && reader.log('Unhandled key in #4000:', key);
1370
+ reader.logMissingFeatures && reader.log(`Unhandled plug-in resource key: ${key}`);
1371
+ (0, psdReader_1.skipBytes)(reader, left());
990
1372
  }
991
- }, (writer, target) => {
992
- if (target.animations) {
1373
+ }, (writer, target, index) => {
1374
+ var _a, _b;
1375
+ const key = pluginResourceKeys(target)[index];
1376
+ if (key === 'mset') {
1377
+ (0, psdWriter_1.writeSignature)(writer, 'mset');
1378
+ (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', target.outputSettings, descriptor_1.outputSettingsRoot);
1379
+ }
1380
+ else if (key === 'mfri') {
1381
+ const animations = target.animations;
1382
+ (0, psdWriter_1.writeSignature)(writer, 'mfri');
1383
+ (0, psdWriter_1.writeUint32)(writer, 2); // version
1384
+ (0, psdWriter_1.writeUint32)(writer, 16); // length
1385
+ (0, psdWriter_1.writeUint32)(writer, animations.frames.length);
1386
+ (0, psdWriter_1.writeUint32)(writer, (_b = (_a = animations.animations[0]) === null || _a === void 0 ? void 0 : _a.activeFrame) !== null && _b !== void 0 ? _b : 0);
1387
+ (0, psdWriter_1.writeUint32)(writer, animations.animations.length);
1388
+ (0, psdWriter_1.writeUint32)(writer, 0);
1389
+ }
1390
+ else if (key === 'mani') {
993
1391
  (0, psdWriter_1.writeSignature)(writer, 'mani');
994
1392
  (0, psdWriter_1.writeSignature)(writer, 'IRFR');
995
1393
  (0, psdWriter_1.writeSection)(writer, 1, () => {
@@ -1031,42 +1429,5 @@ target => target.animations !== undefined, (reader, target, left) => {
1031
1429
  // });
1032
1430
  });
1033
1431
  }
1034
- });
1035
- // TODO: Unfinished
1036
- helpers_1.MOCK_HANDLERS && addHandler(4001, // Plug-In resource(s)
1037
- // Plug-In resource(s)
1038
- target => target._ir4001 !== undefined, (reader, target, left) => {
1039
- if (helpers_1.MOCK_HANDLERS) {
1040
- LOG_MOCK_HANDLERS && console.log('image resource 4001', left());
1041
- target._ir4001 = (0, psdReader_1.readBytes)(reader, left());
1042
- return;
1043
- }
1044
- const key = (0, psdReader_1.readSignature)(reader);
1045
- if (key === 'mfri') {
1046
- const version = (0, psdReader_1.readUint32)(reader);
1047
- if (version !== 2)
1048
- throw new Error('Invalid mfri version');
1049
- const length = (0, psdReader_1.readUint32)(reader);
1050
- const bytes = (0, psdReader_1.readBytes)(reader, length);
1051
- reader.logDevFeatures && reader.log('mfri', bytes);
1052
- }
1053
- else if (key === 'mset') {
1054
- const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
1055
- reader.logDevFeatures && reader.log('mset', desc);
1056
- }
1057
- else {
1058
- reader.logMissingFeatures && reader.log('Unhandled key in #4001', key);
1059
- }
1060
- }, (writer, target) => {
1061
- (0, psdWriter_1.writeBytes)(writer, target._ir4001);
1062
- });
1063
- // TODO: Unfinished
1064
- helpers_1.MOCK_HANDLERS && addHandler(4002, // Plug-In resource(s)
1065
- // Plug-In resource(s)
1066
- target => target._ir4002 !== undefined, (reader, target, left) => {
1067
- LOG_MOCK_HANDLERS && console.log('image resource 4002', left());
1068
- target._ir4002 = (0, psdReader_1.readBytes)(reader, left());
1069
- }, (writer, target) => {
1070
- (0, psdWriter_1.writeBytes)(writer, target._ir4002);
1071
- });
1432
+ }, { keyCount: 1000 });
1072
1433
  //# sourceMappingURL=imageResources.js.map