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.
- package/.v8-cache/v24.7.0-x64-ef5a0af0/03e19709 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/05135617 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/1130885f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/226e2801 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/2a19133e +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/4511bacf +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/68416cb2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/71df9cb3 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/7ea06cea +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/87cf2209 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/932f0770 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/acc36e66 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/b3c2fab7 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c0b789d2 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/c314aece +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cfc49f4f +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/cff9434a +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/d13d7610 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/dc86f000 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e03e2acd +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6745c2b +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/e6b99945 +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/eeeebdfe +0 -0
- package/.v8-cache/v24.7.0-x64-ef5a0af0/f6fd8125 +0 -0
- package/CHANGELOG.md +100 -0
- package/LICENSE +5 -0
- package/README.md +4 -7
- package/README_PSD.md +261 -84
- package/TODO.md +13 -84
- package/dist/abr.d.ts +11 -4
- package/dist/abr.js +362 -230
- package/dist/abr.js.map +1 -1
- package/dist/additionalInfo.d.ts +56 -2
- package/dist/additionalInfo.js +828 -361
- package/dist/additionalInfo.js.map +1 -1
- package/dist/ase.d.ts +6 -1
- package/dist/ase.js +61 -61
- package/dist/ase.js.map +1 -1
- package/dist/bundle.js +3321 -1364
- package/dist/descriptor.d.ts +28 -13
- package/dist/descriptor.js +295 -241
- package/dist/descriptor.js.map +1 -1
- package/dist/helpers.d.ts +7 -1
- package/dist/helpers.js +246 -4
- package/dist/helpers.js.map +1 -1
- package/dist/imageResources.d.ts +15 -3
- package/dist/imageResources.js +586 -144
- package/dist/imageResources.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/jpeg.js +8 -8
- package/dist/jpeg.js.map +1 -1
- package/dist/psd.d.ts +292 -19
- package/dist/psd.js.map +1 -1
- package/dist/psdReader.d.ts +10 -0
- package/dist/psdReader.js +424 -216
- package/dist/psdReader.js.map +1 -1
- package/dist/psdWriter.d.ts +2 -0
- package/dist/psdWriter.js +373 -113
- package/dist/psdWriter.js.map +1 -1
- package/dist/text.d.ts +32 -1
- package/dist/text.js +75 -6
- package/dist/text.js.map +1 -1
- package/dist/utf8.js +0 -3
- package/dist/utf8.js.map +1 -1
- package/dist-es/abr.d.ts +11 -4
- package/dist-es/abr.js +362 -230
- package/dist-es/abr.js.map +1 -1
- package/dist-es/additionalInfo.d.ts +56 -2
- package/dist-es/additionalInfo.js +828 -361
- package/dist-es/additionalInfo.js.map +1 -1
- package/dist-es/ase.d.ts +6 -1
- package/dist-es/ase.js +61 -61
- package/dist-es/ase.js.map +1 -1
- package/dist-es/descriptor.d.ts +28 -13
- package/dist-es/descriptor.js +295 -241
- package/dist-es/descriptor.js.map +1 -1
- package/dist-es/helpers.d.ts +7 -1
- package/dist-es/helpers.js +246 -4
- package/dist-es/helpers.js.map +1 -1
- package/dist-es/imageResources.d.ts +15 -3
- package/dist-es/imageResources.js +586 -144
- package/dist-es/imageResources.js.map +1 -1
- package/dist-es/index.d.ts +1 -0
- package/dist-es/index.js +1 -0
- package/dist-es/index.js.map +1 -1
- package/dist-es/jpeg.js +8 -8
- package/dist-es/jpeg.js.map +1 -1
- package/dist-es/psd.d.ts +292 -19
- package/dist-es/psd.js.map +1 -1
- package/dist-es/psdReader.d.ts +10 -0
- package/dist-es/psdReader.js +424 -216
- package/dist-es/psdReader.js.map +1 -1
- package/dist-es/psdWriter.d.ts +2 -0
- package/dist-es/psdWriter.js +373 -113
- package/dist-es/psdWriter.js.map +1 -1
- package/dist-es/text.d.ts +32 -1
- package/dist-es/text.js +75 -6
- package/dist-es/text.js.map +1 -1
- package/dist-es/utf8.js +0 -3
- package/dist-es/utf8.js.map +1 -1
- package/package.json +2 -2
- package/perf.js +312 -9
- package/src/abr.ts +382 -235
- package/src/additionalInfo.ts +1071 -482
- package/src/ase.ts +66 -61
- package/src/descriptor.ts +291 -242
- package/src/helpers.ts +266 -3
- package/src/imageResources.ts +736 -169
- package/src/index.ts +1 -0
- package/src/jpeg.ts +8 -8
- package/src/psd.ts +271 -32
- package/src/psdReader.ts +440 -221
- package/src/psdWriter.ts +402 -110
- package/src/text.ts +93 -7
- package/src/utf8.ts +0 -4
package/dist/additionalInfo.js
CHANGED
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.booleanOperations = exports.infoHandlersMap = exports.infoHandlers = void 0;
|
|
4
4
|
exports.readBezierKnot = readBezierKnot;
|
|
5
5
|
exports.readVectorMask = readVectorMask;
|
|
6
|
+
exports.writeVectorMask = writeVectorMask;
|
|
7
|
+
exports.parseKeyDescriptorList = parseKeyDescriptorList;
|
|
8
|
+
exports.serializeKeyDescriptorList = serializeKeyDescriptorList;
|
|
6
9
|
exports.hasMultiEffects = hasMultiEffects;
|
|
7
10
|
const base64_js_1 = require("base64-js");
|
|
8
11
|
const effectsHelpers_1 = require("./effectsHelpers");
|
|
@@ -33,6 +36,7 @@ function readLength64(reader) {
|
|
|
33
36
|
return (0, psdReader_1.readUint32)(reader);
|
|
34
37
|
}
|
|
35
38
|
addHandler('TySh', hasKey('text'), (reader, target, leftBytes) => {
|
|
39
|
+
var _a;
|
|
36
40
|
if ((0, psdReader_1.readInt16)(reader) !== 1)
|
|
37
41
|
throw new Error(`Invalid TySh version`);
|
|
38
42
|
const transform = [];
|
|
@@ -79,7 +83,8 @@ addHandler('TySh', hasKey('text'), (reader, target, leftBytes) => {
|
|
|
79
83
|
// require('fs').writeFileSync('before.txt', require('util').inspect(before, false, 99, false), 'utf8');
|
|
80
84
|
// require('fs').writeFileSync('after.txt', require('util').inspect(after, false, 99, false), 'utf8');
|
|
81
85
|
// console.log(require('util').inspect(parseEngineData(text.EngineData), false, 99, true));
|
|
82
|
-
|
|
86
|
+
// descriptor anti-alias value is more reliable than the one from engine data
|
|
87
|
+
target.text = Object.assign(Object.assign(Object.assign({}, target.text), textData), { antiAlias: (_a = target.text.antiAlias) !== null && _a !== void 0 ? _a : textData.antiAlias });
|
|
83
88
|
// console.log(require('util').inspect(target.text, false, 99, true));
|
|
84
89
|
}
|
|
85
90
|
(0, psdReader_1.skipBytes)(reader, leftBytes());
|
|
@@ -103,11 +108,77 @@ addHandler('TySh', hasKey('text'), (reader, target, leftBytes) => {
|
|
|
103
108
|
(0, psdWriter_1.writeFloat32)(writer, (_d = text.bottom) !== null && _d !== void 0 ? _d : 0);
|
|
104
109
|
// writeZeros(writer, 2);
|
|
105
110
|
});
|
|
111
|
+
// type tool info from Photoshop 5.0 and 5.5, converted to regular text data (written as 'TySh')
|
|
112
|
+
addHandler('tySh', () => false, (reader, target, left) => {
|
|
113
|
+
if ((0, psdReader_1.readInt16)(reader) !== 1)
|
|
114
|
+
throw new Error(`Invalid tySh version`);
|
|
115
|
+
const transform = [];
|
|
116
|
+
for (let i = 0; i < 6; i++)
|
|
117
|
+
transform.push((0, psdReader_1.readFloat64)(reader));
|
|
118
|
+
if ((0, psdReader_1.readInt16)(reader) !== 6)
|
|
119
|
+
throw new Error(`Invalid tySh font version`);
|
|
120
|
+
const data = { transform, faces: [], styles: [], lines: [], color: { r: 0, g: 0, b: 0 }, antiAlias: false };
|
|
121
|
+
const facesCount = (0, psdReader_1.readInt16)(reader);
|
|
122
|
+
for (let i = 0; i < facesCount; i++) {
|
|
123
|
+
const mark = (0, psdReader_1.readInt16)(reader);
|
|
124
|
+
(0, psdReader_1.readInt32)(reader); // font type
|
|
125
|
+
const name = (0, psdReader_1.readPascalString)(reader, 1);
|
|
126
|
+
const familyName = (0, psdReader_1.readPascalString)(reader, 1);
|
|
127
|
+
const styleName = (0, psdReader_1.readPascalString)(reader, 1);
|
|
128
|
+
const script = (0, psdReader_1.readInt16)(reader);
|
|
129
|
+
const axesCount = (0, psdReader_1.readInt32)(reader);
|
|
130
|
+
if (axesCount < 0 || axesCount * 4 > left())
|
|
131
|
+
throw new Error(`Invalid tySh design axes count`);
|
|
132
|
+
(0, psdReader_1.skipBytes)(reader, axesCount * 4);
|
|
133
|
+
data.faces.push({ mark, name, familyName, styleName, script });
|
|
134
|
+
}
|
|
135
|
+
const stylesCount = (0, psdReader_1.readInt16)(reader);
|
|
136
|
+
for (let i = 0; i < stylesCount; i++) {
|
|
137
|
+
const mark = (0, psdReader_1.readInt16)(reader);
|
|
138
|
+
const faceMark = (0, psdReader_1.readInt16)(reader);
|
|
139
|
+
const size = (0, psdReader_1.readInt32)(reader);
|
|
140
|
+
const tracking = (0, psdReader_1.readInt32)(reader);
|
|
141
|
+
const kerning = (0, psdReader_1.readInt32)(reader);
|
|
142
|
+
const leading = (0, psdReader_1.readInt32)(reader);
|
|
143
|
+
const baselineShift = (0, psdReader_1.readInt32)(reader);
|
|
144
|
+
const autoKerning = !!(0, psdReader_1.readUint8)(reader);
|
|
145
|
+
(0, psdReader_1.readUint8)(reader); // rotate
|
|
146
|
+
data.styles.push({ mark, faceMark, size, tracking, kerning, leading, baselineShift, autoKerning });
|
|
147
|
+
}
|
|
148
|
+
(0, psdReader_1.readInt16)(reader); // type (0 = point, 1 = paragraph)
|
|
149
|
+
(0, psdReader_1.readInt32)(reader); // scaling factor
|
|
150
|
+
(0, psdReader_1.readInt32)(reader); // character count
|
|
151
|
+
(0, psdReader_1.readInt32)(reader); // horizontal placement
|
|
152
|
+
(0, psdReader_1.readInt32)(reader); // vertical placement
|
|
153
|
+
(0, psdReader_1.readInt32)(reader); // select start
|
|
154
|
+
(0, psdReader_1.readInt32)(reader); // select end
|
|
155
|
+
const linesCount = (0, psdReader_1.readInt16)(reader);
|
|
156
|
+
for (let i = 0; i < linesCount; i++) {
|
|
157
|
+
const charCount = (0, psdReader_1.readInt32)(reader);
|
|
158
|
+
const orientation = (0, psdReader_1.readInt16)(reader);
|
|
159
|
+
const alignment = (0, psdReader_1.readInt16)(reader);
|
|
160
|
+
if (charCount < 0 || charCount * 4 > left())
|
|
161
|
+
throw new Error(`Invalid tySh character count`);
|
|
162
|
+
const chars = [];
|
|
163
|
+
for (let j = 0; j < charCount; j++) {
|
|
164
|
+
const code = (0, psdReader_1.readUint16)(reader);
|
|
165
|
+
const style = (0, psdReader_1.readInt16)(reader);
|
|
166
|
+
chars.push({ code, style });
|
|
167
|
+
}
|
|
168
|
+
data.lines.push({ orientation, alignment, chars });
|
|
169
|
+
}
|
|
170
|
+
data.color = (0, psdReader_1.readColor)(reader);
|
|
171
|
+
data.antiAlias = !!(0, psdReader_1.readUint8)(reader);
|
|
172
|
+
if (!target.text)
|
|
173
|
+
target.text = (0, text_1.decodeLegacyTextData)(data);
|
|
174
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
175
|
+
}, () => { });
|
|
106
176
|
// vector fills
|
|
107
177
|
addHandler('SoCo', target => target.vectorFill !== undefined && target.vectorStroke === undefined &&
|
|
108
|
-
target.vectorFill.type === 'color', (reader, target) => {
|
|
178
|
+
target.vectorFill.type === 'color', (reader, target, left) => {
|
|
109
179
|
const descriptor = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
110
180
|
target.vectorFill = (0, descriptor_1.parseVectorContent)(descriptor);
|
|
181
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
111
182
|
}, (writer, target) => {
|
|
112
183
|
const { descriptor } = (0, descriptor_1.serializeVectorContent)(target.vectorFill);
|
|
113
184
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', descriptor);
|
|
@@ -209,25 +280,8 @@ function readVectorMask(reader, vectorMask, width, height, size) {
|
|
|
209
280
|
}
|
|
210
281
|
return paths;
|
|
211
282
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
throw new Error('Invalid vmsk version');
|
|
215
|
-
target.vectorMask = { paths: [] };
|
|
216
|
-
const vectorMask = target.vectorMask;
|
|
217
|
-
const flags = (0, psdReader_1.readUint32)(reader);
|
|
218
|
-
vectorMask.invert = (flags & 1) !== 0;
|
|
219
|
-
vectorMask.notLink = (flags & 2) !== 0;
|
|
220
|
-
vectorMask.disable = (flags & 4) !== 0;
|
|
221
|
-
readVectorMask(reader, vectorMask, width, height, left());
|
|
222
|
-
// drawBezierPaths(vectorMask.paths, width, height, 'out.png');
|
|
223
|
-
(0, psdReader_1.skipBytes)(reader, left());
|
|
224
|
-
}, (writer, target, { width, height }) => {
|
|
225
|
-
const vectorMask = target.vectorMask;
|
|
226
|
-
const flags = (vectorMask.invert ? 1 : 0) |
|
|
227
|
-
(vectorMask.notLink ? 2 : 0) |
|
|
228
|
-
(vectorMask.disable ? 4 : 0);
|
|
229
|
-
(0, psdWriter_1.writeUint32)(writer, 3); // version
|
|
230
|
-
(0, psdWriter_1.writeUint32)(writer, flags);
|
|
283
|
+
// componentIndices - write index of path component for each subpath (Photoshop writes them for layer vector masks)
|
|
284
|
+
function writeVectorMask(writer, vectorMask, width, height, componentIndices = false) {
|
|
231
285
|
// initial entry
|
|
232
286
|
(0, psdWriter_1.writeUint16)(writer, 6);
|
|
233
287
|
(0, psdWriter_1.writeZeros)(writer, 24);
|
|
@@ -244,12 +298,18 @@ addHandler('vmsk', hasKey('vectorMask'), (reader, target, left, { width, height
|
|
|
244
298
|
(0, psdWriter_1.writeUint16)(writer, 8);
|
|
245
299
|
(0, psdWriter_1.writeUint16)(writer, vectorMask.fillStartsWithAllPixels ? 1 : 0);
|
|
246
300
|
(0, psdWriter_1.writeZeros)(writer, 22);
|
|
301
|
+
let componentIndex = -1;
|
|
247
302
|
for (const path of vectorMask.paths) {
|
|
303
|
+
// subpaths without operation are part of the same path component as previous subpath
|
|
304
|
+
if (path.operation || componentIndex < 0)
|
|
305
|
+
componentIndex++;
|
|
248
306
|
(0, psdWriter_1.writeUint16)(writer, path.open ? 3 : 0);
|
|
249
307
|
(0, psdWriter_1.writeUint16)(writer, path.knots.length);
|
|
250
308
|
(0, psdWriter_1.writeUint16)(writer, path.operation ? exports.booleanOperations.indexOf(path.operation) : -1); // -1 for undefined
|
|
251
309
|
(0, psdWriter_1.writeUint16)(writer, path.fillRule === 'non-zero' ? 2 : 1);
|
|
252
|
-
(0, psdWriter_1.writeZeros)(writer,
|
|
310
|
+
(0, psdWriter_1.writeZeros)(writer, 4);
|
|
311
|
+
(0, psdWriter_1.writeUint32)(writer, componentIndices ? componentIndex : 0);
|
|
312
|
+
(0, psdWriter_1.writeZeros)(writer, 10);
|
|
253
313
|
const linkedKnot = path.open ? 4 : 1;
|
|
254
314
|
const unlinkedKnot = path.open ? 5 : 2;
|
|
255
315
|
for (const { linked, points } of path.knots) {
|
|
@@ -257,8 +317,29 @@ addHandler('vmsk', hasKey('vectorMask'), (reader, target, left, { width, height
|
|
|
257
317
|
writeBezierKnot(writer, points, width, height);
|
|
258
318
|
}
|
|
259
319
|
}
|
|
320
|
+
}
|
|
321
|
+
addHandler('vmsk', hasKey('vectorMask'), (reader, target, left, { width, height }) => {
|
|
322
|
+
if ((0, psdReader_1.readUint32)(reader) !== 3)
|
|
323
|
+
throw new Error('Invalid vmsk version');
|
|
324
|
+
target.vectorMask = { paths: [] };
|
|
325
|
+
const vectorMask = target.vectorMask;
|
|
326
|
+
const flags = (0, psdReader_1.readUint32)(reader);
|
|
327
|
+
vectorMask.invert = (flags & 1) !== 0;
|
|
328
|
+
vectorMask.notLink = (flags & 2) !== 0;
|
|
329
|
+
vectorMask.disable = (flags & 4) !== 0;
|
|
330
|
+
readVectorMask(reader, vectorMask, width, height, left());
|
|
331
|
+
// drawBezierPaths(vectorMask.paths, width, height, 'out.png');
|
|
332
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
333
|
+
}, (writer, target, { width, height }) => {
|
|
334
|
+
const vectorMask = target.vectorMask;
|
|
335
|
+
const flags = (vectorMask.invert ? 1 : 0) |
|
|
336
|
+
(vectorMask.notLink ? 2 : 0) |
|
|
337
|
+
(vectorMask.disable ? 4 : 0);
|
|
338
|
+
(0, psdWriter_1.writeUint32)(writer, 3); // version
|
|
339
|
+
(0, psdWriter_1.writeUint32)(writer, flags);
|
|
340
|
+
writeVectorMask(writer, vectorMask, width, height, true);
|
|
260
341
|
});
|
|
261
|
-
//
|
|
342
|
+
// written instead of 'vmsk' for layers with vector stroke ('vscg' section)
|
|
262
343
|
addHandlerAlias('vsms', 'vmsk');
|
|
263
344
|
// addHandlerAlias('vmsk', 'vsms');
|
|
264
345
|
addHandler('vowv', // something with vectors?
|
|
@@ -267,12 +348,8 @@ hasKey('vowv'), (reader, target) => {
|
|
|
267
348
|
}, (writer, target) => {
|
|
268
349
|
(0, psdWriter_1.writeUint32)(writer, target.vowv);
|
|
269
350
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
throw new Error(`Invalid vogk version`);
|
|
273
|
-
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
274
|
-
// console.log(require('util').inspect(desc, false, 99, true));
|
|
275
|
-
target.vectorOrigination = { keyDescriptorList: [] };
|
|
351
|
+
function parseKeyDescriptorList(desc) {
|
|
352
|
+
const keyDescriptorList = [];
|
|
276
353
|
for (const i of desc.keyDescriptorList) {
|
|
277
354
|
const item = {};
|
|
278
355
|
if (i.keyShapeInvalidated != null)
|
|
@@ -311,15 +388,14 @@ addHandler('vogk', hasKey('vectorOrigination'), (reader, target, left) => {
|
|
|
311
388
|
if (trnf) {
|
|
312
389
|
item.transform = [trnf.xx, trnf.xy, trnf.yx, trnf.yy, trnf.tx, trnf.ty];
|
|
313
390
|
}
|
|
314
|
-
|
|
391
|
+
keyDescriptorList.push(item);
|
|
315
392
|
}
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
const orig = target.vectorOrigination;
|
|
393
|
+
return keyDescriptorList;
|
|
394
|
+
}
|
|
395
|
+
function serializeKeyDescriptorList(keyDescriptorList) {
|
|
320
396
|
const desc = { keyDescriptorList: [] };
|
|
321
|
-
for (let i = 0; i <
|
|
322
|
-
const item =
|
|
397
|
+
for (let i = 0; i < keyDescriptorList.length; i++) {
|
|
398
|
+
const item = keyDescriptorList[i];
|
|
323
399
|
desc.keyDescriptorList.push({}); // we're adding keyOriginIndex at the end
|
|
324
400
|
const out = desc.keyDescriptorList[desc.keyDescriptorList.length - 1];
|
|
325
401
|
if (item.keyOriginType != null)
|
|
@@ -370,20 +446,31 @@ addHandler('vogk', hasKey('vectorOrigination'), (reader, target, left) => {
|
|
|
370
446
|
out.keyShapeInvalidated = item.keyShapeInvalidated;
|
|
371
447
|
out.keyOriginIndex = i;
|
|
372
448
|
}
|
|
449
|
+
return desc;
|
|
450
|
+
}
|
|
451
|
+
addHandler('vogk', hasKey('vectorOrigination'), (reader, target, left) => {
|
|
452
|
+
if ((0, psdReader_1.readInt32)(reader) !== 1)
|
|
453
|
+
throw new Error(`Invalid vogk version`);
|
|
454
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
455
|
+
// console.log(require('util').inspect(desc, false, 99, true));
|
|
456
|
+
target.vectorOrigination = { keyDescriptorList: parseKeyDescriptorList(desc) };
|
|
457
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
458
|
+
}, (writer, target) => {
|
|
459
|
+
const desc = serializeKeyDescriptorList(target.vectorOrigination.keyDescriptorList);
|
|
373
460
|
(0, psdWriter_1.writeInt32)(writer, 1); // version
|
|
374
461
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
375
462
|
});
|
|
376
|
-
addHandler('lmfx', target => target.effects !== undefined && hasMultiEffects(target.effects), (reader, target, left) => {
|
|
463
|
+
addHandler('lmfx', target => target.effects !== undefined && !isGroupLayer(target) && hasMultiEffects(target.effects), (reader, target, left) => {
|
|
377
464
|
const version = (0, psdReader_1.readUint32)(reader);
|
|
378
465
|
if (version !== 0)
|
|
379
466
|
throw new Error('Invalid lmfx version');
|
|
380
467
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
381
468
|
// console.log('READ', require('util').inspect(desc, false, 99, true));
|
|
382
469
|
// discard if read in 'lrFX' or 'lfx2' section
|
|
383
|
-
target.effects = (0, descriptor_1.parseEffects)(desc,
|
|
470
|
+
target.effects = (0, descriptor_1.parseEffects)(desc, reader);
|
|
384
471
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
385
|
-
}, (writer, target
|
|
386
|
-
const desc = (0, descriptor_1.serializeEffects)(target.effects,
|
|
472
|
+
}, (writer, target) => {
|
|
473
|
+
const desc = (0, descriptor_1.serializeEffects)(target.effects, writer, true);
|
|
387
474
|
// console.log('WRITE', require('util').inspect(desc, false, 99, true));
|
|
388
475
|
(0, psdWriter_1.writeUint32)(writer, 0); // version
|
|
389
476
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
@@ -449,8 +536,12 @@ addHandler('lyid', target => target.id !== undefined || layerNeedsId(target), (r
|
|
|
449
536
|
let id;
|
|
450
537
|
if (target.id !== undefined) {
|
|
451
538
|
id = target.id;
|
|
452
|
-
|
|
453
|
-
|
|
539
|
+
if (options.layerIds.has(id)) {
|
|
540
|
+
// make sure we don't have duplicate layer ids (and don't take id explicitly set on another layer)
|
|
541
|
+
const explicitIds = getExplicitLayerIds(psd, options);
|
|
542
|
+
while (options.layerIds.has(id) || explicitIds.has(id))
|
|
543
|
+
id += 100;
|
|
544
|
+
}
|
|
454
545
|
}
|
|
455
546
|
else {
|
|
456
547
|
// generate id for layers that don't have it, if it's referenced by other sections
|
|
@@ -514,6 +605,58 @@ addHandler('lmgm', hasKey('layerMaskAsGlobalMask'), (reader, target) => {
|
|
|
514
605
|
(0, psdWriter_1.writeUint8)(writer, target.layerMaskAsGlobalMask ? 1 : 0);
|
|
515
606
|
(0, psdWriter_1.writeZeros)(writer, 3);
|
|
516
607
|
});
|
|
608
|
+
addHandler('vmgm', hasKey('vectorMaskAsGlobalMask'), (reader, target) => {
|
|
609
|
+
target.vectorMaskAsGlobalMask = !!(0, psdReader_1.readUint8)(reader);
|
|
610
|
+
(0, psdReader_1.skipBytes)(reader, 3);
|
|
611
|
+
}, (writer, target) => {
|
|
612
|
+
(0, psdWriter_1.writeUint8)(writer, target.vectorMaskAsGlobalMask ? 1 : 0);
|
|
613
|
+
(0, psdWriter_1.writeZeros)(writer, 3);
|
|
614
|
+
});
|
|
615
|
+
addHandler('ffxi', hasKey('foreignEffectId'), (reader, target) => {
|
|
616
|
+
target.foreignEffectId = (0, psdReader_1.readInt32)(reader);
|
|
617
|
+
}, (writer, target) => {
|
|
618
|
+
(0, psdWriter_1.writeInt32)(writer, target.foreignEffectId);
|
|
619
|
+
});
|
|
620
|
+
addHandler('shpa', hasKey('patternData'), (reader, target, left) => {
|
|
621
|
+
if ((0, psdReader_1.readInt32)(reader) !== 0)
|
|
622
|
+
throw new Error(`Invalid shpa version`);
|
|
623
|
+
const count = (0, psdReader_1.readInt32)(reader);
|
|
624
|
+
target.patternData = [];
|
|
625
|
+
for (let i = 0; i < count && left() > 0; i++) {
|
|
626
|
+
const signature = (0, psdReader_1.readSignature)(reader);
|
|
627
|
+
const key = (0, psdReader_1.readSignature)(reader);
|
|
628
|
+
const patternsCount = (0, psdReader_1.readInt32)(reader);
|
|
629
|
+
const copyOnSheetDuplication = !!(0, psdReader_1.readUint8)(reader);
|
|
630
|
+
(0, psdReader_1.skipBytes)(reader, 3);
|
|
631
|
+
const patterns = [];
|
|
632
|
+
for (let j = 0; j < patternsCount && left() > 0; j++) {
|
|
633
|
+
const colorHandling = descriptor_1.patternColorHandling.decode('.' + (0, psdReader_1.readSignature)(reader));
|
|
634
|
+
(0, psdReader_1.readPascalString)(reader, 1); // name
|
|
635
|
+
const name = (0, psdReader_1.readUnicodeString)(reader);
|
|
636
|
+
const id = (0, psdReader_1.readPascalString)(reader, 1);
|
|
637
|
+
patterns.push({ colorHandling, name, id });
|
|
638
|
+
}
|
|
639
|
+
target.patternData.push({ signature, key, copyOnSheetDuplication, patterns });
|
|
640
|
+
}
|
|
641
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
642
|
+
}, (writer, target) => {
|
|
643
|
+
const sets = target.patternData;
|
|
644
|
+
(0, psdWriter_1.writeInt32)(writer, 0); // version
|
|
645
|
+
(0, psdWriter_1.writeInt32)(writer, sets.length);
|
|
646
|
+
for (const set of sets) {
|
|
647
|
+
(0, psdWriter_1.writeSignature)(writer, set.signature);
|
|
648
|
+
(0, psdWriter_1.writeSignature)(writer, set.key);
|
|
649
|
+
(0, psdWriter_1.writeInt32)(writer, set.patterns.length);
|
|
650
|
+
(0, psdWriter_1.writeUint8)(writer, set.copyOnSheetDuplication ? 1 : 0);
|
|
651
|
+
(0, psdWriter_1.writeZeros)(writer, 3);
|
|
652
|
+
for (const pattern of set.patterns) {
|
|
653
|
+
(0, psdWriter_1.writeSignature)(writer, descriptor_1.patternColorHandling.encode(pattern.colorHandling).split('.')[1]);
|
|
654
|
+
(0, psdWriter_1.writePascalString)(writer, pattern.name.replace(/[^\x20-\x7e]/g, '?'), 1);
|
|
655
|
+
(0, psdWriter_1.writeUnicodeString)(writer, pattern.name);
|
|
656
|
+
(0, psdWriter_1.writePascalString)(writer, pattern.id, 1);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
});
|
|
517
660
|
addHandler('lspf', hasKey('protected'), (reader, target) => {
|
|
518
661
|
const flags = (0, psdReader_1.readUint32)(reader);
|
|
519
662
|
target.protected = {
|
|
@@ -523,12 +666,15 @@ addHandler('lspf', hasKey('protected'), (reader, target) => {
|
|
|
523
666
|
};
|
|
524
667
|
if (flags & 0x08)
|
|
525
668
|
target.protected.artboards = true;
|
|
669
|
+
if (flags & 0x80000000)
|
|
670
|
+
target.protected.all = true;
|
|
526
671
|
}, (writer, target) => {
|
|
527
672
|
const flags = (target.protected.transparency ? 0x01 : 0) |
|
|
528
673
|
(target.protected.composite ? 0x02 : 0) |
|
|
529
674
|
(target.protected.position ? 0x04 : 0) |
|
|
530
|
-
(target.protected.artboards ? 0x08 : 0)
|
|
531
|
-
|
|
675
|
+
(target.protected.artboards ? 0x08 : 0) |
|
|
676
|
+
(target.protected.all ? 0x80000000 : 0);
|
|
677
|
+
(0, psdWriter_1.writeUint32)(writer, flags >>> 0);
|
|
532
678
|
});
|
|
533
679
|
addHandler('lclr', hasKey('layerColor'), (reader, target) => {
|
|
534
680
|
const color = (0, psdReader_1.readUint16)(reader);
|
|
@@ -539,106 +685,160 @@ addHandler('lclr', hasKey('layerColor'), (reader, target) => {
|
|
|
539
685
|
(0, psdWriter_1.writeUint16)(writer, index === -1 ? 0 : index);
|
|
540
686
|
(0, psdWriter_1.writeZeros)(writer, 6);
|
|
541
687
|
});
|
|
688
|
+
function parseGeneratorSettings(settings) {
|
|
689
|
+
const result = {};
|
|
690
|
+
if (settings.exportAs) {
|
|
691
|
+
result.exportAs = {};
|
|
692
|
+
if (settings.exportAs.exportOption !== undefined)
|
|
693
|
+
result.exportAs.exportOption = settings.exportAs.exportOption;
|
|
694
|
+
if (settings.exportAs.scaleSettings !== undefined)
|
|
695
|
+
result.exportAs.scaleSettings = settings.exportAs.scaleSettings;
|
|
696
|
+
}
|
|
697
|
+
if (settings.generator_45_assets)
|
|
698
|
+
result.assets = settings.generator_45_assets.json;
|
|
699
|
+
if (settings.layerTime !== undefined)
|
|
700
|
+
result.layerTime = settings.layerTime;
|
|
701
|
+
if (settings.crema)
|
|
702
|
+
result.crema = settings.crema.json;
|
|
703
|
+
return result;
|
|
704
|
+
}
|
|
705
|
+
function serializeGeneratorSettings(generatorSettings) {
|
|
706
|
+
const settings = {
|
|
707
|
+
_name: '',
|
|
708
|
+
_classID: generatorSettings.assets !== undefined ? 'generatorSettings' : 'null',
|
|
709
|
+
};
|
|
710
|
+
if (generatorSettings.exportAs) {
|
|
711
|
+
settings.exportAs = { _name: '', _classID: 'null' };
|
|
712
|
+
if (generatorSettings.exportAs.exportOption !== undefined)
|
|
713
|
+
settings.exportAs.exportOption = generatorSettings.exportAs.exportOption;
|
|
714
|
+
if (generatorSettings.exportAs.scaleSettings !== undefined)
|
|
715
|
+
settings.exportAs.scaleSettings = generatorSettings.exportAs.scaleSettings;
|
|
716
|
+
}
|
|
717
|
+
if (generatorSettings.assets !== undefined)
|
|
718
|
+
settings.generator_45_assets = { _name: '', _classID: 'generatorSettings', json: generatorSettings.assets };
|
|
719
|
+
if (generatorSettings.layerTime !== undefined)
|
|
720
|
+
settings.layerTime = generatorSettings.layerTime;
|
|
721
|
+
if (generatorSettings.crema !== undefined)
|
|
722
|
+
settings.crema = { _name: '', _classID: 'null', json: generatorSettings.crema };
|
|
723
|
+
return { generatorSettings: settings };
|
|
724
|
+
}
|
|
725
|
+
// document (Psd object) stores generator settings in 'extn' section instead of 'shmd' section
|
|
726
|
+
function isDocument(target) {
|
|
727
|
+
return target.width !== undefined;
|
|
728
|
+
}
|
|
542
729
|
addHandler('shmd', // Metadata setting
|
|
543
730
|
// Metadata setting
|
|
544
|
-
target => target.timestamp !== undefined || target.animationFrames !== undefined || target.animationFrameFlags !== undefined || target.timeline !== undefined || target.comps !== undefined
|
|
731
|
+
target => target.timestamp !== undefined || target.animationFrames !== undefined || target.animationFrameFlags !== undefined || target.timeline !== undefined || target.comps !== undefined ||
|
|
732
|
+
(target.generatorSettings !== undefined && !isDocument(target)), (reader, target, left) => {
|
|
545
733
|
const count = (0, psdReader_1.readUint32)(reader);
|
|
546
734
|
for (let i = 0; i < count; i++) {
|
|
547
|
-
(0, psdReader_1.
|
|
735
|
+
const signature = (0, psdReader_1.readSignature)(reader);
|
|
736
|
+
if (signature !== '8BIM' && signature !== '8ELE')
|
|
737
|
+
throw new Error(`Invalid shmd signature: '${signature}'`); // 8ELE in Photoshop Elements
|
|
548
738
|
const key = (0, psdReader_1.readSignature)(reader);
|
|
549
739
|
(0, psdReader_1.readUint8)(reader); // copy
|
|
550
740
|
(0, psdReader_1.skipBytes)(reader, 3);
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
target.
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
560
|
-
// console.log('mlst', target.name, require('util').inspect(desc, false, 99, true));
|
|
561
|
-
target.animationFrames = [];
|
|
562
|
-
for (let i = 0; i < desc.LaSt.length; i++) {
|
|
563
|
-
const f = desc.LaSt[i];
|
|
564
|
-
const frame = { frames: f.FrLs };
|
|
565
|
-
if (f.enab !== undefined)
|
|
566
|
-
frame.enable = f.enab;
|
|
567
|
-
if (f.Ofst)
|
|
568
|
-
frame.offset = (0, descriptor_1.horzVrtcToXY)(f.Ofst);
|
|
569
|
-
if (f.FXRf)
|
|
570
|
-
frame.referencePoint = (0, descriptor_1.horzVrtcToXY)(f.FXRf);
|
|
571
|
-
if (f.Lefx)
|
|
572
|
-
frame.effects = (0, descriptor_1.parseEffects)(f.Lefx, !!reader.logMissingFeatures);
|
|
573
|
-
if (f.blendOptions && f.blendOptions.Opct)
|
|
574
|
-
frame.opacity = (0, descriptor_1.parsePercent)(f.blendOptions.Opct);
|
|
575
|
-
target.animationFrames.push(frame);
|
|
741
|
+
const end = reader.offset + 4 + reader.view.getUint32(reader.offset);
|
|
742
|
+
try {
|
|
743
|
+
(0, psdReader_1.readSection)(reader, 1, left => {
|
|
744
|
+
if (key === 'cust') {
|
|
745
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
746
|
+
// console.log('cust', target.name, require('util').inspect(desc, false, 99, true));
|
|
747
|
+
if (desc.layerTime !== undefined)
|
|
748
|
+
target.timestamp = desc.layerTime;
|
|
576
749
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
duration: (0, descriptor_1.frac)(timeScope.duration),
|
|
597
|
-
inTime: (0, descriptor_1.frac)(timeScope.inTime),
|
|
598
|
-
outTime: (0, descriptor_1.frac)(timeScope.outTime),
|
|
599
|
-
autoScope: desc.autoScope,
|
|
600
|
-
audioLevel: desc.audioLevel,
|
|
601
|
-
};
|
|
602
|
-
if (desc.trackList) {
|
|
603
|
-
timeline.tracks = (0, descriptor_1.parseTrackList)(desc.trackList, !!reader.logMissingFeatures);
|
|
750
|
+
else if (key === 'mlst') {
|
|
751
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
752
|
+
// console.log('mlst', target.name, require('util').inspect(desc, false, 99, true));
|
|
753
|
+
target.animationFrames = [];
|
|
754
|
+
for (let i = 0; i < desc.LaSt.length; i++) {
|
|
755
|
+
const f = desc.LaSt[i];
|
|
756
|
+
const frame = { frames: f.FrLs };
|
|
757
|
+
if (f.enab !== undefined)
|
|
758
|
+
frame.enable = f.enab;
|
|
759
|
+
if (f.Ofst)
|
|
760
|
+
frame.offset = (0, descriptor_1.horzVrtcToXY)(f.Ofst);
|
|
761
|
+
if (f.FXRf)
|
|
762
|
+
frame.referencePoint = (0, descriptor_1.horzVrtcToXY)(f.FXRf);
|
|
763
|
+
if (f.Lefx)
|
|
764
|
+
frame.effects = (0, descriptor_1.parseEffects)(f.Lefx, reader);
|
|
765
|
+
if (f.blendOptions && f.blendOptions.Opct)
|
|
766
|
+
frame.opacity = (0, descriptor_1.parsePercent)(f.blendOptions.Opct);
|
|
767
|
+
target.animationFrames.push(frame);
|
|
768
|
+
}
|
|
604
769
|
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
for (const item of desc.layerSettings) {
|
|
617
|
-
target.comps.settings.push({ compList: item.compList });
|
|
618
|
-
const t = target.comps.settings[target.comps.settings.length - 1];
|
|
619
|
-
if ('enab' in item)
|
|
620
|
-
t.enabled = item.enab;
|
|
621
|
-
if (item.Ofst)
|
|
622
|
-
t.offset = { x: item.Ofst.Hrzn, y: item.Ofst.Vrtc };
|
|
623
|
-
if (item.FXRefPoint)
|
|
624
|
-
t.effectsReferencePoint = { x: item.FXRefPoint.Hrzn, y: item.FXRefPoint.Vrtc };
|
|
770
|
+
else if (key === 'mdyn') {
|
|
771
|
+
// frame flags
|
|
772
|
+
(0, psdReader_1.readUint16)(reader); // unknown
|
|
773
|
+
const propagate = (0, psdReader_1.readUint8)(reader);
|
|
774
|
+
const flags = (0, psdReader_1.readUint8)(reader);
|
|
775
|
+
target.animationFrameFlags = {
|
|
776
|
+
propagateFrameOne: !propagate,
|
|
777
|
+
unifyLayerPosition: (flags & 1) !== 0,
|
|
778
|
+
unifyLayerStyle: (flags & 2) !== 0,
|
|
779
|
+
unifyLayerVisibility: (flags & 4) !== 0,
|
|
780
|
+
};
|
|
625
781
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
782
|
+
else if (key === 'tmln') {
|
|
783
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
784
|
+
const timeScope = desc.timeScope;
|
|
785
|
+
// console.log('tmln', target.name, target.id, require('util').inspect(desc, false, 99, true));
|
|
786
|
+
const timeline = {
|
|
787
|
+
start: (0, descriptor_1.frac)(timeScope.Strt),
|
|
788
|
+
duration: (0, descriptor_1.frac)(timeScope.duration),
|
|
789
|
+
inTime: (0, descriptor_1.frac)(timeScope.inTime),
|
|
790
|
+
outTime: (0, descriptor_1.frac)(timeScope.outTime),
|
|
791
|
+
autoScope: desc.autoScope,
|
|
792
|
+
audioLevel: desc.audioLevel,
|
|
793
|
+
};
|
|
794
|
+
if (desc.trackList) {
|
|
795
|
+
timeline.tracks = (0, descriptor_1.parseTrackList)(desc.trackList, reader);
|
|
796
|
+
}
|
|
797
|
+
target.timeline = timeline;
|
|
798
|
+
// console.log('tmln:result', target.name, target.id, require('util').inspect(timeline, false, 99, true));
|
|
799
|
+
}
|
|
800
|
+
else if (key === 'cmls') {
|
|
801
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
802
|
+
// console.log('cmls', require('util').inspect(desc, false, 99, true));
|
|
803
|
+
target.comps = {
|
|
804
|
+
settings: [],
|
|
805
|
+
};
|
|
806
|
+
if (desc.origFXRefPoint)
|
|
807
|
+
target.comps.originalEffectsReferencePoint = { x: desc.origFXRefPoint.Hrzn, y: desc.origFXRefPoint.Vrtc };
|
|
808
|
+
for (const item of desc.layerSettings) {
|
|
809
|
+
target.comps.settings.push({ compList: item.compList });
|
|
810
|
+
const t = target.comps.settings[target.comps.settings.length - 1];
|
|
811
|
+
if ('enab' in item)
|
|
812
|
+
t.enabled = item.enab;
|
|
813
|
+
if (item.Ofst)
|
|
814
|
+
t.offset = { x: item.Ofst.Hrzn, y: item.Ofst.Vrtc };
|
|
815
|
+
if (item.FXRefPoint)
|
|
816
|
+
t.effectsReferencePoint = { x: item.FXRefPoint.Hrzn, y: item.FXRefPoint.Vrtc };
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
else if (key === 'extn') {
|
|
820
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
821
|
+
if (desc.generatorSettings)
|
|
822
|
+
target.generatorSettings = parseGeneratorSettings(desc.generatorSettings);
|
|
823
|
+
}
|
|
824
|
+
else {
|
|
825
|
+
reader.logMissingFeatures && reader.log('Unhandled "shmd" section key', key);
|
|
826
|
+
}
|
|
827
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
catch (e) {
|
|
831
|
+
// failure to read one item shouldn't drop all other items
|
|
832
|
+
if (reader.throwForMissingFeatures)
|
|
833
|
+
throw e;
|
|
834
|
+
reader.logMissingFeatures && reader.log(`Failed to read "shmd" section key ${key}: ${e.message}`);
|
|
835
|
+
reader.offset = end;
|
|
836
|
+
}
|
|
638
837
|
}
|
|
639
838
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
640
839
|
}, (writer, target, _, options) => {
|
|
641
840
|
const { animationFrames, animationFrameFlags, timestamp, timeline, comps } = target;
|
|
841
|
+
const generatorSettings = isDocument(target) ? undefined : target.generatorSettings;
|
|
642
842
|
let count = 0;
|
|
643
843
|
if (animationFrames)
|
|
644
844
|
count++;
|
|
@@ -650,6 +850,8 @@ target => target.timestamp !== undefined || target.animationFrames !== undefined
|
|
|
650
850
|
count++;
|
|
651
851
|
if (comps)
|
|
652
852
|
count++;
|
|
853
|
+
if (generatorSettings)
|
|
854
|
+
count++;
|
|
653
855
|
(0, psdWriter_1.writeUint32)(writer, count);
|
|
654
856
|
if (animationFrames) {
|
|
655
857
|
(0, psdWriter_1.writeSignature)(writer, '8BIM');
|
|
@@ -672,9 +874,9 @@ target => target.timestamp !== undefined || target.animationFrames !== undefined
|
|
|
672
874
|
if (f.referencePoint)
|
|
673
875
|
frame.FXRf = (0, descriptor_1.xyToHorzVrtc)(f.referencePoint);
|
|
674
876
|
if (f.effects)
|
|
675
|
-
frame.Lefx = (0, descriptor_1.serializeEffects)(f.effects,
|
|
877
|
+
frame.Lefx = (0, descriptor_1.serializeEffects)(f.effects, writer, hasMultiEffects(f.effects));
|
|
676
878
|
if (f.opacity !== undefined)
|
|
677
|
-
frame.blendOptions = { Opct: (0, descriptor_1.
|
|
879
|
+
frame.blendOptions = { Opct: (0, descriptor_1.unitsPercentF)(f.opacity) };
|
|
678
880
|
desc.LaSt.push(frame);
|
|
679
881
|
}
|
|
680
882
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
@@ -712,7 +914,7 @@ target => target.timestamp !== undefined || target.animationFrames !== undefined
|
|
|
712
914
|
audioLevel: timeline.audioLevel,
|
|
713
915
|
};
|
|
714
916
|
if (timeline.tracks) {
|
|
715
|
-
desc.trackList = (0, descriptor_1.serializeTrackList)(timeline.tracks);
|
|
917
|
+
desc.trackList = (0, descriptor_1.serializeTrackList)(timeline.tracks, writer);
|
|
716
918
|
}
|
|
717
919
|
desc.LyrI = getLayerId(target, options);
|
|
718
920
|
// console.log('WRITE:tmln', target.name, target.id, require('util').inspect(desc, false, 99, true));
|
|
@@ -758,6 +960,15 @@ target => target.timestamp !== undefined || target.animationFrames !== undefined
|
|
|
758
960
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
759
961
|
}, true);
|
|
760
962
|
}
|
|
963
|
+
if (generatorSettings) {
|
|
964
|
+
(0, psdWriter_1.writeSignature)(writer, '8BIM');
|
|
965
|
+
(0, psdWriter_1.writeSignature)(writer, 'extn');
|
|
966
|
+
(0, psdWriter_1.writeUint8)(writer, 0); // copy (always false)
|
|
967
|
+
(0, psdWriter_1.writeZeros)(writer, 3);
|
|
968
|
+
(0, psdWriter_1.writeSection)(writer, 2, () => {
|
|
969
|
+
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', serializeGeneratorSettings(generatorSettings));
|
|
970
|
+
}, true);
|
|
971
|
+
}
|
|
761
972
|
});
|
|
762
973
|
addHandler('PxSc', hasKey('pixelSource'), (reader, target) => {
|
|
763
974
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader, true);
|
|
@@ -837,7 +1048,7 @@ addHandler('vstk', hasKey('vectorStroke'), (reader, target, left) => {
|
|
|
837
1048
|
lineAlignment: descriptor_1.strokeStyleLineAlignment.decode(desc.strokeStyleLineAlignment),
|
|
838
1049
|
scaleLock: desc.strokeStyleScaleLock,
|
|
839
1050
|
strokeAdjust: desc.strokeStyleStrokeAdjust,
|
|
840
|
-
lineDashSet: desc.strokeStyleLineDashSet.map(descriptor_1.parseUnits),
|
|
1051
|
+
lineDashSet: (desc.strokeStyleLineDashSet || []).map(descriptor_1.parseUnits),
|
|
841
1052
|
blendMode: descriptor_1.BlnM.decode(desc.strokeStyleBlendMode),
|
|
842
1053
|
opacity: (0, descriptor_1.parsePercent)(desc.strokeStyleOpacity),
|
|
843
1054
|
content: (0, descriptor_1.parseVectorContent)(desc.strokeStyleContent),
|
|
@@ -875,9 +1086,11 @@ hasKey('artboard'), (reader, target, left) => {
|
|
|
875
1086
|
rect: { top: rect['Top '], left: rect.Left, bottom: rect.Btom, right: rect.Rght },
|
|
876
1087
|
guideIndices: desc.guideIndeces,
|
|
877
1088
|
presetName: desc.artboardPresetName,
|
|
878
|
-
color: (0, descriptor_1.parseColor)(desc['Clr ']),
|
|
879
|
-
backgroundType: desc.artboardBackgroundType,
|
|
880
1089
|
};
|
|
1090
|
+
if (desc['Clr '])
|
|
1091
|
+
target.artboard.color = (0, descriptor_1.parseColor)(desc['Clr ']);
|
|
1092
|
+
if (desc.artboardBackgroundType !== undefined)
|
|
1093
|
+
target.artboard.backgroundType = desc.artboardBackgroundType;
|
|
881
1094
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
882
1095
|
}, (writer, target) => {
|
|
883
1096
|
var _a;
|
|
@@ -983,14 +1196,15 @@ function encodeWarp(warp) {
|
|
|
983
1196
|
}
|
|
984
1197
|
return desc;
|
|
985
1198
|
}
|
|
986
|
-
addHandler('PlLd',
|
|
1199
|
+
addHandler('PlLd', target => !!target.placedLayer && !target.placedLayer.external, // linked smart objects are stored in SoLE
|
|
1200
|
+
(reader, target, left) => {
|
|
987
1201
|
if ((0, psdReader_1.readSignature)(reader) !== 'plcL')
|
|
988
1202
|
throw new Error(`Invalid PlLd signature`);
|
|
989
1203
|
if ((0, psdReader_1.readInt32)(reader) !== 3)
|
|
990
1204
|
throw new Error(`Invalid PlLd version`);
|
|
991
1205
|
const id = (0, psdReader_1.readPascalString)(reader, 1);
|
|
992
1206
|
const pageNumber = (0, psdReader_1.readInt32)(reader);
|
|
993
|
-
const totalPages = (0, psdReader_1.readInt32)(reader); //
|
|
1207
|
+
const totalPages = (0, psdReader_1.readInt32)(reader); // for multi-page documents (PDF)
|
|
994
1208
|
(0, psdReader_1.readInt32)(reader); // anitAliasPolicy 16
|
|
995
1209
|
const placedLayerType = (0, psdReader_1.readInt32)(reader); // 0 = unknown, 1 = vector, 2 = raster, 3 = image stack
|
|
996
1210
|
if (!placedLayerTypes[placedLayerType])
|
|
@@ -1035,6 +1249,8 @@ addHandler('PlLd', hasKey('placedLayer'), (reader, target, left) => {
|
|
|
1035
1249
|
const type = isQuilt ? 'quiltWarp' : 'warp';
|
|
1036
1250
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', type, encodeWarp(warp), type);
|
|
1037
1251
|
});
|
|
1252
|
+
const levelsFilterKeys = ['_name', '_classID', 'presetKind', 'Adjs'];
|
|
1253
|
+
const levelsFilterAdjustmentKeys = ['_name', '_classID', 'Chnl', 'Inpt', 'Otpt', 'Gmm '];
|
|
1038
1254
|
function uint8ToFloat32(array) {
|
|
1039
1255
|
const length = Math.floor(array.byteLength / 4);
|
|
1040
1256
|
return new Float32Array(array.buffer.slice(array.byteOffset, array.byteOffset + length * 4), 0, length);
|
|
@@ -1077,7 +1293,87 @@ function pointToHrznVrtc(point) {
|
|
|
1077
1293
|
Vrtc: (0, descriptor_1.unitsValue)(point.y, 'y'),
|
|
1078
1294
|
};
|
|
1079
1295
|
}
|
|
1080
|
-
|
|
1296
|
+
// Camera Raw Filter setting paths (in CameraRawFilterSettings) and their descriptor keys
|
|
1297
|
+
const cameraRawColorKeys = [
|
|
1298
|
+
['red', 'R'], ['orange', 'O'], ['yellow', 'Y'], ['green', 'G'], ['aqua', 'A'], ['blue', 'B'], ['purple', 'P'], ['magenta', 'M'],
|
|
1299
|
+
];
|
|
1300
|
+
const cameraRawSettings = [
|
|
1301
|
+
['version', 'CrVe'], ['processVersion', 'PrVN'], ['processVersionCode', 'PrVe'], ['whiteBalance', 'WBal'],
|
|
1302
|
+
['temperature', 'Temp'], ['tint', 'Tint'], ['exposure', 'Ex12'], ['contrast', 'Cr12'], ['highlights', 'Hi12'],
|
|
1303
|
+
['shadows', 'Sh12'], ['whites', 'Wh12'], ['blacks', 'Bk12'], ['texture', 'CrTx'], ['clarity', 'Cl12'],
|
|
1304
|
+
['dehaze', 'Dhze'], ['vibrance', 'Vibr'], ['saturation', 'Strt'],
|
|
1305
|
+
['parametricCurve.shadows', 'PC_S'], ['parametricCurve.darks', 'PC_D'], ['parametricCurve.lights', 'PC_L'],
|
|
1306
|
+
['parametricCurve.highlights', 'PC_H'], ['parametricCurve.shadowSplit', 'PC_1'], ['parametricCurve.midtoneSplit', 'PC_2'],
|
|
1307
|
+
['parametricCurve.highlightSplit', 'PC_3'],
|
|
1308
|
+
['pointCurve.composite', 'Crv '], ['pointCurve.red', 'CrvR'], ['pointCurve.green', 'CrvG'], ['pointCurve.blue', 'CrvB'],
|
|
1309
|
+
...cameraRawColorKeys.map(([name, key]) => [`hsl.hue.${name}`, `HA_${key}`]),
|
|
1310
|
+
...cameraRawColorKeys.map(([name, key]) => [`hsl.saturation.${name}`, `SA_${key}`]),
|
|
1311
|
+
...cameraRawColorKeys.map(([name, key]) => [`hsl.luminance.${name}`, `LA_${key}`]),
|
|
1312
|
+
['colorGrading.shadows.hue', 'STSH'], ['colorGrading.shadows.saturation', 'STSS'], ['colorGrading.shadows.luminance', 'CgSL'],
|
|
1313
|
+
['colorGrading.midtones.hue', 'CgMH'], ['colorGrading.midtones.saturation', 'CgMS'], ['colorGrading.midtones.luminance', 'CgML'],
|
|
1314
|
+
['colorGrading.highlights.hue', 'STHH'], ['colorGrading.highlights.saturation', 'STHS'], ['colorGrading.highlights.luminance', 'CgHL'],
|
|
1315
|
+
['colorGrading.global.hue', 'CgGH'], ['colorGrading.global.saturation', 'CgGS'], ['colorGrading.global.luminance', 'CgGL'],
|
|
1316
|
+
['colorGrading.blending', 'CgBl'], ['colorGrading.balance', 'STB '],
|
|
1317
|
+
['sharpening.amount', 'Shrp'], ['sharpening.radius', 'ShpR'], ['sharpening.detail', 'ShpD'], ['sharpening.masking', 'ShpM'],
|
|
1318
|
+
['noiseReduction.luminance', 'LNR '], ['noiseReduction.luminanceDetail', 'LNRD'], ['noiseReduction.luminanceContrast', 'LNRC'],
|
|
1319
|
+
['noiseReduction.color', 'CNR '], ['noiseReduction.colorDetail', 'CNRD'], ['noiseReduction.colorSmoothness', 'CNRS'],
|
|
1320
|
+
['grain.amount', 'GRNA'], ['grain.size', 'GRNS'], ['grain.roughness', 'GRNF'],
|
|
1321
|
+
['postCropVignette.amount', 'PCVA'], ['postCropVignette.midpoint', 'PCVM'], ['postCropVignette.feather', 'PCVF'],
|
|
1322
|
+
['postCropVignette.roundness', 'PCVR'],
|
|
1323
|
+
];
|
|
1324
|
+
const cameraRawCurveKeys = ['Crv ', 'CrvR', 'CrvG', 'CrvB'];
|
|
1325
|
+
const cameraRawFilterID = 2783;
|
|
1326
|
+
function parseCameraRawSettings(desc, reader) {
|
|
1327
|
+
var _a;
|
|
1328
|
+
const settings = {};
|
|
1329
|
+
for (const [path, key] of cameraRawSettings) {
|
|
1330
|
+
let value = desc[key];
|
|
1331
|
+
if (value === undefined)
|
|
1332
|
+
continue;
|
|
1333
|
+
if (key === 'WBal') {
|
|
1334
|
+
value = value.split('.')[1];
|
|
1335
|
+
}
|
|
1336
|
+
else if (cameraRawCurveKeys.includes(key)) {
|
|
1337
|
+
const values = value;
|
|
1338
|
+
value = [];
|
|
1339
|
+
for (let i = 0; i + 1 < values.length; i += 2)
|
|
1340
|
+
value.push({ input: values[i], output: values[i + 1] });
|
|
1341
|
+
}
|
|
1342
|
+
const parts = path.split('.');
|
|
1343
|
+
let target = settings;
|
|
1344
|
+
for (let i = 0; i < parts.length - 1; i++)
|
|
1345
|
+
target = target[parts[i]] = (_a = target[parts[i]]) !== null && _a !== void 0 ? _a : {};
|
|
1346
|
+
target[parts[parts.length - 1]] = value;
|
|
1347
|
+
}
|
|
1348
|
+
for (const key of Object.keys(desc)) {
|
|
1349
|
+
if (key !== '_name' && key !== '_classID' && !cameraRawSettings.some(s => s[1] === key)) {
|
|
1350
|
+
reader.logMissingFeatures && reader.log(`Unhandled Camera Raw Filter setting: ${key}`);
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
return settings;
|
|
1354
|
+
}
|
|
1355
|
+
function serializeCameraRawSettings(settings) {
|
|
1356
|
+
const desc = { _name: '', _classID: descriptor_1.cameraRawFilterClassID };
|
|
1357
|
+
for (const [path, key] of cameraRawSettings) {
|
|
1358
|
+
let value = settings;
|
|
1359
|
+
for (const part of path.split('.'))
|
|
1360
|
+
value = value === null || value === void 0 ? void 0 : value[part];
|
|
1361
|
+
if (value === undefined)
|
|
1362
|
+
continue;
|
|
1363
|
+
if (key === 'WBal') {
|
|
1364
|
+
value = `WBal.${value}`;
|
|
1365
|
+
}
|
|
1366
|
+
else if (cameraRawCurveKeys.includes(key)) {
|
|
1367
|
+
value = value.flatMap(p => [Math.round(p.input), Math.round(p.output)]);
|
|
1368
|
+
}
|
|
1369
|
+
else if (typeof value === 'number' && key !== 'Ex12' && key !== 'ShpR') {
|
|
1370
|
+
value = Math.round(value);
|
|
1371
|
+
}
|
|
1372
|
+
desc[key] = value;
|
|
1373
|
+
}
|
|
1374
|
+
return desc;
|
|
1375
|
+
}
|
|
1376
|
+
function parseFilterFXItem(f, reader) {
|
|
1081
1377
|
const base = {
|
|
1082
1378
|
name: f['Nm '],
|
|
1083
1379
|
opacity: (0, descriptor_1.parsePercent)(f.blendOptions.Opct),
|
|
@@ -1087,6 +1383,9 @@ function parseFilterFXItem(f, options) {
|
|
|
1087
1383
|
foregroundColor: (0, descriptor_1.parseColor)(f.FrgC),
|
|
1088
1384
|
backgroundColor: (0, descriptor_1.parseColor)(f.BckC),
|
|
1089
1385
|
};
|
|
1386
|
+
if ('Fltr' in f && f.Fltr._classID === descriptor_1.cameraRawFilterClassID) {
|
|
1387
|
+
return Object.assign(Object.assign({}, base), { type: 'camera raw', filter: parseCameraRawSettings(f.Fltr, reader) });
|
|
1388
|
+
}
|
|
1090
1389
|
if ('Fltr' in f) {
|
|
1091
1390
|
switch (f.Fltr._classID) {
|
|
1092
1391
|
case 'boxblur': return Object.assign(Object.assign({}, base), { type: 'box blur', filter: {
|
|
@@ -1125,7 +1424,7 @@ function parseFilterFXItem(f, options) {
|
|
|
1125
1424
|
undefinedAreas: descriptor_1.UndA.decode(f.Fltr.UndA),
|
|
1126
1425
|
displacementFile: {
|
|
1127
1426
|
signature: f.Fltr.DspF.sig,
|
|
1128
|
-
path: f.Fltr.DspF.path,
|
|
1427
|
+
path: f.Fltr.DspF.path,
|
|
1129
1428
|
},
|
|
1130
1429
|
} });
|
|
1131
1430
|
case 'Pnch': return Object.assign(Object.assign({}, base), { type: 'pinch', filter: {
|
|
@@ -1312,8 +1611,7 @@ function parseFilterFXItem(f, options) {
|
|
|
1312
1611
|
],
|
|
1313
1612
|
puppetShapeList: (f.Fltr.puppetShapeList || []).map(p => ({
|
|
1314
1613
|
rigidType: p.rigidType,
|
|
1315
|
-
//
|
|
1316
|
-
// TODO: VrsN
|
|
1614
|
+
// VrsM / VrsN - version (always 1.0)
|
|
1317
1615
|
originalVertexArray: uint8ToPoints(p.originalVertexArray),
|
|
1318
1616
|
deformedVertexArray: uint8ToPoints(p.deformedVertexArray),
|
|
1319
1617
|
indexArray: Array.from(uint8ToUint32(p.indexArray)),
|
|
@@ -1410,7 +1708,7 @@ function parseFilterFXItem(f, options) {
|
|
|
1410
1708
|
;
|
|
1411
1709
|
case 'Crvs':
|
|
1412
1710
|
{
|
|
1413
|
-
return Object.assign(Object.assign({}, base), { type: 'curves', filter: Object.assign({ presetKind: descriptor_1.presetKindType.decode(f.Fltr.presetKind) }, (f.Fltr.Adjs ? {
|
|
1711
|
+
return Object.assign(Object.assign({}, base), { type: 'curves', filter: Object.assign(Object.assign({}, (f.Fltr.presetKind !== undefined ? { presetKind: descriptor_1.presetKindType.decode(f.Fltr.presetKind) } : {})), (f.Fltr.Adjs ? {
|
|
1414
1712
|
adjustments: f.Fltr.Adjs.map(a => {
|
|
1415
1713
|
const channels = a.Chnl.map(descriptor_1.Chnl.decode);
|
|
1416
1714
|
if (a['Crv ']) {
|
|
@@ -1434,6 +1732,35 @@ function parseFilterFXItem(f, options) {
|
|
|
1434
1732
|
} : {})) });
|
|
1435
1733
|
}
|
|
1436
1734
|
;
|
|
1735
|
+
case 'Lvls':
|
|
1736
|
+
{
|
|
1737
|
+
const adjustments = f.Fltr.Adjs;
|
|
1738
|
+
const isKnown = (obj, keys) => Object.keys(obj).every(k => keys.indexOf(k) !== -1);
|
|
1739
|
+
// skip filter with settings we don't know about
|
|
1740
|
+
if (!isKnown(f.Fltr, levelsFilterKeys) || (adjustments && !adjustments.every(a => isKnown(a, levelsFilterAdjustmentKeys)))) {
|
|
1741
|
+
if (reader.throwForMissingFeatures)
|
|
1742
|
+
throw new Error('Unknown levels filter settings');
|
|
1743
|
+
reader.logMissingFeatures && reader.log(`Skipped levels smart filter with unknown settings`);
|
|
1744
|
+
return undefined;
|
|
1745
|
+
}
|
|
1746
|
+
return Object.assign(Object.assign({}, base), { type: 'levels', filter: Object.assign(Object.assign({}, (f.Fltr.presetKind !== undefined ? { presetKind: descriptor_1.presetKindType.decode(f.Fltr.presetKind) } : {})), (adjustments ? {
|
|
1747
|
+
adjustments: adjustments.map(a => {
|
|
1748
|
+
const result = { channels: a.Chnl.map(descriptor_1.Chnl.decode) };
|
|
1749
|
+
if (a.Inpt) {
|
|
1750
|
+
result.shadowInput = a.Inpt[0];
|
|
1751
|
+
result.highlightInput = a.Inpt[1];
|
|
1752
|
+
}
|
|
1753
|
+
if (a.Otpt) {
|
|
1754
|
+
result.shadowOutput = a.Otpt[0];
|
|
1755
|
+
result.highlightOutput = a.Otpt[1];
|
|
1756
|
+
}
|
|
1757
|
+
if (a['Gmm '] !== undefined)
|
|
1758
|
+
result.midtoneInput = a['Gmm '];
|
|
1759
|
+
return result;
|
|
1760
|
+
}),
|
|
1761
|
+
} : {})) });
|
|
1762
|
+
}
|
|
1763
|
+
;
|
|
1437
1764
|
case 'BrgC':
|
|
1438
1765
|
{
|
|
1439
1766
|
return Object.assign(Object.assign({}, base), { type: 'brightness/contrast', filter: {
|
|
@@ -1444,10 +1771,11 @@ function parseFilterFXItem(f, options) {
|
|
|
1444
1771
|
}
|
|
1445
1772
|
;
|
|
1446
1773
|
default:
|
|
1447
|
-
if (
|
|
1774
|
+
if (reader.throwForMissingFeatures) {
|
|
1448
1775
|
// console.log('FILTER', require('util').inspect(f, false, 99, true));
|
|
1449
1776
|
throw new Error(`Unknown filter classId: ${f.Fltr._classID}`);
|
|
1450
1777
|
}
|
|
1778
|
+
reader.logMissingFeatures && reader.log(`Unhandled smart filter: ${f.Fltr._classID} (${f['Nm ']})`);
|
|
1451
1779
|
return undefined;
|
|
1452
1780
|
}
|
|
1453
1781
|
}
|
|
@@ -1467,21 +1795,23 @@ function parseFilterFXItem(f, options) {
|
|
|
1467
1795
|
case 1314149187: return Object.assign(Object.assign({}, base), { type: 'ntsc colors' });
|
|
1468
1796
|
case 1231976050: return Object.assign(Object.assign({}, base), { type: 'invert' });
|
|
1469
1797
|
default:
|
|
1470
|
-
if (
|
|
1798
|
+
if (reader.throwForMissingFeatures) {
|
|
1471
1799
|
// console.log('FILTER', require('util').inspect(f, false, 99, true));
|
|
1472
1800
|
throw new Error(`Unknown filterID: ${f.filterID}`);
|
|
1473
1801
|
}
|
|
1802
|
+
reader.logMissingFeatures && reader.log(`Unhandled smart filter: ${f.filterID} (${f['Nm ']})`);
|
|
1803
|
+
return undefined;
|
|
1474
1804
|
}
|
|
1475
1805
|
}
|
|
1476
1806
|
}
|
|
1477
|
-
function parseFilterFX(desc,
|
|
1807
|
+
function parseFilterFX(desc, reader) {
|
|
1478
1808
|
return {
|
|
1479
1809
|
enabled: desc.enab,
|
|
1480
1810
|
validAtPosition: desc.validAtPosition,
|
|
1481
1811
|
maskEnabled: desc.filterMaskEnable,
|
|
1482
1812
|
maskLinked: desc.filterMaskLinked,
|
|
1483
1813
|
maskExtendWithWhite: desc.filterMaskExtendWithWhite,
|
|
1484
|
-
list: desc.filterFXList.map(x => parseFilterFXItem(x,
|
|
1814
|
+
list: desc.filterFXList.map(x => parseFilterFXItem(x, reader)).filter((x) => !!x),
|
|
1485
1815
|
};
|
|
1486
1816
|
}
|
|
1487
1817
|
function uvRadius(t) {
|
|
@@ -1837,14 +2167,14 @@ function serializeFilterFXItem(f) {
|
|
|
1837
2167
|
case 'puppet': return Object.assign(Object.assign({}, base), { Fltr: {
|
|
1838
2168
|
_name: 'Rigid Transform',
|
|
1839
2169
|
_classID: 'rigidTransform',
|
|
1840
|
-
'null': ['Ordn.Trgt'], //
|
|
2170
|
+
'null': ['Ordn.Trgt'], // target layer reference
|
|
1841
2171
|
rigidType: f.filter.rigidType,
|
|
1842
2172
|
puppetShapeList: (f.filter.puppetShapeList || []).map(p => ({
|
|
1843
2173
|
_name: '',
|
|
1844
2174
|
_classID: 'puppetShape',
|
|
1845
2175
|
rigidType: p.rigidType,
|
|
1846
|
-
VrsM: 1, //
|
|
1847
|
-
VrsN: 0, //
|
|
2176
|
+
VrsM: 1, // version major
|
|
2177
|
+
VrsN: 0, // version minor
|
|
1848
2178
|
originalVertexArray: toUint8(new Float32Array(pointsToArray(p.originalVertexArray))),
|
|
1849
2179
|
deformedVertexArray: toUint8(new Float32Array(pointsToArray(p.deformedVertexArray))),
|
|
1850
2180
|
indexArray: toUint8(new Uint32Array(p.indexArray)),
|
|
@@ -1926,7 +2256,7 @@ function serializeFilterFXItem(f) {
|
|
|
1926
2256
|
warpedVertices: f.filter.warpedVertices.map(pointToHrznVrtc),
|
|
1927
2257
|
quads: f.filter.quads.map(indices => ({ _name: '', _classID: 'quadIndices', indices })),
|
|
1928
2258
|
}, filterID: 442 });
|
|
1929
|
-
case 'curves': return Object.assign(Object.assign({}, base), { Fltr: Object.assign({ _name: 'Curves', _classID: 'Crvs', presetKind: descriptor_1.presetKindType.encode(f.filter.presetKind) }, (f.filter.adjustments ? {
|
|
2259
|
+
case 'curves': return Object.assign(Object.assign({}, base), { Fltr: Object.assign(Object.assign({ _name: 'Curves', _classID: 'Crvs' }, (f.filter.presetKind !== undefined ? { presetKind: descriptor_1.presetKindType.encode(f.filter.presetKind) } : {})), (f.filter.adjustments ? {
|
|
1930
2260
|
Adjs: f.filter.adjustments.map(a => 'curve' in a ? {
|
|
1931
2261
|
_name: '',
|
|
1932
2262
|
_classID: 'CrvA',
|
|
@@ -1939,6 +2269,22 @@ function serializeFilterFXItem(f) {
|
|
|
1939
2269
|
Mpng: a.values,
|
|
1940
2270
|
})
|
|
1941
2271
|
} : {})), filterID: 1131574899 });
|
|
2272
|
+
case 'levels': return Object.assign(Object.assign({}, base), { Fltr: Object.assign(Object.assign({ _name: 'Levels', _classID: 'Lvls' }, (f.filter.presetKind !== undefined ? { presetKind: descriptor_1.presetKindType.encode(f.filter.presetKind) } : {})), (f.filter.adjustments ? {
|
|
2273
|
+
Adjs: f.filter.adjustments.map(a => {
|
|
2274
|
+
var _a, _b, _c, _d;
|
|
2275
|
+
const adjustment = { _name: '', _classID: 'LvlA', Chnl: a.channels.map(descriptor_1.Chnl.encode) };
|
|
2276
|
+
if (a.shadowInput !== undefined || a.highlightInput !== undefined) {
|
|
2277
|
+
adjustment.Inpt = [Math.round((_a = a.shadowInput) !== null && _a !== void 0 ? _a : 0), Math.round((_b = a.highlightInput) !== null && _b !== void 0 ? _b : 255)];
|
|
2278
|
+
}
|
|
2279
|
+
if (a.shadowOutput !== undefined || a.highlightOutput !== undefined) {
|
|
2280
|
+
adjustment.Otpt = [Math.round((_c = a.shadowOutput) !== null && _c !== void 0 ? _c : 0), Math.round((_d = a.highlightOutput) !== null && _d !== void 0 ? _d : 255)];
|
|
2281
|
+
}
|
|
2282
|
+
if (a.midtoneInput !== undefined)
|
|
2283
|
+
adjustment['Gmm '] = a.midtoneInput;
|
|
2284
|
+
return adjustment;
|
|
2285
|
+
}),
|
|
2286
|
+
} : {})), filterID: 1282829427 });
|
|
2287
|
+
case 'camera raw': return Object.assign(Object.assign({}, base), { Fltr: serializeCameraRawSettings(f.filter), filterID: cameraRawFilterID });
|
|
1942
2288
|
case 'brightness/contrast': return Object.assign(Object.assign({}, base), { Fltr: {
|
|
1943
2289
|
_name: 'Brightness/Contrast',
|
|
1944
2290
|
_classID: 'BrgC',
|
|
@@ -1989,7 +2335,8 @@ function getWarpFromPlacedLayer(placed) {
|
|
|
1989
2335
|
},
|
|
1990
2336
|
};
|
|
1991
2337
|
}
|
|
1992
|
-
addHandler('SoLd',
|
|
2338
|
+
addHandler('SoLd', target => !!target.placedLayer && !target.placedLayer.external, // linked smart objects are stored in SoLE
|
|
2339
|
+
(reader, target, left) => {
|
|
1993
2340
|
if ((0, psdReader_1.readSignature)(reader) !== 'soLD')
|
|
1994
2341
|
throw new Error(`Invalid SoLd type`);
|
|
1995
2342
|
const version = (0, psdReader_1.readInt32)(reader);
|
|
@@ -2046,13 +2393,18 @@ addHandler('SoLd', hasKey('placedLayer'), (reader, target, left) => {
|
|
|
2046
2393
|
const placedType = placedLayerTypes.indexOf(placed.type);
|
|
2047
2394
|
if (placedType === -1)
|
|
2048
2395
|
throw new Error('Invalid placedLayer type');
|
|
2396
|
+
const warp = getWarpFromPlacedLayer(placed);
|
|
2397
|
+
// size of linked image matches warp bounds if it's not provided
|
|
2398
|
+
const bounds = warp.bounds;
|
|
2399
|
+
const width = placed.width || (bounds ? bounds.right.value - bounds.left.value : 0);
|
|
2400
|
+
const height = placed.height || (bounds ? bounds.bottom.value - bounds.top.value : 0);
|
|
2049
2401
|
const desc = Object.assign(Object.assign({ Idnt: placed.id, placed: (_a = placed.placed) !== null && _a !== void 0 ? _a : placed.id, PgNm: placed.pageNumber || 1, totalPages: placed.totalPages || 1 }, (placed.crop ? { Crop: placed.crop } : {})), { frameStep: placed.frameStep || { numerator: 0, denominator: 600 }, duration: placed.duration || { numerator: 0, denominator: 600 }, frameCount: placed.frameCount || 0, Annt: 16, Type: placedType, Trnf: placed.transform, nonAffineTransform: (_b = placed.nonAffineTransform) !== null && _b !== void 0 ? _b : placed.transform,
|
|
2050
2402
|
// quiltWarp: {} as any,
|
|
2051
|
-
warp: encodeWarp(
|
|
2403
|
+
warp: encodeWarp(warp), 'Sz ': {
|
|
2052
2404
|
_name: '',
|
|
2053
2405
|
_classID: 'Pnt ',
|
|
2054
|
-
Wdth:
|
|
2055
|
-
Hght:
|
|
2406
|
+
Wdth: width,
|
|
2407
|
+
Hght: height,
|
|
2056
2408
|
}, Rslt: placed.resolution ? (0, descriptor_1.unitsValue)(placed.resolution, 'resolution') : { units: 'Density', value: 72 } });
|
|
2057
2409
|
if (placed.filter) {
|
|
2058
2410
|
desc.filterFX = {
|
|
@@ -2066,14 +2418,6 @@ addHandler('SoLd', hasKey('placedLayer'), (reader, target, left) => {
|
|
|
2066
2418
|
filterFXList: placed.filter.list.map(f => serializeFilterFXItem(f)),
|
|
2067
2419
|
};
|
|
2068
2420
|
}
|
|
2069
|
-
// TODO:
|
|
2070
|
-
// desc.comp = -1;
|
|
2071
|
-
// desc.compInfo = { _name: '', _classID: 'null', compID: -1, originalCompID: -1 } as any;
|
|
2072
|
-
// desc.ClMg = {
|
|
2073
|
-
// _name: '',
|
|
2074
|
-
// _classID: 'ClMg',
|
|
2075
|
-
// placedLayerOCIOConversion: 'placedLayerOCIOConversion.placedLayerOCIOConvertEmbedded'
|
|
2076
|
-
// } as any;
|
|
2077
2421
|
// if (JSON.stringify(t) !== JSON.stringify(desc)) {
|
|
2078
2422
|
// console.log('read', require('util').inspect(t, false, 99, true));
|
|
2079
2423
|
// console.log('write', require('util').inspect(desc, false, 99, true));
|
|
@@ -2103,7 +2447,13 @@ addHandler('SoLd', hasKey('placedLayer'), (reader, target, left) => {
|
|
|
2103
2447
|
desc.compInfo = placed.compInfo;
|
|
2104
2448
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc, desc.quiltWarp ? 'quiltWarp' : 'warp');
|
|
2105
2449
|
});
|
|
2106
|
-
|
|
2450
|
+
const soLdHandler = exports.infoHandlersMap['SoLd'];
|
|
2451
|
+
addHandler('SoLE', // linked smart object (Photoshop doesn't write PlLd for these)
|
|
2452
|
+
// linked smart object (Photoshop doesn't write PlLd for these)
|
|
2453
|
+
target => { var _a; return !!((_a = target.placedLayer) === null || _a === void 0 ? void 0 : _a.external); }, (reader, target, left, psd, imageResources) => {
|
|
2454
|
+
soLdHandler.read(reader, target, left, psd, imageResources);
|
|
2455
|
+
target.placedLayer.external = true;
|
|
2456
|
+
}, soLdHandler.write);
|
|
2107
2457
|
addHandler('fxrp', hasKey('referencePoint'), (reader, target) => {
|
|
2108
2458
|
target.referencePoint = {
|
|
2109
2459
|
x: (0, psdReader_1.readFloat64)(reader),
|
|
@@ -2113,14 +2463,37 @@ addHandler('fxrp', hasKey('referencePoint'), (reader, target) => {
|
|
|
2113
2463
|
(0, psdWriter_1.writeFloat64)(writer, target.referencePoint.x);
|
|
2114
2464
|
(0, psdWriter_1.writeFloat64)(writer, target.referencePoint.y);
|
|
2115
2465
|
});
|
|
2116
|
-
|
|
2117
|
-
(
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2466
|
+
function createGlobalLayerInfoHandler(key, bitsPerChannel) {
|
|
2467
|
+
addHandler(key, () => false, (reader, _target, left, psd, imageResources) => {
|
|
2468
|
+
var _a;
|
|
2469
|
+
// Photoshop writes empty (or 8bit compatibility) layer info section alongside Lr16/Lr32 in 16/32bit documents,
|
|
2470
|
+
// layers from global info with matching bit depth replace layers from that section, other ones are only used
|
|
2471
|
+
// if the section is empty
|
|
2472
|
+
if (!reader.layersInGlobalInfo && (psd.bitsPerChannel === bitsPerChannel || !((_a = psd.children) === null || _a === void 0 ? void 0 : _a.length))) {
|
|
2473
|
+
const sectionLayers = psd.children;
|
|
2474
|
+
psd.children = [];
|
|
2475
|
+
try {
|
|
2476
|
+
(0, psdReader_1.readLayerInfo)(reader, psd, imageResources);
|
|
2477
|
+
}
|
|
2478
|
+
catch (e) {
|
|
2479
|
+
psd.children = sectionLayers; // keep layers from layer info section if global info is broken
|
|
2480
|
+
throw e;
|
|
2481
|
+
}
|
|
2482
|
+
reader.layersInGlobalInfo = true;
|
|
2483
|
+
}
|
|
2484
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
2485
|
+
}, () => { });
|
|
2486
|
+
}
|
|
2487
|
+
createGlobalLayerInfoHandler('Lr16', 16);
|
|
2488
|
+
createGlobalLayerInfoHandler('Lr32', 32);
|
|
2489
|
+
createGlobalLayerInfoHandler('Layr', undefined);
|
|
2490
|
+
// merged transparency markers, first extra channel of composite image is transparency
|
|
2491
|
+
for (const key of ['Mtrn', 'Mt16', 'Mt32']) {
|
|
2492
|
+
addHandler(key, () => false, (reader, _target, left) => {
|
|
2493
|
+
reader.globalAlpha = true;
|
|
2494
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
2495
|
+
}, () => { });
|
|
2496
|
+
}
|
|
2124
2497
|
addHandler('LMsk', hasKey('userMask'), (reader, target) => {
|
|
2125
2498
|
target.userMask = {
|
|
2126
2499
|
colorSpace: (0, psdReader_1.readColor)(reader),
|
|
@@ -2137,29 +2510,23 @@ addHandler('LMsk', hasKey('userMask'), (reader, target) => {
|
|
|
2137
2510
|
(0, psdWriter_1.writeUint8)(writer, 128);
|
|
2138
2511
|
(0, psdWriter_1.writeZeros)(writer, 1);
|
|
2139
2512
|
});
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
const patterns = target.patterns || [];
|
|
2158
|
-
for (const pattern of patterns) {
|
|
2159
|
-
(0, psdWriter_1.writePattern)(writer, pattern);
|
|
2160
|
-
}
|
|
2161
|
-
});
|
|
2162
|
-
}
|
|
2513
|
+
addHandler('Patt', // 'Pat2' and 'Pat3' (16 and 32 bit documents) are aliases, patterns are always written as 8 bit
|
|
2514
|
+
// 'Pat2' and 'Pat3' (16 and 32 bit documents) are aliases, patterns are always written as 8 bit
|
|
2515
|
+
target => !!(target.patterns && target.patterns.length > 0), (reader, target, left) => {
|
|
2516
|
+
while (left() > 0) {
|
|
2517
|
+
const pattern = (0, psdReader_1.readPatternSafe)(reader);
|
|
2518
|
+
if (!pattern)
|
|
2519
|
+
continue;
|
|
2520
|
+
if (target.patterns === undefined)
|
|
2521
|
+
target.patterns = [];
|
|
2522
|
+
target.patterns.push(pattern);
|
|
2523
|
+
}
|
|
2524
|
+
}, (writer, target, _, _options) => {
|
|
2525
|
+
const patterns = target.patterns || [];
|
|
2526
|
+
for (const pattern of patterns) {
|
|
2527
|
+
(0, psdWriter_1.writePattern)(writer, pattern);
|
|
2528
|
+
}
|
|
2529
|
+
});
|
|
2163
2530
|
addHandlerAlias('Pat2', 'Patt');
|
|
2164
2531
|
addHandlerAlias('Pat3', 'Patt');
|
|
2165
2532
|
/*
|
|
@@ -2336,6 +2703,10 @@ addHandler('Anno', target => target.annotations !== undefined, (reader, target,
|
|
|
2336
2703
|
writer.view.setUint32(dataOffset - 4, writer.offset - dataOffset, false);
|
|
2337
2704
|
}
|
|
2338
2705
|
});
|
|
2706
|
+
function readFileTypeSignature(reader) {
|
|
2707
|
+
const value = (0, psdReader_1.readSignature)(reader);
|
|
2708
|
+
return /^[\0 ]*$/.test(value) ? '' : value.trim(); // empty value is stored as spaces or zeros
|
|
2709
|
+
}
|
|
2339
2710
|
function createLnkHandler(tag) {
|
|
2340
2711
|
addHandler(tag, (target) => {
|
|
2341
2712
|
const psd = target;
|
|
@@ -2357,8 +2728,8 @@ function createLnkHandler(tag) {
|
|
|
2357
2728
|
const version = (0, psdReader_1.readInt32)(reader);
|
|
2358
2729
|
const id = (0, psdReader_1.readPascalString)(reader, 1);
|
|
2359
2730
|
const name = (0, psdReader_1.readUnicodeString)(reader);
|
|
2360
|
-
const fileType = (
|
|
2361
|
-
const fileCreator = (
|
|
2731
|
+
const fileType = readFileTypeSignature(reader); // ' ' if empty
|
|
2732
|
+
const fileCreator = readFileTypeSignature(reader); // ' ' or '\0\0\0\0' if empty
|
|
2362
2733
|
const dataSize = readLength64(reader);
|
|
2363
2734
|
const hasFileOpenDescriptor = (0, psdReader_1.readUint8)(reader);
|
|
2364
2735
|
const fileOpenDescriptor = hasFileOpenDescriptor ? (0, descriptor_1.readVersionAndDescriptor)(reader) : undefined;
|
|
@@ -2509,36 +2880,48 @@ createLnkHandler('lnk2');
|
|
|
2509
2880
|
createLnkHandler('lnkE');
|
|
2510
2881
|
addHandlerAlias('lnkD', 'lnk2');
|
|
2511
2882
|
addHandlerAlias('lnk3', 'lnk2');
|
|
2512
|
-
|
|
2883
|
+
// unicode names of saved paths (path data is stored in image resources 2000-2998)
|
|
2884
|
+
addHandler('pths', target => { var _a; return ((_a = target.imageResources) === null || _a === void 0 ? void 0 : _a.savedPaths) !== undefined; }, (reader, _target, left, psd) => {
|
|
2885
|
+
var _a, _b;
|
|
2513
2886
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader, true);
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
desc;
|
|
2517
|
-
|
|
2518
|
-
|
|
2887
|
+
const imageResources = (_a = psd.imageResources) !== null && _a !== void 0 ? _a : (psd.imageResources = {});
|
|
2888
|
+
const savedPaths = (_b = imageResources.savedPaths) !== null && _b !== void 0 ? _b : (imageResources.savedPaths = []);
|
|
2889
|
+
for (let i = 0; i < desc.pathList.length && i < savedPaths.length; i++) {
|
|
2890
|
+
const { pathUnicodeName, pathSymmetryClass } = desc.pathList[i];
|
|
2891
|
+
const path = savedPaths[i];
|
|
2892
|
+
// clipping path is referenced by (non-unicode) name
|
|
2893
|
+
if (imageResources.clippingPath && imageResources.clippingPath.name === path.name) {
|
|
2894
|
+
imageResources.clippingPath.name = pathUnicodeName;
|
|
2895
|
+
}
|
|
2896
|
+
path.name = pathUnicodeName;
|
|
2897
|
+
if (pathSymmetryClass)
|
|
2898
|
+
path.symmetryMode = pathSymmetryClass.pathSymmetryMode.split('.')[1];
|
|
2899
|
+
}
|
|
2900
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
2901
|
+
}, (writer, _target, psd) => {
|
|
2519
2902
|
const desc = {
|
|
2520
|
-
pathList:
|
|
2903
|
+
pathList: psd.imageResources.savedPaths.map(path => (Object.assign({ _name: '', _classID: 'pathInfoClass', pathUnicodeName: path.name }, (path.symmetryMode ? {
|
|
2904
|
+
pathSymmetryClass: {
|
|
2905
|
+
_name: '',
|
|
2906
|
+
_classID: 'pathSymmetryClass',
|
|
2907
|
+
pathSymmetryMode: `pathSymmetryModeEnum.${path.symmetryMode}`,
|
|
2908
|
+
},
|
|
2909
|
+
} : {})))),
|
|
2521
2910
|
};
|
|
2522
2911
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'pathsDataClass', desc);
|
|
2523
2912
|
});
|
|
2524
2913
|
addHandler('lyvr', hasKey('version'), (reader, target) => target.version = (0, psdReader_1.readUint32)(reader), (writer, target) => (0, psdWriter_1.writeUint32)(writer, target.version));
|
|
2525
|
-
addHandler('lfxs',
|
|
2526
|
-
//
|
|
2527
|
-
|
|
2528
|
-
// !!target.effects.dropShadow?.some(e => e.choke) ||
|
|
2529
|
-
// !!target.effects.innerShadow?.some(e => e.choke) ||
|
|
2530
|
-
// !!target.effects.outerGlow?.choke ||
|
|
2531
|
-
// !!target.effects.innerGlow?.choke
|
|
2532
|
-
// ),
|
|
2533
|
-
(reader, target, left) => {
|
|
2914
|
+
addHandler('lfxs', // effects of group layers (instead of 'lfx2' / 'lmfx')
|
|
2915
|
+
// effects of group layers (instead of 'lfx2' / 'lmfx')
|
|
2916
|
+
target => target.effects !== undefined && isGroupLayer(target), (reader, target, left) => {
|
|
2534
2917
|
const version = (0, psdReader_1.readUint32)(reader);
|
|
2535
2918
|
if (version !== 0)
|
|
2536
2919
|
throw new Error(`Invalid lfxs version`);
|
|
2537
2920
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
2538
|
-
target.effects = (0, descriptor_1.parseEffects)(desc,
|
|
2921
|
+
target.effects = (0, descriptor_1.parseEffects)(desc, reader);
|
|
2539
2922
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
2540
|
-
}, (writer, target
|
|
2541
|
-
const desc = (0, descriptor_1.serializeEffects)(target.effects,
|
|
2923
|
+
}, (writer, target) => {
|
|
2924
|
+
const desc = (0, descriptor_1.serializeEffects)(target.effects, writer, true);
|
|
2542
2925
|
(0, psdWriter_1.writeUint32)(writer, 0); // version
|
|
2543
2926
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
2544
2927
|
});
|
|
@@ -2574,6 +2957,10 @@ function readLevelsChannel(reader) {
|
|
|
2574
2957
|
const midtoneInput = (0, psdReader_1.readInt16)(reader) / 100;
|
|
2575
2958
|
return { shadowInput, highlightInput, shadowOutput, highlightOutput, midtoneInput };
|
|
2576
2959
|
}
|
|
2960
|
+
const defaultLevelsChannel = { shadowInput: 0, highlightInput: 255, shadowOutput: 0, highlightOutput: 255, midtoneInput: 1 };
|
|
2961
|
+
function isDefaultLevelsChannel(c) {
|
|
2962
|
+
return c.shadowInput === 0 && c.highlightInput === 255 && c.shadowOutput === 0 && c.highlightOutput === 255 && c.midtoneInput === 1;
|
|
2963
|
+
}
|
|
2577
2964
|
function writeLevelsChannel(writer, channel) {
|
|
2578
2965
|
(0, psdWriter_1.writeInt16)(writer, channel.shadowInput);
|
|
2579
2966
|
(0, psdWriter_1.writeInt16)(writer, channel.highlightInput);
|
|
@@ -2584,48 +2971,44 @@ function writeLevelsChannel(writer, channel) {
|
|
|
2584
2971
|
addHandler('levl', adjustmentType('levels'), (reader, target, left) => {
|
|
2585
2972
|
if ((0, psdReader_1.readUint16)(reader) !== 2)
|
|
2586
2973
|
throw new Error('Invalid levl version');
|
|
2587
|
-
const
|
|
2588
|
-
for (let i = 0; i < 29 && left(); i++) {
|
|
2589
|
-
|
|
2590
|
-
}
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2974
|
+
const channels = [];
|
|
2975
|
+
for (let i = 0; i < 29 && left() >= 10; i++) {
|
|
2976
|
+
channels.push(readLevelsChannel(reader));
|
|
2977
|
+
}
|
|
2978
|
+
if (left() >= 8) {
|
|
2979
|
+
const signature = (0, psdReader_1.readSignature)(reader);
|
|
2980
|
+
let totalChannelRecords;
|
|
2981
|
+
if (signature === 'ls\x00\x03') {
|
|
2982
|
+
// Clip Studio Paint writes 'ls' instead of 'Lvls' signature (version is part of the read signature)
|
|
2983
|
+
totalChannelRecords = (0, psdReader_1.readUint16)(reader);
|
|
2984
|
+
}
|
|
2985
|
+
else {
|
|
2986
|
+
if (signature !== 'Lvls')
|
|
2987
|
+
throw new Error(`Invalid levl signature`);
|
|
2988
|
+
if ((0, psdReader_1.readUint16)(reader) !== 3)
|
|
2989
|
+
throw new Error(`Invalid levl version`);
|
|
2990
|
+
totalChannelRecords = (0, psdReader_1.readUint16)(reader);
|
|
2991
|
+
}
|
|
2992
|
+
while (channels.length < totalChannelRecords && left() >= 10) {
|
|
2993
|
+
channels.push(readLevelsChannel(reader));
|
|
2604
2994
|
}
|
|
2605
2995
|
}
|
|
2996
|
+
// records for all possible channels are stored, skip unused ones
|
|
2997
|
+
while (channels.length && isDefaultLevelsChannel(channels[channels.length - 1]))
|
|
2998
|
+
channels.pop();
|
|
2999
|
+
target.adjustment = Object.assign(Object.assign({}, target.adjustment), { type: 'levels', channels });
|
|
2606
3000
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
2607
3001
|
}, (writer, target) => {
|
|
2608
|
-
const
|
|
2609
|
-
const defaultChannel = {
|
|
2610
|
-
shadowInput: 0,
|
|
2611
|
-
highlightInput: 255,
|
|
2612
|
-
shadowOutput: 0,
|
|
2613
|
-
highlightOutput: 255,
|
|
2614
|
-
midtoneInput: 1,
|
|
2615
|
-
};
|
|
3002
|
+
const channels = target.adjustment.channels || [];
|
|
2616
3003
|
(0, psdWriter_1.writeUint16)(writer, 2); // version
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
writeLevelsChannel(writer, info.green || defaultChannel);
|
|
2620
|
-
writeLevelsChannel(writer, info.blue || defaultChannel);
|
|
2621
|
-
for (let i = 0; i < (29 - 4); i++) {
|
|
2622
|
-
writeLevelsChannel(writer, defaultChannel);
|
|
3004
|
+
for (let i = 0; i < 29; i++) {
|
|
3005
|
+
writeLevelsChannel(writer, channels[i] || defaultLevelsChannel);
|
|
2623
3006
|
}
|
|
2624
3007
|
(0, psdWriter_1.writeSignature)(writer, 'Lvls');
|
|
2625
3008
|
(0, psdWriter_1.writeUint16)(writer, 3); // version
|
|
2626
3009
|
(0, psdWriter_1.writeUint16)(writer, 62); // total count
|
|
2627
|
-
for (let i =
|
|
2628
|
-
writeLevelsChannel(writer,
|
|
3010
|
+
for (let i = 29; i < 62; i++) {
|
|
3011
|
+
writeLevelsChannel(writer, channels[i] || defaultLevelsChannel);
|
|
2629
3012
|
}
|
|
2630
3013
|
});
|
|
2631
3014
|
function readCurveChannel(reader) {
|
|
@@ -2646,87 +3029,78 @@ function writeCurveChannel(writer, channel) {
|
|
|
2646
3029
|
}
|
|
2647
3030
|
}
|
|
2648
3031
|
addHandler('curv', adjustmentType('curves'), (reader, target, left) => {
|
|
2649
|
-
(0, psdReader_1.readUint8)(reader);
|
|
2650
|
-
|
|
3032
|
+
const isMap = !!(0, psdReader_1.readUint8)(reader); // curves drawn with pencil tool (lookup tables instead of points)
|
|
3033
|
+
const version = (0, psdReader_1.readUint16)(reader);
|
|
3034
|
+
if (version !== 1 && version !== 4)
|
|
2651
3035
|
throw new Error('Invalid curv version');
|
|
2652
|
-
(0, psdReader_1.
|
|
2653
|
-
const channels =
|
|
2654
|
-
const
|
|
2655
|
-
if (
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
target.adjustment = Object.assign(Object.assign({}, target.adjustment), info);
|
|
2664
|
-
// ignoring, duplicate information
|
|
2665
|
-
// checkSignature(reader, 'Crv ');
|
|
2666
|
-
// const cVersion = readUint16(reader);
|
|
2667
|
-
// readUint16(reader);
|
|
2668
|
-
// const channelCount = readUint16(reader);
|
|
2669
|
-
// for (let i = 0; i < channelCount; i++) {
|
|
2670
|
-
// const index = readUint16(reader);
|
|
2671
|
-
// const nodes = readUint16(reader);
|
|
2672
|
-
// for (let j = 0; j < nodes; j++) {
|
|
2673
|
-
// const output = readInt16(reader);
|
|
2674
|
-
// const input = readInt16(reader);
|
|
2675
|
-
// }
|
|
2676
|
-
// }
|
|
2677
|
-
(0, psdReader_1.skipBytes)(reader, left());
|
|
2678
|
-
}, (writer, target) => {
|
|
2679
|
-
const info = target.adjustment;
|
|
2680
|
-
const { rgb, red, green, blue } = info;
|
|
2681
|
-
let channels = 0;
|
|
2682
|
-
let channelCount = 0;
|
|
2683
|
-
if (rgb && rgb.length) {
|
|
2684
|
-
channels |= 1;
|
|
2685
|
-
channelCount++;
|
|
2686
|
-
}
|
|
2687
|
-
if (red && red.length) {
|
|
2688
|
-
channels |= 2;
|
|
2689
|
-
channelCount++;
|
|
3036
|
+
const countOrMask = (0, psdReader_1.readUint32)(reader);
|
|
3037
|
+
const channels = [];
|
|
3038
|
+
const readChannel = () => isMap ? Array.from((0, psdReader_1.readBytes)(reader, 256)) : readCurveChannel(reader);
|
|
3039
|
+
if (version === 1) {
|
|
3040
|
+
for (let i = 0; i < 32; i++) {
|
|
3041
|
+
if (countOrMask & (1 << i)) {
|
|
3042
|
+
while (channels.length < i)
|
|
3043
|
+
channels.push([]);
|
|
3044
|
+
channels.push(readChannel());
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
2690
3047
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
3048
|
+
else {
|
|
3049
|
+
if (countOrMask > 64)
|
|
3050
|
+
throw new Error('Invalid curv channel count');
|
|
3051
|
+
for (let i = 0; i < countOrMask; i++)
|
|
3052
|
+
channels.push(readChannel());
|
|
3053
|
+
}
|
|
3054
|
+
// extra section stores curves for all channels (including ones that don't fit in the mask)
|
|
3055
|
+
if (version === 1 && left() >= 10 && (0, psdReader_1.readSignature)(reader) === 'Crv ') {
|
|
3056
|
+
(0, psdReader_1.readUint16)(reader); // version
|
|
3057
|
+
const count = (0, psdReader_1.readUint32)(reader);
|
|
3058
|
+
for (let i = 0; i < count && left() >= 2; i++) {
|
|
3059
|
+
const index = (0, psdReader_1.readUint16)(reader);
|
|
3060
|
+
const channel = readChannel();
|
|
3061
|
+
while (channels.length < index)
|
|
3062
|
+
channels.push([]);
|
|
3063
|
+
channels[index] = channel;
|
|
3064
|
+
}
|
|
2694
3065
|
}
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
3066
|
+
target.adjustment = Object.assign(Object.assign(Object.assign({}, target.adjustment), { type: 'curves' }), (isMap ? { values: channels } : { channels: channels }));
|
|
3067
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
3068
|
+
}, (writer, target) => {
|
|
3069
|
+
var _a;
|
|
3070
|
+
const adjustment = target.adjustment;
|
|
3071
|
+
const isMap = !!adjustment.values;
|
|
3072
|
+
const channels = (isMap ? adjustment.values : adjustment.channels) || [];
|
|
3073
|
+
const used = [];
|
|
3074
|
+
let channelsMask = 0;
|
|
3075
|
+
for (let i = 0; i < channels.length; i++) {
|
|
3076
|
+
if ((_a = channels[i]) === null || _a === void 0 ? void 0 : _a.length) {
|
|
3077
|
+
if (i < 32)
|
|
3078
|
+
channelsMask |= 1 << i;
|
|
3079
|
+
used.push(i);
|
|
3080
|
+
}
|
|
2698
3081
|
}
|
|
2699
|
-
(
|
|
3082
|
+
const writeChannel = (channel) => {
|
|
3083
|
+
var _a;
|
|
3084
|
+
if (isMap) {
|
|
3085
|
+
for (let i = 0; i < 256; i++)
|
|
3086
|
+
(0, psdWriter_1.writeUint8)(writer, (0, helpers_1.clamp)(Math.round((_a = channel[i]) !== null && _a !== void 0 ? _a : i), 0, 255));
|
|
3087
|
+
}
|
|
3088
|
+
else {
|
|
3089
|
+
writeCurveChannel(writer, channel);
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
(0, psdWriter_1.writeUint8)(writer, isMap ? 1 : 0);
|
|
2700
3093
|
(0, psdWriter_1.writeUint16)(writer, 1); // version
|
|
2701
|
-
(0, psdWriter_1.
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
if (red && red.length)
|
|
2706
|
-
writeCurveChannel(writer, red);
|
|
2707
|
-
if (green && green.length)
|
|
2708
|
-
writeCurveChannel(writer, green);
|
|
2709
|
-
if (blue && blue.length)
|
|
2710
|
-
writeCurveChannel(writer, blue);
|
|
3094
|
+
(0, psdWriter_1.writeUint32)(writer, channelsMask >>> 0);
|
|
3095
|
+
for (const i of used)
|
|
3096
|
+
if (i < 32)
|
|
3097
|
+
writeChannel(channels[i]);
|
|
2711
3098
|
(0, psdWriter_1.writeSignature)(writer, 'Crv ');
|
|
2712
3099
|
(0, psdWriter_1.writeUint16)(writer, 4); // version
|
|
2713
|
-
(0, psdWriter_1.
|
|
2714
|
-
(
|
|
2715
|
-
|
|
2716
|
-
(
|
|
2717
|
-
writeCurveChannel(writer, rgb);
|
|
2718
|
-
}
|
|
2719
|
-
if (red && red.length) {
|
|
2720
|
-
(0, psdWriter_1.writeUint16)(writer, 1);
|
|
2721
|
-
writeCurveChannel(writer, red);
|
|
2722
|
-
}
|
|
2723
|
-
if (green && green.length) {
|
|
2724
|
-
(0, psdWriter_1.writeUint16)(writer, 2);
|
|
2725
|
-
writeCurveChannel(writer, green);
|
|
2726
|
-
}
|
|
2727
|
-
if (blue && blue.length) {
|
|
2728
|
-
(0, psdWriter_1.writeUint16)(writer, 3);
|
|
2729
|
-
writeCurveChannel(writer, blue);
|
|
3100
|
+
(0, psdWriter_1.writeUint32)(writer, used.length);
|
|
3101
|
+
for (const i of used) {
|
|
3102
|
+
(0, psdWriter_1.writeUint16)(writer, i);
|
|
3103
|
+
writeChannel(channels[i]);
|
|
2730
3104
|
}
|
|
2731
3105
|
});
|
|
2732
3106
|
addHandler('expA', adjustmentType('exposure'), (reader, target, left) => {
|
|
@@ -2783,12 +3157,34 @@ function writeHueChannel(writer, channel) {
|
|
|
2783
3157
|
addHandler('hue2', adjustmentType('hue/saturation'), (reader, target, left) => {
|
|
2784
3158
|
if ((0, psdReader_1.readUint16)(reader) !== 2)
|
|
2785
3159
|
throw new Error('Invalid hue2 version');
|
|
2786
|
-
|
|
3160
|
+
const colorize = !!(0, psdReader_1.readUint8)(reader);
|
|
3161
|
+
(0, psdReader_1.skipBytes)(reader, 1);
|
|
3162
|
+
const colorizeHue = (0, psdReader_1.readInt16)(reader); // stored as -180..180
|
|
3163
|
+
const colorizeSaturation = (0, psdReader_1.readInt16)(reader);
|
|
3164
|
+
const colorizeLightness = (0, psdReader_1.readInt16)(reader);
|
|
3165
|
+
target.adjustment = Object.assign(Object.assign({}, target.adjustment), { type: 'hue/saturation', colorize, colorization: {
|
|
3166
|
+
hue: colorizeHue < 0 ? colorizeHue + 360 : colorizeHue,
|
|
3167
|
+
saturation: colorizeSaturation,
|
|
3168
|
+
lightness: colorizeLightness,
|
|
3169
|
+
}, master: {
|
|
3170
|
+
hue: (0, psdReader_1.readInt16)(reader),
|
|
3171
|
+
saturation: (0, psdReader_1.readInt16)(reader),
|
|
3172
|
+
lightness: (0, psdReader_1.readInt16)(reader),
|
|
3173
|
+
}, reds: readHueChannel(reader), yellows: readHueChannel(reader), greens: readHueChannel(reader), cyans: readHueChannel(reader), blues: readHueChannel(reader), magentas: readHueChannel(reader) });
|
|
2787
3174
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
2788
3175
|
}, (writer, target) => {
|
|
3176
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
2789
3177
|
const info = target.adjustment;
|
|
2790
3178
|
(0, psdWriter_1.writeUint16)(writer, 2); // version
|
|
2791
|
-
|
|
3179
|
+
(0, psdWriter_1.writeUint8)(writer, info.colorize ? 1 : 0);
|
|
3180
|
+
(0, psdWriter_1.writeUint8)(writer, 0);
|
|
3181
|
+
const colorizeHue = Math.round((_b = (_a = info.colorization) === null || _a === void 0 ? void 0 : _a.hue) !== null && _b !== void 0 ? _b : 0);
|
|
3182
|
+
(0, psdWriter_1.writeInt16)(writer, colorizeHue > 180 ? colorizeHue - 360 : colorizeHue);
|
|
3183
|
+
(0, psdWriter_1.writeInt16)(writer, Math.round((_d = (_c = info.colorization) === null || _c === void 0 ? void 0 : _c.saturation) !== null && _d !== void 0 ? _d : 0));
|
|
3184
|
+
(0, psdWriter_1.writeInt16)(writer, Math.round((_f = (_e = info.colorization) === null || _e === void 0 ? void 0 : _e.lightness) !== null && _f !== void 0 ? _f : 0));
|
|
3185
|
+
(0, psdWriter_1.writeInt16)(writer, Math.round((_h = (_g = info.master) === null || _g === void 0 ? void 0 : _g.hue) !== null && _h !== void 0 ? _h : 0));
|
|
3186
|
+
(0, psdWriter_1.writeInt16)(writer, Math.round((_k = (_j = info.master) === null || _j === void 0 ? void 0 : _j.saturation) !== null && _k !== void 0 ? _k : 0));
|
|
3187
|
+
(0, psdWriter_1.writeInt16)(writer, Math.round((_m = (_l = info.master) === null || _l === void 0 ? void 0 : _l.lightness) !== null && _m !== void 0 ? _m : 0));
|
|
2792
3188
|
writeHueChannel(writer, info.reds);
|
|
2793
3189
|
writeHueChannel(writer, info.yellows);
|
|
2794
3190
|
writeHueChannel(writer, info.greens);
|
|
@@ -2867,16 +3263,18 @@ addHandler('phfl', adjustmentType('photo filter'), (reader, target, left) => {
|
|
|
2867
3263
|
color = (0, psdReader_1.readColor)(reader);
|
|
2868
3264
|
}
|
|
2869
3265
|
else { // version 3
|
|
2870
|
-
//
|
|
2871
|
-
//
|
|
2872
|
-
|
|
2873
|
-
const
|
|
2874
|
-
const
|
|
2875
|
-
|
|
3266
|
+
// XYZ color relative to D50 white point, 32768 = 1.0 (not documented, matches colors of Photoshop presets),
|
|
3267
|
+
// converted to Lab (same scale as readColor()) so it can be written back as version 2
|
|
3268
|
+
const x = (0, psdReader_1.readInt32)(reader) / 32768;
|
|
3269
|
+
const y = (0, psdReader_1.readInt32)(reader) / 32768;
|
|
3270
|
+
const z = (0, psdReader_1.readInt32)(reader) / 32768;
|
|
3271
|
+
if (!(x >= 0 && y >= 0 && z >= 0 && x <= 2 && y <= 2 && z <= 2))
|
|
3272
|
+
throw new Error('Invalid phfl XYZ color');
|
|
3273
|
+
const f = (t) => t > 216 / 24389 ? Math.cbrt(t) : (24389 / 27 * t + 16) / 116;
|
|
2876
3274
|
color = {
|
|
2877
|
-
l:
|
|
2878
|
-
a: (0, helpers_1.normalizeLabAB)(
|
|
2879
|
-
b: (0, helpers_1.normalizeLabAB)(
|
|
3275
|
+
l: Math.max(0, 116 * f(y) - 16) / 100,
|
|
3276
|
+
a: (0, helpers_1.normalizeLabAB)(500 * (f(x) - f(y))),
|
|
3277
|
+
b: (0, helpers_1.normalizeLabAB)(200 * (f(y) - f(z))),
|
|
2880
3278
|
};
|
|
2881
3279
|
}
|
|
2882
3280
|
target.adjustment = {
|
|
@@ -3044,7 +3442,7 @@ addHandler('grdm', adjustmentType('gradient map'), (reader, target, left) => {
|
|
|
3044
3442
|
reader.offset--;
|
|
3045
3443
|
if (hasMethod) {
|
|
3046
3444
|
const method = (0, psdReader_1.readSignature)(reader);
|
|
3047
|
-
info.method = descriptor_1.gradientInterpolationMethodType.decode(method);
|
|
3445
|
+
info.method = descriptor_1.gradientInterpolationMethodType.decode(`gradientInterpolationMethodType.${method}`);
|
|
3048
3446
|
}
|
|
3049
3447
|
info.name = (0, psdReader_1.readUnicodeString)(reader);
|
|
3050
3448
|
info.colorStops = [];
|
|
@@ -3106,7 +3504,7 @@ addHandler('grdm', adjustmentType('gradient map'), (reader, target, left) => {
|
|
|
3106
3504
|
(0, psdWriter_1.writeUint8)(writer, info.reverse ? 1 : 0);
|
|
3107
3505
|
(0, psdWriter_1.writeUint8)(writer, info.dither ? 1 : 0);
|
|
3108
3506
|
if (info.method !== undefined) {
|
|
3109
|
-
(0, psdWriter_1.writeSignature)(writer, descriptor_1.gradientInterpolationMethodType.encode(info.method));
|
|
3507
|
+
(0, psdWriter_1.writeSignature)(writer, descriptor_1.gradientInterpolationMethodType.encode(info.method).split('.')[1]);
|
|
3110
3508
|
}
|
|
3111
3509
|
(0, psdWriter_1.writeUnicodeStringWithPadding)(writer, info.name || '');
|
|
3112
3510
|
(0, psdWriter_1.writeUint16)(writer, info.colorStops && info.colorStops.length || 0);
|
|
@@ -3414,6 +3812,10 @@ addHandler('FEid', hasKey('filterEffectsMasks'), (reader, target, leftBytes) =>
|
|
|
3414
3812
|
}
|
|
3415
3813
|
});
|
|
3416
3814
|
addHandlerAlias('FXid', 'FEid');
|
|
3815
|
+
addHandlerAlias('FELS', 'FEid'); // filter effects 3
|
|
3816
|
+
addHandlerAlias('hue ', 'hue2'); // old hue/saturation (Photoshop 4.0), same structure as 'hue2'
|
|
3817
|
+
addHandlerAlias('plLd', 'PlLd'); // old placed layer key
|
|
3818
|
+
addHandlerAlias('abdd', 'artb'); // artboard data 3
|
|
3417
3819
|
addHandler('FMsk', hasKey('filterMask'), (reader, target) => {
|
|
3418
3820
|
target.filterMask = {
|
|
3419
3821
|
colorSpace: (0, psdReader_1.readColor)(reader),
|
|
@@ -3428,17 +3830,22 @@ addHandler('artd', // document-wide artboard info
|
|
|
3428
3830
|
// document-wide artboard info
|
|
3429
3831
|
target => target.artboards !== undefined, (reader, target, left) => {
|
|
3430
3832
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
3431
|
-
target.artboards = {
|
|
3432
|
-
|
|
3433
|
-
autoExpandOffset
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3833
|
+
const artboards = target.artboards = { count: desc['Cnt '] };
|
|
3834
|
+
if (desc.autoExpandOffset)
|
|
3835
|
+
artboards.autoExpandOffset = { horizontal: desc.autoExpandOffset.Hrzn, vertical: desc.autoExpandOffset.Vrtc };
|
|
3836
|
+
if (desc.origin)
|
|
3837
|
+
artboards.origin = { horizontal: desc.origin.Hrzn, vertical: desc.origin.Vrtc };
|
|
3838
|
+
if (desc.autoExpandEnabled !== undefined)
|
|
3839
|
+
artboards.autoExpandEnabled = desc.autoExpandEnabled;
|
|
3840
|
+
if (desc.autoNestEnabled !== undefined)
|
|
3841
|
+
artboards.autoNestEnabled = desc.autoNestEnabled;
|
|
3842
|
+
if (desc.autoPositionEnabled !== undefined)
|
|
3843
|
+
artboards.autoPositionEnabled = desc.autoPositionEnabled;
|
|
3844
|
+
artboards.shrinkwrapOnSaveEnabled = !!desc.shrinkwrapOnSaveEnabled;
|
|
3845
|
+
if (desc.docDefaultNewArtboardBackgroundColor)
|
|
3846
|
+
artboards.docDefaultNewArtboardBackgroundColor = (0, descriptor_1.parseColor)(desc.docDefaultNewArtboardBackgroundColor);
|
|
3847
|
+
if (desc.docDefaultNewArtboardBackgroundType !== undefined)
|
|
3848
|
+
artboards.docDefaultNewArtboardBackgroundType = desc.docDefaultNewArtboardBackgroundType;
|
|
3442
3849
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
3443
3850
|
}, (writer, target) => {
|
|
3444
3851
|
var _a, _b, _c, _d, _e;
|
|
@@ -3456,21 +3863,23 @@ target => target.artboards !== undefined, (reader, target, left) => {
|
|
|
3456
3863
|
};
|
|
3457
3864
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc, 'artd');
|
|
3458
3865
|
});
|
|
3866
|
+
function isGroupLayer(target) {
|
|
3867
|
+
return !!target.children;
|
|
3868
|
+
}
|
|
3459
3869
|
function hasMultiEffects(effects) {
|
|
3460
3870
|
return Object.keys(effects).map(key => effects[key]).some(v => Array.isArray(v) && v.length > 1);
|
|
3461
3871
|
}
|
|
3462
|
-
addHandler('lfx2', target => target.effects !== undefined && !hasMultiEffects(target.effects), (reader, target, left) => {
|
|
3872
|
+
addHandler('lfx2', target => target.effects !== undefined && !isGroupLayer(target) && !hasMultiEffects(target.effects), (reader, target, left) => {
|
|
3463
3873
|
const version = (0, psdReader_1.readUint32)(reader);
|
|
3464
3874
|
if (version !== 0)
|
|
3465
3875
|
throw new Error(`Invalid lfx2 version`);
|
|
3466
3876
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
3467
3877
|
// console.log('READ', require('util').inspect(desc, false, 99, true));
|
|
3468
|
-
//
|
|
3469
|
-
|
|
3470
|
-
target.effects = (0, descriptor_1.parseEffects)(desc, !!reader.logMissingFeatures);
|
|
3878
|
+
// discard if read in 'lrFX' section ('lmfx' and 'lfx2' are never stored together)
|
|
3879
|
+
target.effects = (0, descriptor_1.parseEffects)(desc, reader);
|
|
3471
3880
|
(0, psdReader_1.skipBytes)(reader, left());
|
|
3472
|
-
}, (writer, target
|
|
3473
|
-
const desc = (0, descriptor_1.serializeEffects)(target.effects,
|
|
3881
|
+
}, (writer, target) => {
|
|
3882
|
+
const desc = (0, descriptor_1.serializeEffects)(target.effects, writer, true);
|
|
3474
3883
|
// console.log('WRITE', require('util').inspect(desc, false, 99, true));
|
|
3475
3884
|
(0, psdWriter_1.writeUint32)(writer, 0); // version
|
|
3476
3885
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
@@ -3523,16 +3932,74 @@ addHandler('cinf', hasKey('compositorUsed'), (reader, target, left) => {
|
|
|
3523
3932
|
desc.compCoreGPUSupport = `reason.${cinf.compCoreGPUSupport}`;
|
|
3524
3933
|
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc);
|
|
3525
3934
|
});
|
|
3526
|
-
//
|
|
3527
|
-
addHandler('extn', target => target.
|
|
3935
|
+
// generator settings of the document (layers store them in 'shmd' section)
|
|
3936
|
+
addHandler('extn', target => target.generatorSettings !== undefined && isDocument(target), (reader, target, left) => {
|
|
3528
3937
|
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3938
|
+
if (desc.generatorSettings)
|
|
3939
|
+
target.generatorSettings = parseGeneratorSettings(desc.generatorSettings);
|
|
3940
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
3532
3941
|
}, (writer, target) => {
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3942
|
+
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', serializeGeneratorSettings(target.generatorSettings));
|
|
3943
|
+
});
|
|
3944
|
+
// generator settings stored by older versions of Photoshop (written back in 'shmd' or 'extn' section)
|
|
3945
|
+
addHandler('extd', () => false, (reader, target, left) => {
|
|
3946
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
3947
|
+
if (desc.generatorSettings && target.generatorSettings === undefined) {
|
|
3948
|
+
target.generatorSettings = parseGeneratorSettings(desc.generatorSettings);
|
|
3949
|
+
}
|
|
3950
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
3951
|
+
}, () => { });
|
|
3952
|
+
addHandler('frgb', // frame tool group
|
|
3953
|
+
hasKey('framedGroup'), (reader, target, left) => {
|
|
3954
|
+
const desc = (0, descriptor_1.readVersionAndDescriptor)(reader);
|
|
3955
|
+
const rect = desc.framedGroupRect;
|
|
3956
|
+
target.framedGroup = {
|
|
3957
|
+
rect: { top: rect['Top '], left: rect.Left, bottom: rect.Btom, right: rect.Rght },
|
|
3958
|
+
type: desc.framedGroupType,
|
|
3959
|
+
};
|
|
3960
|
+
if (desc.LockPPI !== undefined)
|
|
3961
|
+
target.framedGroup.lockPPI = desc.LockPPI;
|
|
3962
|
+
if (desc.PreferredResolution !== undefined)
|
|
3963
|
+
target.framedGroup.preferredResolution = desc.PreferredResolution;
|
|
3964
|
+
if (desc.SavedIteratedName !== undefined)
|
|
3965
|
+
target.framedGroup.savedIteratedName = desc.SavedIteratedName;
|
|
3966
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
3967
|
+
}, (writer, target) => {
|
|
3968
|
+
const group = target.framedGroup;
|
|
3969
|
+
const rect = group.rect;
|
|
3970
|
+
const desc = {
|
|
3971
|
+
framedGroupRect: { _name: '', _classID: 'classFloatRect', 'Top ': rect.top, Left: rect.left, Btom: rect.bottom, Rght: rect.right },
|
|
3972
|
+
framedGroupType: group.type,
|
|
3973
|
+
};
|
|
3974
|
+
if (group.lockPPI !== undefined)
|
|
3975
|
+
desc.LockPPI = group.lockPPI;
|
|
3976
|
+
if (group.preferredResolution !== undefined)
|
|
3977
|
+
desc.PreferredResolution = group.preferredResolution;
|
|
3978
|
+
if (group.savedIteratedName !== undefined)
|
|
3979
|
+
desc.SavedIteratedName = group.savedIteratedName;
|
|
3980
|
+
(0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'framedGroup', desc);
|
|
3981
|
+
});
|
|
3982
|
+
addHandler('anFX', hasKey('animationEffects'), (reader, target, left) => {
|
|
3983
|
+
target.animationEffects = (0, psdReader_1.readBytes)(reader, left());
|
|
3984
|
+
}, (writer, target) => {
|
|
3985
|
+
(0, psdWriter_1.writeBytes)(writer, target.animationEffects);
|
|
3986
|
+
});
|
|
3987
|
+
addHandler('PxSD', // pixel source data 2 (video layer frames)
|
|
3988
|
+
hasKey('pixelSourceData'), (reader, target, left) => {
|
|
3989
|
+
target.pixelSourceData = [];
|
|
3990
|
+
while (left() >= 8) {
|
|
3991
|
+
const length = readLength64(reader);
|
|
3992
|
+
if (length > left())
|
|
3993
|
+
throw new Error('Invalid PxSD data length');
|
|
3994
|
+
target.pixelSourceData.push((0, psdReader_1.readBytes)(reader, length));
|
|
3995
|
+
}
|
|
3996
|
+
(0, psdReader_1.skipBytes)(reader, left());
|
|
3997
|
+
}, (writer, target) => {
|
|
3998
|
+
for (const data of target.pixelSourceData) {
|
|
3999
|
+
(0, psdWriter_1.writeUint32)(writer, 0);
|
|
4000
|
+
(0, psdWriter_1.writeUint32)(writer, data.byteLength);
|
|
4001
|
+
(0, psdWriter_1.writeBytes)(writer, data);
|
|
4002
|
+
}
|
|
3536
4003
|
});
|
|
3537
4004
|
addHandler('iOpa', hasKey('fillOpacity'), (reader, target) => {
|
|
3538
4005
|
target.fillOpacity = (0, psdReader_1.readUint8)(reader) / 0xff;
|