ag-psd 32.0.0 → 34.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 (117) 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/87cf2209 +0 -0
  11. package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
  12. package/.v8-cache/v24.7.0-x64-ef5a0af0/acc36e66 +0 -0
  13. package/.v8-cache/v24.7.0-x64-ef5a0af0/b3c2fab7 +0 -0
  14. package/.v8-cache/v24.7.0-x64-ef5a0af0/c0b789d2 +0 -0
  15. package/.v8-cache/v24.7.0-x64-ef5a0af0/c314aece +0 -0
  16. package/.v8-cache/v24.7.0-x64-ef5a0af0/cfc49f4f +0 -0
  17. package/.v8-cache/v24.7.0-x64-ef5a0af0/cff9434a +0 -0
  18. package/.v8-cache/v24.7.0-x64-ef5a0af0/d13d7610 +0 -0
  19. package/.v8-cache/v24.7.0-x64-ef5a0af0/dc86f000 +0 -0
  20. package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +0 -0
  21. package/.v8-cache/v24.7.0-x64-ef5a0af0/e6745c2b +0 -0
  22. package/.v8-cache/v24.7.0-x64-ef5a0af0/e6b99945 +0 -0
  23. package/.v8-cache/v24.7.0-x64-ef5a0af0/eeeebdfe +0 -0
  24. package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
  25. package/CHANGELOG.md +100 -0
  26. package/LICENSE +5 -0
  27. package/README.md +4 -7
  28. package/README_PSD.md +261 -84
  29. package/TODO.md +13 -84
  30. package/dist/abr.d.ts +11 -4
  31. package/dist/abr.js +362 -230
  32. package/dist/abr.js.map +1 -1
  33. package/dist/additionalInfo.d.ts +56 -2
  34. package/dist/additionalInfo.js +828 -361
  35. package/dist/additionalInfo.js.map +1 -1
  36. package/dist/ase.d.ts +6 -1
  37. package/dist/ase.js +61 -61
  38. package/dist/ase.js.map +1 -1
  39. package/dist/bundle.js +3321 -1364
  40. package/dist/descriptor.d.ts +28 -13
  41. package/dist/descriptor.js +295 -241
  42. package/dist/descriptor.js.map +1 -1
  43. package/dist/helpers.d.ts +7 -1
  44. package/dist/helpers.js +246 -4
  45. package/dist/helpers.js.map +1 -1
  46. package/dist/imageResources.d.ts +15 -3
  47. package/dist/imageResources.js +586 -144
  48. package/dist/imageResources.js.map +1 -1
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.js +1 -0
  51. package/dist/index.js.map +1 -1
  52. package/dist/jpeg.js +8 -8
  53. package/dist/jpeg.js.map +1 -1
  54. package/dist/psd.d.ts +292 -19
  55. package/dist/psd.js.map +1 -1
  56. package/dist/psdReader.d.ts +10 -0
  57. package/dist/psdReader.js +424 -216
  58. package/dist/psdReader.js.map +1 -1
  59. package/dist/psdWriter.d.ts +2 -0
  60. package/dist/psdWriter.js +373 -113
  61. package/dist/psdWriter.js.map +1 -1
  62. package/dist/text.d.ts +32 -1
  63. package/dist/text.js +75 -6
  64. package/dist/text.js.map +1 -1
  65. package/dist/utf8.js +0 -3
  66. package/dist/utf8.js.map +1 -1
  67. package/dist-es/abr.d.ts +11 -4
  68. package/dist-es/abr.js +362 -230
  69. package/dist-es/abr.js.map +1 -1
  70. package/dist-es/additionalInfo.d.ts +56 -2
  71. package/dist-es/additionalInfo.js +828 -361
  72. package/dist-es/additionalInfo.js.map +1 -1
  73. package/dist-es/ase.d.ts +6 -1
  74. package/dist-es/ase.js +61 -61
  75. package/dist-es/ase.js.map +1 -1
  76. package/dist-es/descriptor.d.ts +28 -13
  77. package/dist-es/descriptor.js +295 -241
  78. package/dist-es/descriptor.js.map +1 -1
  79. package/dist-es/helpers.d.ts +7 -1
  80. package/dist-es/helpers.js +246 -4
  81. package/dist-es/helpers.js.map +1 -1
  82. package/dist-es/imageResources.d.ts +15 -3
  83. package/dist-es/imageResources.js +586 -144
  84. package/dist-es/imageResources.js.map +1 -1
  85. package/dist-es/index.d.ts +1 -0
  86. package/dist-es/index.js +1 -0
  87. package/dist-es/index.js.map +1 -1
  88. package/dist-es/jpeg.js +8 -8
  89. package/dist-es/jpeg.js.map +1 -1
  90. package/dist-es/psd.d.ts +292 -19
  91. package/dist-es/psd.js.map +1 -1
  92. package/dist-es/psdReader.d.ts +10 -0
  93. package/dist-es/psdReader.js +424 -216
  94. package/dist-es/psdReader.js.map +1 -1
  95. package/dist-es/psdWriter.d.ts +2 -0
  96. package/dist-es/psdWriter.js +373 -113
  97. package/dist-es/psdWriter.js.map +1 -1
  98. package/dist-es/text.d.ts +32 -1
  99. package/dist-es/text.js +75 -6
  100. package/dist-es/text.js.map +1 -1
  101. package/dist-es/utf8.js +0 -3
  102. package/dist-es/utf8.js.map +1 -1
  103. package/package.json +2 -2
  104. package/perf.js +312 -9
  105. package/src/abr.ts +382 -235
  106. package/src/additionalInfo.ts +1071 -482
  107. package/src/ase.ts +66 -61
  108. package/src/descriptor.ts +291 -242
  109. package/src/helpers.ts +266 -3
  110. package/src/imageResources.ts +736 -169
  111. package/src/index.ts +1 -0
  112. package/src/jpeg.ts +8 -8
  113. package/src/psd.ts +271 -32
  114. package/src/psdReader.ts +440 -221
  115. package/src/psdWriter.ts +402 -110
  116. package/src/text.ts +93 -7
  117. 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,133 @@ 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(1014, // Duotone halftoning information
517
+ // Duotone halftoning information
518
+ target => target.duotoneHalftoneScreens !== undefined, (reader, target, left) => target.duotoneHalftoneScreens = readHalftoneScreens(reader, left), (writer, target) => writeHalftoneScreens(writer, target.duotoneHalftoneScreens));
519
+ addHandler(1017, // Duotone transfer functions
520
+ // Duotone transfer functions
521
+ target => target.duotoneTransferFunctions !== undefined, (reader, target, left) => target.duotoneTransferFunctions = readTransferFunctions(reader, left), (writer, target) => writeTransferFunctions(writer, target.duotoneTransferFunctions));
522
+ addHandler(1018, // Duotone image information
523
+ // Duotone image information
524
+ target => target.duotoneImageInformation !== undefined, (reader, target, left) => target.duotoneImageInformation = (0, psdReader_1.readBytes)(reader, left()), (writer, target) => (0, psdWriter_1.writeBytes)(writer, target.duotoneImageInformation));
525
+ addHandler(1066, // Alternate duotone colors
526
+ // Alternate duotone colors
527
+ target => target.alternateDuotoneColors !== undefined, (reader, target, left) => {
528
+ if ((0, psdReader_1.readUint16)(reader) !== 1)
529
+ throw new Error('Invalid alternate duotone colors version');
530
+ const colors = [];
531
+ const count = (0, psdReader_1.readUint16)(reader);
532
+ for (let i = 0; i < count && left() >= 10; i++)
533
+ colors.push((0, psdReader_1.readColor)(reader));
534
+ const labCount = (0, psdReader_1.readUint16)(reader);
535
+ if (labCount * 3 > left())
536
+ throw new Error('Invalid alternate duotone colors Lab table size');
537
+ const labColors = (0, psdReader_1.readBytes)(reader, labCount * 3);
538
+ target.alternateDuotoneColors = { colors, labColors };
539
+ }, (writer, target) => {
540
+ const { colors, labColors } = target.alternateDuotoneColors;
541
+ (0, psdWriter_1.writeUint16)(writer, 1); // version
542
+ (0, psdWriter_1.writeUint16)(writer, colors.length);
543
+ for (const color of colors)
544
+ (0, psdWriter_1.writeColor)(writer, color);
545
+ (0, psdWriter_1.writeUint16)(writer, Math.floor(labColors.byteLength / 3));
546
+ (0, psdWriter_1.writeBytes)(writer, labColors.subarray(0, Math.floor(labColors.byteLength / 3) * 3));
547
+ });
548
+ addHandler(1015, // Grayscale and multichannel transfer function
549
+ // Grayscale and multichannel transfer function
550
+ target => target.grayscaleTransferFunctions !== undefined, (reader, target, left) => target.grayscaleTransferFunctions = readTransferFunctions(reader, left), (writer, target) => writeTransferFunctions(writer, target.grayscaleTransferFunctions));
551
+ addHandler(1016, // Color transfer functions
552
+ // Color transfer functions
553
+ target => target.colorTransferFunctions !== undefined, (reader, target, left) => target.colorTransferFunctions = readTransferFunctions(reader, left), (writer, target) => writeTransferFunctions(writer, target.colorTransferFunctions));
348
554
  addHandler(1080, // Count Information
349
555
  // Count Information
350
556
  target => target.countInformation !== undefined, (reader, target) => {
@@ -407,22 +613,27 @@ addHandler(1069, target => target.layerSelectionIds !== undefined, (reader, targ
407
613
  }
408
614
  });
409
615
  addHandler(1032, target => target.gridAndGuidesInformation !== undefined, (reader, target) => {
616
+ var _a;
410
617
  const version = (0, psdReader_1.readUint32)(reader);
411
618
  const horizontal = (0, psdReader_1.readUint32)(reader);
412
619
  const vertical = (0, psdReader_1.readUint32)(reader);
413
620
  const count = (0, psdReader_1.readUint32)(reader);
414
621
  if (version !== 1)
415
622
  throw new Error(`Invalid 1032 resource version: ${version}`);
416
- target.gridAndGuidesInformation = {
417
- grid: { horizontal, vertical },
418
- guides: [],
419
- };
623
+ const previous = (_a = target.gridAndGuidesInformation) === null || _a === void 0 ? void 0 : _a.guides; // in case guides were already read from 1092
624
+ const guides = [];
420
625
  for (let i = 0; i < count; i++) {
421
- target.gridAndGuidesInformation.guides.push({
626
+ const guide = {
422
627
  location: (0, psdReader_1.readInt32)(reader) / 32,
423
628
  direction: (0, psdReader_1.readUint8)(reader) ? 'horizontal' : 'vertical'
424
- });
629
+ };
630
+ if ((previous === null || previous === void 0 ? void 0 : previous.length) === count && previous[i].color)
631
+ guide.color = previous[i].color;
632
+ if ((previous === null || previous === void 0 ? void 0 : previous.length) === count && previous[i].id)
633
+ guide.id = previous[i].id;
634
+ guides.push(guide);
425
635
  }
636
+ target.gridAndGuidesInformation = { grid: { horizontal, vertical }, guides };
426
637
  }, (writer, target) => {
427
638
  const info = target.gridAndGuidesInformation;
428
639
  const grid = info.grid || { horizontal: 18 * 32, vertical: 18 * 32 };
@@ -436,6 +647,76 @@ addHandler(1032, target => target.gridAndGuidesInformation !== undefined, (reade
436
647
  (0, psdWriter_1.writeUint8)(writer, g.direction === 'horizontal' ? 1 : 0);
437
648
  }
438
649
  });
650
+ const defaultGuideColor = { r: 74, g: 255, b: 255 }; // Photoshop default (cyan)
651
+ addHandler(1092, // Grid and guides information with guide colors (same as 1032 with color of each guide)
652
+ // Grid and guides information with guide colors (same as 1032 with color of each guide)
653
+ target => target.gridAndGuidesInformation !== undefined, (reader, target) => {
654
+ var _a;
655
+ const version = (0, psdReader_1.readUint32)(reader);
656
+ if (version !== 2)
657
+ throw new Error(`Invalid 1092 resource version: ${version}`);
658
+ const horizontal = (0, psdReader_1.readUint32)(reader);
659
+ const vertical = (0, psdReader_1.readUint32)(reader);
660
+ const count = (0, psdReader_1.readUint32)(reader);
661
+ const guides = [];
662
+ for (let i = 0; i < count; i++) {
663
+ const location = (0, psdReader_1.readInt32)(reader) / 32;
664
+ const direction = (0, psdReader_1.readUint8)(reader) ? 'horizontal' : 'vertical';
665
+ (0, psdReader_1.skipBytes)(reader, 1);
666
+ const color = { r: (0, psdReader_1.readUint8)(reader), g: (0, psdReader_1.readUint8)(reader), b: (0, psdReader_1.readUint8)(reader) };
667
+ guides.push({ location, direction, color });
668
+ }
669
+ const existing = (_a = target.gridAndGuidesInformation) === null || _a === void 0 ? void 0 : _a.guides;
670
+ if (existing && existing.length === count) {
671
+ existing.forEach((guide, i) => guide.color = guides[i].color);
672
+ }
673
+ else {
674
+ target.gridAndGuidesInformation = { grid: { horizontal, vertical }, guides };
675
+ }
676
+ }, (writer, target) => {
677
+ const info = target.gridAndGuidesInformation;
678
+ const grid = info.grid || { horizontal: 18 * 32, vertical: 18 * 32 };
679
+ const guides = info.guides || [];
680
+ (0, psdWriter_1.writeUint32)(writer, 2); // version
681
+ (0, psdWriter_1.writeUint32)(writer, Math.round(grid.horizontal));
682
+ (0, psdWriter_1.writeUint32)(writer, Math.round(grid.vertical));
683
+ (0, psdWriter_1.writeUint32)(writer, guides.length);
684
+ for (const g of guides) {
685
+ const color = g.color || defaultGuideColor;
686
+ (0, psdWriter_1.writeInt32)(writer, Math.round(g.location * 32));
687
+ (0, psdWriter_1.writeUint8)(writer, g.direction === 'horizontal' ? 1 : 0);
688
+ (0, psdWriter_1.writeUint8)(writer, 0);
689
+ (0, psdWriter_1.writeUint8)(writer, Math.round(color.r));
690
+ (0, psdWriter_1.writeUint8)(writer, Math.round(color.g));
691
+ (0, psdWriter_1.writeUint8)(writer, Math.round(color.b));
692
+ }
693
+ });
694
+ const emptyGuid = '00000000-0000-0000-0000-000000000000';
695
+ addHandler(1097, // Guide ids
696
+ // Guide ids
697
+ target => !!target.gridAndGuidesInformation && (target.gridAndGuidesInformation.guides || []).every(g => g.id), (reader, target) => {
698
+ var _a;
699
+ const count = (0, psdReader_1.readUint32)(reader);
700
+ const ids = [];
701
+ for (let i = 0; i < count; i++) {
702
+ ids.push((0, psdReader_1.readAsciiString)(reader, (0, psdReader_1.readUint32)(reader)));
703
+ (0, psdReader_1.readUint32)(reader); // unknown, always 0
704
+ (0, psdReader_1.readAsciiString)(reader, (0, psdReader_1.readUint32)(reader)); // unknown, always empty guid
705
+ }
706
+ const guides = (_a = target.gridAndGuidesInformation) === null || _a === void 0 ? void 0 : _a.guides;
707
+ if (guides && guides.length === count)
708
+ guides.forEach((guide, i) => guide.id = ids[i]);
709
+ }, (writer, target) => {
710
+ const guides = target.gridAndGuidesInformation.guides || [];
711
+ (0, psdWriter_1.writeUint32)(writer, guides.length);
712
+ for (const g of guides) {
713
+ (0, psdWriter_1.writeUint32)(writer, g.id.length);
714
+ (0, psdWriter_1.writeAsciiString)(writer, g.id);
715
+ (0, psdWriter_1.writeUint32)(writer, 0);
716
+ (0, psdWriter_1.writeUint32)(writer, emptyGuid.length);
717
+ (0, psdWriter_1.writeAsciiString)(writer, emptyGuid);
718
+ }
719
+ });
439
720
  addHandler(1065, // Layer Comps
440
721
  // Layer Comps
441
722
  target => target.layerComps !== undefined, (reader, target) => {
@@ -529,7 +810,7 @@ target => target.timelineInformation !== undefined, (reader, target) => {
529
810
  workOutTime: (0, descriptor_1.frac)(desc.workOutTime),
530
811
  repeats: desc.LCnt,
531
812
  hasMotion: desc.hasMotion,
532
- globalTracks: (0, descriptor_1.parseTrackList)(desc.globalTrackList, !!reader.logMissingFeatures),
813
+ globalTracks: (0, descriptor_1.parseTrackList)(desc.globalTrackList, reader),
533
814
  };
534
815
  if ((_b = (_a = desc.audioClipGroupList) === null || _a === void 0 ? void 0 : _a.audioClipGroupList) === null || _b === void 0 ? void 0 : _b.length) {
535
816
  target.timelineInformation.audioClipGroups = desc.audioClipGroupList.audioClipGroupList.map(g => ({
@@ -568,7 +849,7 @@ target => target.timelineInformation !== undefined, (reader, target) => {
568
849
  workInTime: timeline.workInTime,
569
850
  workOutTime: timeline.workOutTime,
570
851
  LCnt: timeline.repeats,
571
- globalTrackList: (0, descriptor_1.serializeTrackList)(timeline.globalTracks),
852
+ globalTrackList: (0, descriptor_1.serializeTrackList)(timeline.globalTracks, writer),
572
853
  audioClipGroupList: {
573
854
  audioClipGroupList: ((_a = timeline.audioClipGroups) !== null && _a !== void 0 ? _a : []).map(a => ({
574
855
  groupID: a.id,
@@ -816,27 +1097,127 @@ addHandler(1041, target => target.iccUntaggedProfile !== undefined, (reader, tar
816
1097
  }, (writer, target) => {
817
1098
  (0, psdWriter_1.writeUint8)(writer, target.iccUntaggedProfile ? 1 : 0);
818
1099
  });
819
- helpers_1.MOCK_HANDLERS && addHandler(1039, // ICC Profile
1100
+ addHandler(1039, // ICC Profile
820
1101
  // 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());
1102
+ target => target.iccProfile !== undefined, (reader, target, left) => {
1103
+ target.iccProfile = (0, psdReader_1.readBytes)(reader, left());
825
1104
  }, (writer, target) => {
826
- (0, psdWriter_1.writeBytes)(writer, target._ir1039);
1105
+ (0, psdWriter_1.writeBytes)(writer, target.iccProfile);
827
1106
  });
828
1107
  addHandler(1044, target => target.idsSeedNumber !== undefined, (reader, target) => target.idsSeedNumber = (0, psdReader_1.readUint32)(reader), (writer, target) => (0, psdWriter_1.writeUint32)(writer, target.idsSeedNumber));
1108
+ addHandler(1038, // Color samplers (Photoshop 5.0, replaced by 1073 in CS3)
1109
+ // Color samplers (Photoshop 5.0, replaced by 1073 in CS3)
1110
+ target => target.colorSamplers !== undefined && !target.colorSamplers.some(s => s.depth !== undefined), (reader, target, left) => {
1111
+ var _a;
1112
+ const version = (0, psdReader_1.readUint32)(reader);
1113
+ if (version !== 1)
1114
+ throw new Error(`Invalid color samplers version: ${version}`);
1115
+ if ((_a = target.colorSamplers) === null || _a === void 0 ? void 0 : _a.some(s => s.depth !== undefined))
1116
+ return (0, psdReader_1.skipBytes)(reader, left()); // already read from 1073
1117
+ const count = (0, psdReader_1.readUint32)(reader);
1118
+ target.colorSamplers = [];
1119
+ for (let i = 0; i < count && left() >= 10; i++) {
1120
+ // vertical and horizontal position in 1/16 pixel (inferred from sample files, the specification describes
1121
+ // these values as horizontal and vertical fixed point numbers)
1122
+ const y = (0, psdReader_1.readInt32)(reader) / 16;
1123
+ const x = (0, psdReader_1.readInt32)(reader) / 16;
1124
+ const colorSpace = (0, psdReader_1.readInt16)(reader);
1125
+ target.colorSamplers.push({ x, y, colorSpace });
1126
+ }
1127
+ }, (writer, target) => {
1128
+ (0, psdWriter_1.writeUint32)(writer, 1); // version
1129
+ (0, psdWriter_1.writeUint32)(writer, target.colorSamplers.length);
1130
+ for (const sampler of target.colorSamplers) {
1131
+ (0, psdWriter_1.writeInt32)(writer, Math.round(sampler.y * 16));
1132
+ (0, psdWriter_1.writeInt32)(writer, Math.round(sampler.x * 16));
1133
+ (0, psdWriter_1.writeInt16)(writer, sampler.colorSpace);
1134
+ }
1135
+ });
1136
+ addHandler(1073, // Color samplers (Photoshop CS3)
1137
+ // Color samplers (Photoshop CS3)
1138
+ target => target.colorSamplers !== undefined && target.colorSamplers.some(s => s.depth !== undefined), (reader, target, left) => {
1139
+ const version = (0, psdReader_1.readUint32)(reader);
1140
+ if (version < 1 || version > 3)
1141
+ throw new Error(`Invalid color samplers version: ${version}`);
1142
+ const count = (0, psdReader_1.readUint32)(reader);
1143
+ target.colorSamplers = [];
1144
+ for (let i = 0; i < count && left() >= 10; i++) {
1145
+ // position is fixed point value for sampler version 1 (stored the same way as in 1038 resource) or float for version 2
1146
+ const samplerVersion = version === 3 ? (0, psdReader_1.readUint32)(reader) : version;
1147
+ const y = samplerVersion === 1 ? (0, psdReader_1.readInt32)(reader) / 16 : (0, psdReader_1.readFloat32)(reader);
1148
+ const x = samplerVersion === 1 ? (0, psdReader_1.readInt32)(reader) / 16 : (0, psdReader_1.readFloat32)(reader);
1149
+ const colorSpace = (0, psdReader_1.readInt16)(reader);
1150
+ const depth = version >= 2 ? (0, psdReader_1.readInt16)(reader) : 1;
1151
+ target.colorSamplers.push({ x, y, colorSpace, depth });
1152
+ }
1153
+ }, (writer, target) => {
1154
+ var _a;
1155
+ (0, psdWriter_1.writeUint32)(writer, 3); // version
1156
+ (0, psdWriter_1.writeUint32)(writer, target.colorSamplers.length);
1157
+ for (const sampler of target.colorSamplers) {
1158
+ (0, psdWriter_1.writeUint32)(writer, 1); // sampler version
1159
+ (0, psdWriter_1.writeInt32)(writer, Math.round(sampler.y * 16));
1160
+ (0, psdWriter_1.writeInt32)(writer, Math.round(sampler.x * 16));
1161
+ (0, psdWriter_1.writeInt16)(writer, sampler.colorSpace);
1162
+ (0, psdWriter_1.writeInt16)(writer, (_a = sampler.depth) !== null && _a !== void 0 ? _a : 1);
1163
+ }
1164
+ });
1165
+ addHandler(1022, // Quick Mask information
1166
+ // Quick Mask information
1167
+ target => target.quickMaskInfo !== undefined, (reader, target) => {
1168
+ const channelId = (0, psdReader_1.readUint16)(reader);
1169
+ const initiallyEmpty = !!(0, psdReader_1.readUint8)(reader);
1170
+ target.quickMaskInfo = { channelId, initiallyEmpty };
1171
+ }, (writer, target) => {
1172
+ (0, psdWriter_1.writeUint16)(writer, target.quickMaskInfo.channelId);
1173
+ (0, psdWriter_1.writeUint8)(writer, target.quickMaskInfo.initiallyEmpty ? 1 : 0);
1174
+ });
1175
+ addHandler(1074, // Measurement scale
1176
+ // Measurement scale
1177
+ target => target.measurementScale !== undefined, (reader, target, left) => {
1178
+ target.measurementScale = (0, psdReader_1.readBytes)(reader, left());
1179
+ }, (writer, target) => {
1180
+ (0, psdWriter_1.writeBytes)(writer, target.measurementScale);
1181
+ });
1182
+ addHandler(1042, // Effects visible (only present when effects are hidden)
1183
+ // Effects visible (only present when effects are hidden)
1184
+ target => target.effectsVisible !== undefined, (reader, target) => {
1185
+ target.effectsVisible = !!(0, psdReader_1.readUint8)(reader);
1186
+ }, (writer, target) => {
1187
+ (0, psdWriter_1.writeUint8)(writer, target.effectsVisible ? 1 : 0);
1188
+ });
829
1189
  addHandler(1036, target => target.thumbnail !== undefined || target.thumbnailRaw !== undefined, (reader, target, left) => {
830
1190
  const format = (0, psdReader_1.readUint32)(reader); // 1 = kJpegRGB, 0 = kRawRGB
831
1191
  const width = (0, psdReader_1.readUint32)(reader);
832
1192
  const height = (0, psdReader_1.readUint32)(reader);
833
- (0, psdReader_1.readUint32)(reader); // widthBytes = (width * bits_per_pixel + 31) / 32 * 4.
1193
+ const widthBytes = (0, psdReader_1.readUint32)(reader); // widthBytes = (width * bits_per_pixel + 31) / 32 * 4.
834
1194
  (0, psdReader_1.readUint32)(reader); // totalSize = widthBytes * height * planes
835
1195
  (0, psdReader_1.readUint32)(reader); // sizeAfterCompression
836
1196
  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})`);
1197
+ (0, psdReader_1.readUint16)(reader); // planes, should be 1 (some applications write 3)
1198
+ if (format === 0 && bitsPerPixel === 24 && widthBytes >= width * 3 && widthBytes * height <= left()) {
1199
+ // raw RGB data, rows are padded to 4 bytes
1200
+ if (reader.useRawThumbnail) {
1201
+ reader.logMissingFeatures && reader.log('Raw thumbnail data is not supported with useRawThumbnail option');
1202
+ (0, psdReader_1.skipBytes)(reader, left());
1203
+ return;
1204
+ }
1205
+ const data = (0, psdReader_1.readBytes)(reader, widthBytes * height);
1206
+ const imageData = (0, helpers_1.createImageData)(width, height);
1207
+ for (let y = 0, dst = 0; y < height; y++) {
1208
+ for (let x = 0, src = y * widthBytes; x < width; x++, src += 3, dst += 4) {
1209
+ imageData.data[dst + 0] = data[src + 0];
1210
+ imageData.data[dst + 1] = data[src + 1];
1211
+ imageData.data[dst + 2] = data[src + 2];
1212
+ imageData.data[dst + 3] = 255;
1213
+ }
1214
+ }
1215
+ target.thumbnail = (0, helpers_1.imageDataToCanvas)(imageData);
1216
+ (0, psdReader_1.skipBytes)(reader, left());
1217
+ return;
1218
+ }
1219
+ if (format !== 1 || bitsPerPixel !== 24) {
1220
+ reader.logMissingFeatures && reader.log(`Invalid thumbnail data (format: ${format}, bitsPerPixel: ${bitsPerPixel})`);
840
1221
  (0, psdReader_1.skipBytes)(reader, left());
841
1222
  return;
842
1223
  }
@@ -903,13 +1284,12 @@ addHandler(1057, target => target.versionInfo !== undefined, (reader, target, le
903
1284
  (0, psdWriter_1.writeUnicodeString)(writer, versionInfo.readerName);
904
1285
  (0, psdWriter_1.writeUint32)(writer, versionInfo.fileVersion);
905
1286
  });
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());
1287
+ addHandler(1058, // EXIF data 1
1288
+ // EXIF data 1
1289
+ target => target.exifData !== undefined, (reader, target, left) => {
1290
+ target.exifData = (0, psdReader_1.readBytes)(reader, left());
911
1291
  }, (writer, target) => {
912
- (0, psdWriter_1.writeBytes)(writer, target._ir1058);
1292
+ (0, psdWriter_1.writeBytes)(writer, target.exifData);
913
1293
  });
914
1294
  addHandler(7000, target => target.imageReadyVariables !== undefined, (reader, target, left) => {
915
1295
  target.imageReadyVariables = readUtf8String(reader, left());
@@ -928,22 +1308,101 @@ addHandler(1088, target => target.pathSelectionState !== undefined, (reader, tar
928
1308
  const desc = { 'null': (0, descriptor_1.pathSelectionStateToReference)(target.pathSelectionState) };
929
1309
  (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
930
1310
  });
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());
1311
+ addHandler(1025, // Work path
1312
+ // Work path
1313
+ target => target.workPath !== undefined, (reader, target, left, { width, height }) => {
1314
+ target.workPath = { paths: [] };
1315
+ (0, additionalInfo_1.readVectorMask)(reader, target.workPath, width, height, left());
1316
+ (0, psdReader_1.skipBytes)(reader, left());
1317
+ }, (writer, target, _index, { width, height }) => {
1318
+ (0, additionalInfo_1.writeVectorMask)(writer, target.workPath, width, height);
1319
+ });
1320
+ const MAX_SAVED_PATHS = 999; // ids 2000-2998
1321
+ addHandler(2000, // Saved paths (one resource for each path, named after the path)
1322
+ // Saved paths (one resource for each path, named after the path)
1323
+ target => target.savedPaths ? Math.min(target.savedPaths.length, MAX_SAVED_PATHS) : 0, (reader, target, left, { signature, id, name, width, height }) => {
1324
+ var _a, _b;
1325
+ if (signature !== '8BIM') { // ImageReady ('MeSa') resources use the same ids for other data
1326
+ reader.logMissingFeatures && reader.log(`Unhandled image resource: ${signature} ${id}`);
1327
+ (0, psdReader_1.skipBytes)(reader, left());
1328
+ return;
1329
+ }
1330
+ const savedPaths = (_a = target.savedPaths) !== null && _a !== void 0 ? _a : (target.savedPaths = []);
1331
+ const path = { name: decodeEncodedString(reader, name), paths: [] };
1332
+ (0, additionalInfo_1.readVectorMask)(reader, path, width, height, left());
1333
+ (0, psdReader_1.skipBytes)(reader, left());
1334
+ const keyDescriptorList = (_b = target.savedPathsOrigination) === null || _b === void 0 ? void 0 : _b[savedPaths.length];
1335
+ if (keyDescriptorList)
1336
+ path.vectorOrigination = { keyDescriptorList };
1337
+ savedPaths.push(path);
1338
+ }, (writer, target, index, { width, height }) => {
1339
+ (0, additionalInfo_1.writeVectorMask)(writer, target.savedPaths[index], width, height);
1340
+ }, { keyCount: MAX_SAVED_PATHS, name: (target, index) => toShortAsciiString(target.savedPaths[index].name) });
1341
+ addHandler(3000, // Origin path info (origination data of saved paths)
1342
+ // Origin path info (origination data of saved paths)
1343
+ target => { var _a; return !!((_a = target.savedPaths) === null || _a === void 0 ? void 0 : _a.some(path => path.vectorOrigination)); }, (reader, target, left) => {
1344
+ const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
1345
+ desc.keyRootDescriptorList.forEach((item, i) => {
1346
+ var _a, _b;
1347
+ const keyDescriptorList = (0, additionalInfo_1.parseKeyDescriptorList)(item);
1348
+ if (!keyDescriptorList.length)
1349
+ return; // written for paths without origination data
1350
+ const path = (_a = target.savedPaths) === null || _a === void 0 ? void 0 : _a[i];
1351
+ if (path) {
1352
+ path.vectorOrigination = { keyDescriptorList };
1353
+ }
1354
+ else { // saved paths are stored after this resource
1355
+ ((_b = target.savedPathsOrigination) !== null && _b !== void 0 ? _b : (target.savedPathsOrigination = []))[i] = keyDescriptorList;
1356
+ }
1357
+ });
1358
+ (0, psdReader_1.skipBytes)(reader, left());
934
1359
  }, (writer, target) => {
935
- (0, psdWriter_1.writeBytes)(writer, target._ir1025);
1360
+ const desc = {
1361
+ keyRootDescriptorList: target.savedPaths.slice(0, MAX_SAVED_PATHS)
1362
+ .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 : []); }),
1363
+ };
1364
+ (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
1365
+ }, { name: () => 'OriginDataIRB' });
1366
+ addHandler(2999, // Clipping path
1367
+ // Clipping path
1368
+ target => target.clippingPath !== undefined, (reader, target, left) => {
1369
+ const name = readEncodedString(reader);
1370
+ const flatness = (0, psdReader_1.readFixedPoint32)(reader);
1371
+ (0, psdReader_1.skipBytes)(reader, left()); // fill rule (ignored by Photoshop)
1372
+ target.clippingPath = { name, flatness };
1373
+ }, (writer, target) => {
1374
+ writeEncodedString(writer, target.clippingPath.name);
1375
+ (0, psdWriter_1.writeFixedPoint32)(writer, target.clippingPath.flatness);
1376
+ (0, psdWriter_1.writeUint16)(writer, 1); // fill rule (ignored by Photoshop)
936
1377
  });
937
1378
  const FrmD = (0, helpers_1.createEnum)('FrmD', 'auto', {
938
1379
  auto: 'Auto',
939
1380
  none: 'None',
940
1381
  dispose: 'Disp',
941
1382
  });
942
- addHandler(4000, // Plug-In resource(s)
943
- // Plug-In resource(s)
944
- target => target.animations !== undefined, (reader, target, left) => {
1383
+ // plug-in resources are written with consecutive ids starting at 4000, in the same order as Photoshop writes them
1384
+ function pluginResourceKeys(target) {
1385
+ const keys = [];
1386
+ if (target.outputSettings !== undefined)
1387
+ keys.push('mset');
1388
+ if (target.animations !== undefined)
1389
+ keys.push('mani', 'mfri');
1390
+ return keys;
1391
+ }
1392
+ addHandler(4000, // Plug-In resource(s), identified by key stored in the data (ids 4000-4999)
1393
+ // Plug-In resource(s), identified by key stored in the data (ids 4000-4999)
1394
+ target => pluginResourceKeys(target).length, (reader, target, left) => {
945
1395
  const key = (0, psdReader_1.readSignature)(reader);
946
- if (key === 'mani') {
1396
+ if (key === 'mset') {
1397
+ // Save for Web output settings
1398
+ target.outputSettings = (0, descriptor_1.readVersionAndDescriptor)(reader, true);
1399
+ (0, psdReader_1.skipBytes)(reader, left());
1400
+ }
1401
+ else if (key === 'mfri') {
1402
+ // frame count, active frame and animation count, same data as in animations (mani)
1403
+ (0, psdReader_1.skipBytes)(reader, left());
1404
+ }
1405
+ else if (key === 'mani') {
947
1406
  (0, psdReader_1.checkSignature)(reader, 'IRFR');
948
1407
  (0, psdReader_1.readSection)(reader, 1, left => {
949
1408
  while (left() > 0) {
@@ -969,6 +1428,7 @@ target => target.animations !== undefined, (reader, target, left) => {
969
1428
  };
970
1429
  // console.log('#4000 AnDs', require('util').inspect(desc, false, 99, true));
971
1430
  // console.log('#4000 AnDs:result', require('util').inspect(target.animations, false, 99, true));
1431
+ (0, psdReader_1.skipBytes)(reader, left()); // padding
972
1432
  }
973
1433
  else if (key === 'Roll') {
974
1434
  const bytes = (0, psdReader_1.readBytes)(reader, left());
@@ -976,20 +1436,39 @@ target => target.animations !== undefined, (reader, target, left) => {
976
1436
  }
977
1437
  else {
978
1438
  reader.logMissingFeatures && reader.log('Unhandled subsection in #4000', key);
1439
+ (0, psdReader_1.skipBytes)(reader, left());
979
1440
  }
980
1441
  });
981
1442
  }
982
1443
  });
1444
+ (0, psdReader_1.skipBytes)(reader, left()); // unknown data after animations section
983
1445
  }
984
1446
  else if (key === 'mopt') {
985
1447
  const bytes = (0, psdReader_1.readBytes)(reader, left());
986
1448
  reader.logDevFeatures && reader.log('#4000 mopt', bytes);
987
1449
  }
988
1450
  else {
989
- reader.logMissingFeatures && reader.log('Unhandled key in #4000:', key);
1451
+ reader.logMissingFeatures && reader.log(`Unhandled plug-in resource key: ${key}`);
1452
+ (0, psdReader_1.skipBytes)(reader, left());
990
1453
  }
991
- }, (writer, target) => {
992
- if (target.animations) {
1454
+ }, (writer, target, index) => {
1455
+ var _a, _b;
1456
+ const key = pluginResourceKeys(target)[index];
1457
+ if (key === 'mset') {
1458
+ (0, psdWriter_1.writeSignature)(writer, 'mset');
1459
+ (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', target.outputSettings, descriptor_1.outputSettingsRoot);
1460
+ }
1461
+ else if (key === 'mfri') {
1462
+ const animations = target.animations;
1463
+ (0, psdWriter_1.writeSignature)(writer, 'mfri');
1464
+ (0, psdWriter_1.writeUint32)(writer, 2); // version
1465
+ (0, psdWriter_1.writeUint32)(writer, 16); // length
1466
+ (0, psdWriter_1.writeUint32)(writer, animations.frames.length);
1467
+ (0, psdWriter_1.writeUint32)(writer, (_b = (_a = animations.animations[0]) === null || _a === void 0 ? void 0 : _a.activeFrame) !== null && _b !== void 0 ? _b : 0);
1468
+ (0, psdWriter_1.writeUint32)(writer, animations.animations.length);
1469
+ (0, psdWriter_1.writeUint32)(writer, 0);
1470
+ }
1471
+ else if (key === 'mani') {
993
1472
  (0, psdWriter_1.writeSignature)(writer, 'mani');
994
1473
  (0, psdWriter_1.writeSignature)(writer, 'IRFR');
995
1474
  (0, psdWriter_1.writeSection)(writer, 1, () => {
@@ -1031,42 +1510,5 @@ target => target.animations !== undefined, (reader, target, left) => {
1031
1510
  // });
1032
1511
  });
1033
1512
  }
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
- });
1513
+ }, { keyCount: 1000 });
1072
1514
  //# sourceMappingURL=imageResources.js.map