UNPKG

ag-psd

Version:

Library for reading and writing PSD files

918 lines (917 loc) 792 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.agPsd = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.readAbr = void 0; var descriptor_1 = require("./descriptor"); var psdReader_1 = require("./psdReader"); var dynamicsControl = ['off', 'fade', 'pen pressure', 'pen tilt', 'stylus wheel', 'initial direction', 'direction', 'initial rotation', 'rotation']; var toBrushType = { _: 'brush', MixB: 'mixer brush', SmTl: 'smudge brush', // PbTl // ErTl }; function parseDynamics(desc) { return { control: dynamicsControl[desc.bVTy], steps: desc.fStp, jitter: (0, descriptor_1.parsePercent)(desc.jitter), minimum: (0, descriptor_1.parsePercent)(desc['Mnm ']), }; } function parseBrushShape(desc) { var shape = { size: (0, descriptor_1.parseUnitsToNumber)(desc.Dmtr, 'Pixels'), angle: (0, descriptor_1.parseAngle)(desc.Angl), roundness: (0, descriptor_1.parsePercent)(desc.Rndn), spacingOn: desc.Intr, spacing: (0, descriptor_1.parsePercent)(desc.Spcn), flipX: desc.flipX, flipY: desc.flipY, }; if (desc['Nm ']) shape.name = desc['Nm ']; if (desc.Hrdn) shape.hardness = (0, descriptor_1.parsePercent)(desc.Hrdn); if (desc.sampledData) shape.sampledData = desc.sampledData; return shape; } function readAbr(buffer, options) { var _a, _b, _c, _d; if (options === void 0) { options = {}; } var reader = (0, psdReader_1.createReader)(buffer.buffer, buffer.byteOffset, buffer.byteLength); var version = (0, psdReader_1.readInt16)(reader); var samples = []; var brushes = []; var patterns = []; if (version === 1 || version === 2) { throw new Error("Unsupported ABR version (".concat(version, ")")); // TODO: ... } else if (version === 6 || version === 7 || version === 9 || version === 10) { var minorVersion = (0, psdReader_1.readInt16)(reader); if (minorVersion !== 1 && minorVersion !== 2) throw new Error('Unsupported ABR minor version'); while (reader.offset < reader.view.byteLength) { (0, psdReader_1.checkSignature)(reader, '8BIM'); var type = (0, psdReader_1.readSignature)(reader); var size = (0, psdReader_1.readUint32)(reader); var end = reader.offset + size; switch (type) { case 'samp': { while (reader.offset < end) { var brushLength = (0, psdReader_1.readUint32)(reader); while (brushLength & 3) brushLength++; // pad to 4 byte alignment var brushEnd = reader.offset + brushLength; var id = (0, psdReader_1.readPascalString)(reader, 1); // v1 - Skip the Int16 bounds rectangle and the unknown Int16. // v2 - Skip the unknown bytes. (0, psdReader_1.skipBytes)(reader, minorVersion === 1 ? 10 : 264); var y = (0, psdReader_1.readInt32)(reader); var x = (0, psdReader_1.readInt32)(reader); var h = (0, psdReader_1.readInt32)(reader) - y; var w = (0, psdReader_1.readInt32)(reader) - x; if (w <= 0 || h <= 0) throw new Error('Invalid bounds'); var bithDepth = (0, psdReader_1.readInt16)(reader); var compression = (0, psdReader_1.readUint8)(reader); // 0 - raw, 1 - RLE var alpha = new Uint8Array(w * h); if (bithDepth === 8) { if (compression === 0) { alpha.set((0, psdReader_1.readBytes)(reader, alpha.byteLength)); } else if (compression === 1) { (0, psdReader_1.readDataRLE)(reader, { width: w, height: h, data: alpha }, w, h, bithDepth, 1, [0], false); } else { throw new Error('Invalid compression'); } } else if (bithDepth === 16) { if (compression === 0) { for (var i = 0; i < alpha.byteLength; i++) { alpha[i] = (0, psdReader_1.readUint16)(reader) >> 8; // convert to 8bit values } } else if (compression === 1) { throw new Error('not implemented (16bit RLE)'); // TODO: ... } else { throw new Error('Invalid compression'); } } else { throw new Error('Invalid depth'); } samples.push({ id: id, bounds: { x: x, y: y, w: w, h: h }, alpha: alpha }); reader.offset = brushEnd; } break; } case 'desc': { var desc = (0, descriptor_1.readVersionAndDescriptor)(reader, true); // console.log(require('util').inspect(desc, false, 99, true)); for (var _i = 0, _e = desc.Brsh; _i < _e.length; _i++) { var brush = _e[_i]; var b = { name: brush['Nm '], shape: parseBrushShape(brush.Brsh), spacing: (0, descriptor_1.parsePercent)(brush.Spcn), // TODO: brushGroup ??? wetEdges: brush.Wtdg, noise: brush.Nose, // TODO: TxtC ??? smoothing / build-up ? // TODO: 'Rpt ' ??? useBrushSize: brush.useBrushSize, // ??? }; if (brush.interpretation != null) b.interpretation = brush.interpretation; if (brush.protectTexture != null) b.protectTexture = brush.protectTexture; if (brush.useTipDynamics) { b.shapeDynamics = { tiltScale: (0, descriptor_1.parsePercent)(brush.tiltScale), sizeDynamics: parseDynamics(brush.szVr), angleDynamics: parseDynamics(brush.angleDynamics), roundnessDynamics: parseDynamics(brush.roundnessDynamics), flipX: brush.flipX, flipY: brush.flipY, brushProjection: brush.brushProjection, minimumDiameter: (0, descriptor_1.parsePercent)(brush.minimumDiameter), minimumRoundness: (0, descriptor_1.parsePercent)(brush.minimumRoundness), }; } if (brush.useScatter) { b.scatter = { count: brush['Cnt '], bothAxes: brush.bothAxes, countDynamics: parseDynamics(brush.countDynamics), scatterDynamics: parseDynamics(brush.scatterDynamics), }; } if (brush.useTexture && brush.Txtr) { b.texture = { id: brush.Txtr.Idnt, name: brush.Txtr['Nm '], blendMode: descriptor_1.BlnM.decode(brush.textureBlendMode), depth: (0, descriptor_1.parsePercent)(brush.textureDepth), depthMinimum: (0, descriptor_1.parsePercent)(brush.minimumDepth), depthDynamics: parseDynamics(brush.textureDepthDynamics), scale: (0, descriptor_1.parsePercent)(brush.textureScale), invert: brush.InvT, brightness: brush.textureBrightness, contrast: brush.textureContrast, }; } var db = brush.dualBrush; if (db && db.useDualBrush) { b.dualBrush = { flip: db.Flip, shape: parseBrushShape(db.Brsh), blendMode: descriptor_1.BlnM.decode(db.BlnM), useScatter: db.useScatter, spacing: (0, descriptor_1.parsePercent)(db.Spcn), count: db['Cnt '], bothAxes: db.bothAxes, countDynamics: parseDynamics(db.countDynamics), scatterDynamics: parseDynamics(db.scatterDynamics), }; } if (brush.useColorDynamics) { b.colorDynamics = { foregroundBackground: parseDynamics(brush.clVr), hue: (0, descriptor_1.parsePercent)(brush['H ']), saturation: (0, descriptor_1.parsePercent)(brush.Strt), brightness: (0, descriptor_1.parsePercent)(brush.Brgh), purity: (0, descriptor_1.parsePercent)(brush.purity), perTip: brush.colorDynamicsPerTip, }; } if (brush.usePaintDynamics) { b.transfer = { flowDynamics: parseDynamics(brush.prVr), opacityDynamics: parseDynamics(brush.opVr), wetnessDynamics: parseDynamics(brush.wtVr), mixDynamics: parseDynamics(brush.mxVr), }; } if (brush.useBrushPose) { b.brushPose = { overrideAngle: brush.overridePoseAngle, overrideTiltX: brush.overridePoseTiltX, overrideTiltY: brush.overridePoseTiltY, overridePressure: brush.overridePosePressure, pressure: (0, descriptor_1.parsePercent)(brush.brushPosePressure), tiltX: brush.brushPoseTiltX, tiltY: brush.brushPoseTiltY, angle: brush.brushPoseAngle, }; } var to = brush.toolOptions; if (to) { b.toolOptions = { type: toBrushType[to._classID] || 'brush', brushPreset: to.brushPreset, flow: (_a = to.flow) !== null && _a !== void 0 ? _a : 100, smooth: (_b = to.Smoo) !== null && _b !== void 0 ? _b : 0, mode: descriptor_1.BlnM.decode(to['Md '] || 'BlnM.Nrml'), opacity: (_c = to.Opct) !== null && _c !== void 0 ? _c : 100, smoothing: !!to.smoothing, smoothingValue: to.smoothingValue || 0, smoothingRadiusMode: !!to.smoothingRadiusMode, smoothingCatchup: !!to.smoothingCatchup, smoothingCatchupAtEnd: !!to.smoothingCatchupAtEnd, smoothingZoomCompensation: !!to.smoothingZoomCompensation, pressureSmoothing: !!to.pressureSmoothing, usePressureOverridesSize: !!to.usePressureOverridesSize, usePressureOverridesOpacity: !!to.usePressureOverridesOpacity, useLegacy: !!to.useLegacy, }; if (to.prVr) b.toolOptions.flowDynamics = parseDynamics(to.prVr); if (to.opVr) b.toolOptions.opacityDynamics = parseDynamics(to.opVr); if (to.szVr) b.toolOptions.sizeDynamics = parseDynamics(to.szVr); if ('wetness' in to) b.toolOptions.wetness = to.wetness; if ('dryness' in to) b.toolOptions.dryness = to.dryness; if ('mix' in to) b.toolOptions.mix = to.mix; if ('autoFill' in to) b.toolOptions.autoFill = to.autoFill; if ('autoClean' in to) b.toolOptions.autoClean = to.autoClean; if ('loadSolidColorOnly' in to) b.toolOptions.loadSolidColorOnly = to.loadSolidColorOnly; if ('sampleAllLayers' in to) b.toolOptions.sampleAllLayers = to.sampleAllLayers; if ('SmdF' in to) b.toolOptions.smudgeFingerPainting = to.SmdF; if ('SmdS' in to) b.toolOptions.smudgeSampleAllLayers = to.SmdS; if ('Prs ' in to) b.toolOptions.strength = to['Prs ']; if ('SmdF' in to) b.toolOptions.smudgeFingerPainting = to.SmdF; if ('SmdS' in to) b.toolOptions.smudgeSampleAllLayers = to.SmdS; } brushes.push(b); } break; } case 'patt': { if (reader.offset < end) { // TODO: check multiple patterns patterns.push((0, psdReader_1.readPattern)(reader)); reader.offset = end; } break; } case 'phry': { // TODO: what is this ? var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); if (options.logMissingFeatures) { if ((_d = desc.hierarchy) === null || _d === void 0 ? void 0 : _d.length) { console.log('unhandled phry section', desc); } } break; } default: throw new Error("Invalid brush type: ".concat(type)); } // align to 4 bytes while (size % 4) { reader.offset++; size++; } } } else { throw new Error("Unsupported ABR version (".concat(version, ")")); } return { samples: samples, patterns: patterns, brushes: brushes }; } exports.readAbr = readAbr; },{"./descriptor":4,"./psdReader":12}],2:[function(require,module,exports){ "use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.hasMultiEffects = exports.readVectorMask = exports.booleanOperations = exports.readBezierKnot = exports.infoHandlersMap = exports.infoHandlers = void 0; var base64_js_1 = require("base64-js"); var effectsHelpers_1 = require("./effectsHelpers"); var helpers_1 = require("./helpers"); var psdReader_1 = require("./psdReader"); var psdWriter_1 = require("./psdWriter"); var descriptor_1 = require("./descriptor"); var engineData_1 = require("./engineData"); var text_1 = require("./text"); var engineData2_1 = require("./engineData2"); var fromAtoZ = 'abcdefghijklmnopqrstuvwxyz'; exports.infoHandlers = []; exports.infoHandlersMap = {}; function addHandler(key, has, read, write) { var handler = { key: key, has: has, read: read, write: write }; exports.infoHandlers.push(handler); exports.infoHandlersMap[handler.key] = handler; } function addHandlerAlias(key, target) { exports.infoHandlersMap[key] = exports.infoHandlersMap[target]; } function hasKey(key) { return function (target) { return target[key] !== undefined; }; } function readLength64(reader) { if ((0, psdReader_1.readUint32)(reader)) throw new Error("Resource size above 4 GB limit at ".concat(reader.offset.toString(16))); return (0, psdReader_1.readUint32)(reader); } function writeLength64(writer, length) { (0, psdWriter_1.writeUint32)(writer, 0); (0, psdWriter_1.writeUint32)(writer, length); } addHandler('TySh', hasKey('text'), function (reader, target, leftBytes) { if ((0, psdReader_1.readInt16)(reader) !== 1) throw new Error("Invalid TySh version"); var transform = []; for (var i = 0; i < 6; i++) transform.push((0, psdReader_1.readFloat64)(reader)); if ((0, psdReader_1.readInt16)(reader) !== 50) throw new Error("Invalid TySh text version"); var text = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log(require('util').inspect(text, false, 99, false), 'utf8'); if ((0, psdReader_1.readInt16)(reader) !== 1) throw new Error("Invalid TySh warp version"); var warp = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log(require('util').inspect(warp, false, 99, false), 'utf8'); target.text = { transform: transform, left: (0, psdReader_1.readFloat32)(reader), top: (0, psdReader_1.readFloat32)(reader), right: (0, psdReader_1.readFloat32)(reader), bottom: (0, psdReader_1.readFloat32)(reader), text: text['Txt '].replace(/\r/g, '\n'), index: text.TextIndex || 0, gridding: descriptor_1.textGridding.decode(text.textGridding), antiAlias: descriptor_1.Annt.decode(text.AntA), orientation: descriptor_1.Ornt.decode(text.Ornt), warp: { style: descriptor_1.warpStyle.decode(warp.warpStyle), value: warp.warpValue || 0, perspective: warp.warpPerspective || 0, perspectiveOther: warp.warpPerspectiveOther || 0, rotate: descriptor_1.Ornt.decode(warp.warpRotate), }, }; if (text.bounds) target.text.bounds = (0, descriptor_1.descBoundsToBounds)(text.bounds); if (text.boundingBox) target.text.boundingBox = (0, descriptor_1.descBoundsToBounds)(text.boundingBox); if (text.EngineData) { var engineData = (0, engineData_1.parseEngineData)(text.EngineData); var textData = (0, text_1.decodeEngineData)(engineData); // console.log(require('util').inspect(engineData, false, 99, false), 'utf8'); // require('fs').writeFileSync(`layer-${target.name}.txt`, require('util').inspect(engineData, false, 99, false), 'utf8'); // const before = parseEngineData(text.EngineData); // const after = encodeEngineData(engineData); // require('fs').writeFileSync('before.txt', require('util').inspect(before, false, 99, false), 'utf8'); // require('fs').writeFileSync('after.txt', require('util').inspect(after, false, 99, false), 'utf8'); // console.log(require('util').inspect(parseEngineData(text.EngineData), false, 99, true)); target.text = __assign(__assign({}, target.text), textData); // console.log(require('util').inspect(target.text, false, 99, true)); } (0, psdReader_1.skipBytes)(reader, leftBytes()); }, function (writer, target) { var text = target.text; var warp = text.warp || {}; var transform = text.transform || [1, 0, 0, 1, 0, 0]; var textDescriptor = __assign(__assign(__assign({ 'Txt ': (text.text || '').replace(/\r?\n/g, '\r'), textGridding: descriptor_1.textGridding.encode(text.gridding), Ornt: descriptor_1.Ornt.encode(text.orientation), AntA: descriptor_1.Annt.encode(text.antiAlias) }, (text.bounds ? { bounds: (0, descriptor_1.boundsToDescBounds)(text.bounds) } : {})), (text.boundingBox ? { boundingBox: (0, descriptor_1.boundsToDescBounds)(text.boundingBox) } : {})), { TextIndex: text.index || 0, EngineData: (0, engineData_1.serializeEngineData)((0, text_1.encodeEngineData)(text)) }); (0, psdWriter_1.writeInt16)(writer, 1); // version for (var i = 0; i < 6; i++) { (0, psdWriter_1.writeFloat64)(writer, transform[i]); } (0, psdWriter_1.writeInt16)(writer, 50); // text version (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'TxLr', textDescriptor, 'text'); (0, psdWriter_1.writeInt16)(writer, 1); // warp version (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'warp', encodeWarp(warp)); (0, psdWriter_1.writeFloat32)(writer, text.left); (0, psdWriter_1.writeFloat32)(writer, text.top); (0, psdWriter_1.writeFloat32)(writer, text.right); (0, psdWriter_1.writeFloat32)(writer, text.bottom); // writeZeros(writer, 2); }); // vector fills addHandler('SoCo', function (target) { return target.vectorFill !== undefined && target.vectorStroke === undefined && target.vectorFill.type === 'color'; }, function (reader, target) { var descriptor = (0, descriptor_1.readVersionAndDescriptor)(reader); target.vectorFill = (0, descriptor_1.parseVectorContent)(descriptor); }, function (writer, target) { var descriptor = (0, descriptor_1.serializeVectorContent)(target.vectorFill).descriptor; (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', descriptor); }); addHandler('GdFl', function (target) { return target.vectorFill !== undefined && target.vectorStroke === undefined && (target.vectorFill.type === 'solid' || target.vectorFill.type === 'noise'); }, function (reader, target, left) { var descriptor = (0, descriptor_1.readVersionAndDescriptor)(reader); target.vectorFill = (0, descriptor_1.parseVectorContent)(descriptor); (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target) { var descriptor = (0, descriptor_1.serializeVectorContent)(target.vectorFill).descriptor; (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', descriptor); }); addHandler('PtFl', function (target) { return target.vectorFill !== undefined && target.vectorStroke === undefined && target.vectorFill.type === 'pattern'; }, function (reader, target) { var descriptor = (0, descriptor_1.readVersionAndDescriptor)(reader); target.vectorFill = (0, descriptor_1.parseVectorContent)(descriptor); }, function (writer, target) { var descriptor = (0, descriptor_1.serializeVectorContent)(target.vectorFill).descriptor; (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', descriptor); }); addHandler('vscg', function (target) { return target.vectorFill !== undefined && target.vectorStroke !== undefined; }, function (reader, target, left) { (0, psdReader_1.readSignature)(reader); // key var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); target.vectorFill = (0, descriptor_1.parseVectorContent)(desc); (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target) { var _a = (0, descriptor_1.serializeVectorContent)(target.vectorFill), descriptor = _a.descriptor, key = _a.key; (0, psdWriter_1.writeSignature)(writer, key); (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', descriptor); }); function readBezierKnot(reader, width, height) { var y0 = (0, psdReader_1.readFixedPointPath32)(reader) * height; var x0 = (0, psdReader_1.readFixedPointPath32)(reader) * width; var y1 = (0, psdReader_1.readFixedPointPath32)(reader) * height; var x1 = (0, psdReader_1.readFixedPointPath32)(reader) * width; var y2 = (0, psdReader_1.readFixedPointPath32)(reader) * height; var x2 = (0, psdReader_1.readFixedPointPath32)(reader) * width; return [x0, y0, x1, y1, x2, y2]; } exports.readBezierKnot = readBezierKnot; function writeBezierKnot(writer, points, width, height) { (0, psdWriter_1.writeFixedPointPath32)(writer, points[1] / height); // y0 (0, psdWriter_1.writeFixedPointPath32)(writer, points[0] / width); // x0 (0, psdWriter_1.writeFixedPointPath32)(writer, points[3] / height); // y1 (0, psdWriter_1.writeFixedPointPath32)(writer, points[2] / width); // x1 (0, psdWriter_1.writeFixedPointPath32)(writer, points[5] / height); // y2 (0, psdWriter_1.writeFixedPointPath32)(writer, points[4] / width); // x2 } exports.booleanOperations = ['exclude', 'combine', 'subtract', 'intersect']; function readVectorMask(reader, vectorMask, width, height, size) { var end = reader.offset + size; var paths = vectorMask.paths; var path = undefined; while ((end - reader.offset) >= 26) { var selector = (0, psdReader_1.readUint16)(reader); switch (selector) { case 0: // Closed subpath length record case 3: { // Open subpath length record (0, psdReader_1.readUint16)(reader); // count var boolOp = (0, psdReader_1.readInt16)(reader); var flags = (0, psdReader_1.readUint16)(reader); // bit 1 always 1 ? (0, psdReader_1.skipBytes)(reader, 18); path = { open: selector === 3, knots: [], fillRule: flags === 2 ? 'non-zero' : 'even-odd', }; if (boolOp !== -1) path.operation = exports.booleanOperations[boolOp]; paths.push(path); break; } case 1: // Closed subpath Bezier knot, linked case 2: // Closed subpath Bezier knot, unlinked case 4: // Open subpath Bezier knot, linked case 5: // Open subpath Bezier knot, unlinked path.knots.push({ linked: (selector === 1 || selector === 4), points: readBezierKnot(reader, width, height) }); break; case 6: // Path fill rule record (0, psdReader_1.skipBytes)(reader, 24); break; case 7: { // Clipboard record // TODO: check if these need to be multiplied by document size var top_1 = (0, psdReader_1.readFixedPointPath32)(reader); var left = (0, psdReader_1.readFixedPointPath32)(reader); var bottom = (0, psdReader_1.readFixedPointPath32)(reader); var right = (0, psdReader_1.readFixedPointPath32)(reader); var resolution = (0, psdReader_1.readFixedPointPath32)(reader); (0, psdReader_1.skipBytes)(reader, 4); vectorMask.clipboard = { top: top_1, left: left, bottom: bottom, right: right, resolution: resolution }; break; } case 8: // Initial fill rule record vectorMask.fillStartsWithAllPixels = !!(0, psdReader_1.readUint16)(reader); (0, psdReader_1.skipBytes)(reader, 22); break; default: throw new Error('Invalid vmsk section'); } } return paths; } exports.readVectorMask = readVectorMask; addHandler('vmsk', hasKey('vectorMask'), function (reader, target, left, _a) { var width = _a.width, height = _a.height; if ((0, psdReader_1.readUint32)(reader) !== 3) throw new Error('Invalid vmsk version'); target.vectorMask = { paths: [] }; var vectorMask = target.vectorMask; var flags = (0, psdReader_1.readUint32)(reader); vectorMask.invert = (flags & 1) !== 0; vectorMask.notLink = (flags & 2) !== 0; vectorMask.disable = (flags & 4) !== 0; readVectorMask(reader, vectorMask, width, height, left()); // drawBezierPaths(vectorMask.paths, width, height, 'out.png'); (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target, _a) { var width = _a.width, height = _a.height; var vectorMask = target.vectorMask; var flags = (vectorMask.invert ? 1 : 0) | (vectorMask.notLink ? 2 : 0) | (vectorMask.disable ? 4 : 0); (0, psdWriter_1.writeUint32)(writer, 3); // version (0, psdWriter_1.writeUint32)(writer, flags); // initial entry (0, psdWriter_1.writeUint16)(writer, 6); (0, psdWriter_1.writeZeros)(writer, 24); var clipboard = vectorMask.clipboard; if (clipboard) { (0, psdWriter_1.writeUint16)(writer, 7); (0, psdWriter_1.writeFixedPointPath32)(writer, clipboard.top); (0, psdWriter_1.writeFixedPointPath32)(writer, clipboard.left); (0, psdWriter_1.writeFixedPointPath32)(writer, clipboard.bottom); (0, psdWriter_1.writeFixedPointPath32)(writer, clipboard.right); (0, psdWriter_1.writeFixedPointPath32)(writer, clipboard.resolution); (0, psdWriter_1.writeZeros)(writer, 4); } if (vectorMask.fillStartsWithAllPixels !== undefined) { (0, psdWriter_1.writeUint16)(writer, 8); (0, psdWriter_1.writeUint16)(writer, vectorMask.fillStartsWithAllPixels ? 1 : 0); (0, psdWriter_1.writeZeros)(writer, 22); } for (var _i = 0, _b = vectorMask.paths; _i < _b.length; _i++) { var path = _b[_i]; (0, psdWriter_1.writeUint16)(writer, path.open ? 3 : 0); (0, psdWriter_1.writeUint16)(writer, path.knots.length); (0, psdWriter_1.writeUint16)(writer, path.operation ? exports.booleanOperations.indexOf(path.operation) : -1); // -1 for undefined (0, psdWriter_1.writeUint16)(writer, path.fillRule === 'non-zero' ? 2 : 1); (0, psdWriter_1.writeZeros)(writer, 18); // TODO: these are sometimes non-zero var linkedKnot = path.open ? 4 : 1; var unlinkedKnot = path.open ? 5 : 2; for (var _c = 0, _d = path.knots; _c < _d.length; _c++) { var _e = _d[_c], linked = _e.linked, points = _e.points; (0, psdWriter_1.writeUint16)(writer, linked ? linkedKnot : unlinkedKnot); writeBezierKnot(writer, points, width, height); } } }); // TODO: need to write vmsk if has outline ? addHandlerAlias('vsms', 'vmsk'); // addHandlerAlias('vmsk', 'vsms'); addHandler('vowv', // something with vectors? hasKey('vowv'), function (reader, target) { target.vowv = (0, psdReader_1.readUint32)(reader); // always 2 ???? }, function (writer, target) { (0, psdWriter_1.writeUint32)(writer, target.vowv); }); addHandler('vogk', hasKey('vectorOrigination'), function (reader, target, left) { if ((0, psdReader_1.readInt32)(reader) !== 1) throw new Error("Invalid vogk version"); var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log(require('util').inspect(desc, false, 99, true)); target.vectorOrigination = { keyDescriptorList: [] }; for (var _i = 0, _a = desc.keyDescriptorList; _i < _a.length; _i++) { var i = _a[_i]; var item = {}; if (i.keyShapeInvalidated != null) item.keyShapeInvalidated = i.keyShapeInvalidated; if (i.keyOriginType != null) item.keyOriginType = i.keyOriginType; if (i.keyOriginResolution != null) item.keyOriginResolution = i.keyOriginResolution; if (i.keyOriginShapeBBox) { item.keyOriginShapeBoundingBox = { top: (0, descriptor_1.parseUnitsOrNumber)(i.keyOriginShapeBBox['Top ']), left: (0, descriptor_1.parseUnitsOrNumber)(i.keyOriginShapeBBox.Left), bottom: (0, descriptor_1.parseUnitsOrNumber)(i.keyOriginShapeBBox.Btom), right: (0, descriptor_1.parseUnitsOrNumber)(i.keyOriginShapeBBox.Rght), }; } var rectRadii = i.keyOriginRRectRadii; if (rectRadii) { item.keyOriginRRectRadii = { topRight: (0, descriptor_1.parseUnits)(rectRadii.topRight), topLeft: (0, descriptor_1.parseUnits)(rectRadii.topLeft), bottomLeft: (0, descriptor_1.parseUnits)(rectRadii.bottomLeft), bottomRight: (0, descriptor_1.parseUnits)(rectRadii.bottomRight), }; } var corners = i.keyOriginBoxCorners; if (corners) { item.keyOriginBoxCorners = [ { x: corners.rectangleCornerA.Hrzn, y: corners.rectangleCornerA.Vrtc }, { x: corners.rectangleCornerB.Hrzn, y: corners.rectangleCornerB.Vrtc }, { x: corners.rectangleCornerC.Hrzn, y: corners.rectangleCornerC.Vrtc }, { x: corners.rectangleCornerD.Hrzn, y: corners.rectangleCornerD.Vrtc }, ]; } var trnf = i.Trnf; if (trnf) { item.transform = [trnf.xx, trnf.xy, trnf.xy, trnf.yy, trnf.tx, trnf.ty]; } target.vectorOrigination.keyDescriptorList.push(item); } (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target) { target; var orig = target.vectorOrigination; var desc = { keyDescriptorList: [] }; for (var i = 0; i < orig.keyDescriptorList.length; i++) { var item = orig.keyDescriptorList[i]; desc.keyDescriptorList.push({}); // we're adding keyOriginIndex at the end var out = desc.keyDescriptorList[desc.keyDescriptorList.length - 1]; if (item.keyOriginType != null) out.keyOriginType = item.keyOriginType; if (item.keyOriginResolution != null) out.keyOriginResolution = item.keyOriginResolution; var radii = item.keyOriginRRectRadii; if (radii) { out.keyOriginRRectRadii = { unitValueQuadVersion: 1, topRight: (0, descriptor_1.unitsValue)(radii.topRight, 'topRight'), topLeft: (0, descriptor_1.unitsValue)(radii.topLeft, 'topLeft'), bottomLeft: (0, descriptor_1.unitsValue)(radii.bottomLeft, 'bottomLeft'), bottomRight: (0, descriptor_1.unitsValue)(radii.bottomRight, 'bottomRight'), }; } var box = item.keyOriginShapeBoundingBox; if (box) { out.keyOriginShapeBBox = { unitValueQuadVersion: 1, 'Top ': (0, descriptor_1.unitsValue)(box.top, 'top'), Left: (0, descriptor_1.unitsValue)(box.left, 'left'), Btom: (0, descriptor_1.unitsValue)(box.bottom, 'bottom'), Rght: (0, descriptor_1.unitsValue)(box.right, 'right'), }; } var corners = item.keyOriginBoxCorners; if (corners && corners.length === 4) { out.keyOriginBoxCorners = { rectangleCornerA: { Hrzn: corners[0].x, Vrtc: corners[0].y }, rectangleCornerB: { Hrzn: corners[1].x, Vrtc: corners[1].y }, rectangleCornerC: { Hrzn: corners[2].x, Vrtc: corners[2].y }, rectangleCornerD: { Hrzn: corners[3].x, Vrtc: corners[3].y }, }; } var transform = item.transform; if (transform && transform.length === 6) { out.Trnf = { xx: transform[0], xy: transform[1], yx: transform[2], yy: transform[3], tx: transform[4], ty: transform[5], }; } if (item.keyShapeInvalidated != null) out.keyShapeInvalidated = item.keyShapeInvalidated; out.keyOriginIndex = i; } (0, psdWriter_1.writeInt32)(writer, 1); // version (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc); }); addHandler('lmfx', function (target) { return target.effects !== undefined && hasMultiEffects(target.effects); }, function (reader, target, left) { var version = (0, psdReader_1.readUint32)(reader); if (version !== 0) throw new Error('Invalid lmfx version'); var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log('READ', require('util').inspect(desc, false, 99, true)); // discard if read in 'lrFX' or 'lfx2' section target.effects = (0, descriptor_1.parseEffects)(desc, !!reader.logMissingFeatures); (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target, _, options) { var desc = (0, descriptor_1.serializeEffects)(target.effects, !!options.logMissingFeatures, true); // console.log('WRITE', require('util').inspect(desc, false, 99, true)); (0, psdWriter_1.writeUint32)(writer, 0); // version (0, descriptor_1.writeVersionAndDescriptor)(writer, '', 'null', desc); }); addHandler('lrFX', hasKey('effects'), function (reader, target, left) { if (!target.effects) target.effects = (0, effectsHelpers_1.readEffects)(reader); (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target) { (0, effectsHelpers_1.writeEffects)(writer, target.effects); }); addHandler('luni', hasKey('name'), function (reader, target, left) { if (left() > 4) { var length_1 = (0, psdReader_1.readUint32)(reader); if (left() >= (length_1 * 2)) { target.name = (0, psdReader_1.readUnicodeStringWithLength)(reader, length_1); } else { if (reader.logDevFeatures) reader.log('name in luni section is too long'); } } else { if (reader.logDevFeatures) reader.log('empty luni section'); } (0, psdReader_1.skipBytes)(reader, left()); }, function (writer, target) { (0, psdWriter_1.writeUnicodeString)(writer, target.name); // writeUint16(writer, 0); // padding (but not extending string length) }); addHandler('lnsr', hasKey('nameSource'), function (reader, target) { return target.nameSource = (0, psdReader_1.readSignature)(reader); }, function (writer, target) { return (0, psdWriter_1.writeSignature)(writer, target.nameSource); }); addHandler('lyid', hasKey('id'), function (reader, target) { target.id = (0, psdReader_1.readUint32)(reader); }, function (writer, target, _psd, options) { var id = target.id; while (options.layerIds.has(id)) id += 100; // make sure we don't have duplicate layer ids (0, psdWriter_1.writeUint32)(writer, id); options.layerIds.add(id); options.layerToId.set(target, id); }); addHandler('lsct', hasKey('sectionDivider'), function (reader, target, left) { target.sectionDivider = { type: (0, psdReader_1.readUint32)(reader) }; if (left()) { (0, psdReader_1.checkSignature)(reader, '8BIM'); target.sectionDivider.key = (0, psdReader_1.readSignature)(reader); } if (left()) { target.sectionDivider.subType = (0, psdReader_1.readUint32)(reader); } }, function (writer, target) { (0, psdWriter_1.writeUint32)(writer, target.sectionDivider.type); if (target.sectionDivider.key) { (0, psdWriter_1.writeSignature)(writer, '8BIM'); (0, psdWriter_1.writeSignature)(writer, target.sectionDivider.key); if (target.sectionDivider.subType !== undefined) { (0, psdWriter_1.writeUint32)(writer, target.sectionDivider.subType); } } }); // it seems lsdk is used when there's a layer is nested more than 6 levels, but I don't know why? // maybe some limitation of old version of PS? addHandlerAlias('lsdk', 'lsct'); addHandler('clbl', hasKey('blendClippendElements'), function (reader, target) { target.blendClippendElements = !!(0, psdReader_1.readUint8)(reader); (0, psdReader_1.skipBytes)(reader, 3); }, function (writer, target) { (0, psdWriter_1.writeUint8)(writer, target.blendClippendElements ? 1 : 0); (0, psdWriter_1.writeZeros)(writer, 3); }); addHandler('infx', hasKey('blendInteriorElements'), function (reader, target) { target.blendInteriorElements = !!(0, psdReader_1.readUint8)(reader); (0, psdReader_1.skipBytes)(reader, 3); }, function (writer, target) { (0, psdWriter_1.writeUint8)(writer, target.blendInteriorElements ? 1 : 0); (0, psdWriter_1.writeZeros)(writer, 3); }); addHandler('knko', hasKey('knockout'), function (reader, target) { target.knockout = !!(0, psdReader_1.readUint8)(reader); (0, psdReader_1.skipBytes)(reader, 3); }, function (writer, target) { (0, psdWriter_1.writeUint8)(writer, target.knockout ? 1 : 0); (0, psdWriter_1.writeZeros)(writer, 3); }); addHandler('lmgm', hasKey('layerMaskAsGlobalMask'), function (reader, target) { target.layerMaskAsGlobalMask = !!(0, psdReader_1.readUint8)(reader); (0, psdReader_1.skipBytes)(reader, 3); }, function (writer, target) { (0, psdWriter_1.writeUint8)(writer, target.layerMaskAsGlobalMask ? 1 : 0); (0, psdWriter_1.writeZeros)(writer, 3); }); addHandler('lspf', hasKey('protected'), function (reader, target) { var flags = (0, psdReader_1.readUint32)(reader); target.protected = { transparency: (flags & 0x01) !== 0, composite: (flags & 0x02) !== 0, position: (flags & 0x04) !== 0, }; if (flags & 0x08) target.protected.artboards = true; }, function (writer, target) { var flags = (target.protected.transparency ? 0x01 : 0) | (target.protected.composite ? 0x02 : 0) | (target.protected.position ? 0x04 : 0) | (target.protected.artboards ? 0x08 : 0); (0, psdWriter_1.writeUint32)(writer, flags); }); addHandler('lclr', hasKey('layerColor'), function (reader, target) { var color = (0, psdReader_1.readUint16)(reader); (0, psdReader_1.skipBytes)(reader, 6); target.layerColor = helpers_1.layerColors[color]; }, function (writer, target) { var index = helpers_1.layerColors.indexOf(target.layerColor); (0, psdWriter_1.writeUint16)(writer, index === -1 ? 0 : index); (0, psdWriter_1.writeZeros)(writer, 6); }); addHandler('shmd', // Metadata setting function (// Metadata setting target) { return target.timestamp !== undefined || target.animationFrames !== undefined || target.animationFrameFlags !== undefined || target.timeline !== undefined || target.comps !== undefined; }, function (reader, target, left) { var count = (0, psdReader_1.readUint32)(reader); var _loop_1 = function (i) { (0, psdReader_1.checkSignature)(reader, '8BIM'); var key = (0, psdReader_1.readSignature)(reader); (0, psdReader_1.readUint8)(reader); // copy (0, psdReader_1.skipBytes)(reader, 3); (0, psdReader_1.readSection)(reader, 1, function (left) { if (key === 'cust') { var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log('cust', target.name, require('util').inspect(desc, false, 99, true)); if (desc.layerTime !== undefined) target.timestamp = desc.layerTime; } else if (key === 'mlst') { var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log('mlst', target.name, require('util').inspect(desc, false, 99, true)); target.animationFrames = []; for (var i_1 = 0; i_1 < desc.LaSt.length; i_1++) { var f = desc.LaSt[i_1]; var frame = { frames: f.FrLs }; if (f.enab !== undefined) frame.enable = f.enab; if (f.Ofst) frame.offset = (0, descriptor_1.horzVrtcToXY)(f.Ofst); if (f.FXRf) frame.referencePoint = (0, descriptor_1.horzVrtcToXY)(f.FXRf); if (f.Lefx) frame.effects = (0, descriptor_1.parseEffects)(f.Lefx, !!reader.logMissingFeatures); if (f.blendOptions && f.blendOptions.Opct) frame.opacity = (0, descriptor_1.parsePercent)(f.blendOptions.Opct); target.animationFrames.push(frame); } } else if (key === 'mdyn') { // frame flags (0, psdReader_1.readUint16)(reader); // unknown var propagate = (0, psdReader_1.readUint8)(reader); var flags = (0, psdReader_1.readUint8)(reader); target.animationFrameFlags = { propagateFrameOne: !propagate, unifyLayerPosition: (flags & 1) !== 0, unifyLayerStyle: (flags & 2) !== 0, unifyLayerVisibility: (flags & 4) !== 0, }; } else if (key === 'tmln') { var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); var timeScope = desc.timeScope; // console.log('tmln', target.name, target.id, require('util').inspect(desc, false, 99, true)); var timeline = { start: (0, descriptor_1.frac)(timeScope.Strt), duration: (0, descriptor_1.frac)(timeScope.duration), inTime: (0, descriptor_1.frac)(timeScope.inTime), outTime: (0, descriptor_1.frac)(timeScope.outTime), autoScope: desc.autoScope, audioLevel: desc.audioLevel, }; if (desc.trackList) { timeline.tracks = (0, descriptor_1.parseTrackList)(desc.trackList, !!reader.logMissingFeatures); } target.timeline = timeline; // console.log('tmln:result', target.name, target.id, require('util').inspect(timeline, false, 99, true)); } else if (key === 'cmls') { var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log('cmls', require('util').inspect(desc, false, 99, true)); target.comps = { settings: [], }; if (desc.origFXRefPoint) target.comps.originalEffectsReferencePoint = { x: desc.origFXRefPoint.Hrzn, y: desc.origFXRefPoint.Vrtc }; for (var _i = 0, _a = desc.layerSettings; _i < _a.length; _i++) { var item = _a[_i]; target.comps.settings.push({ compList: item.compList }); var t = target.comps.settings[target.comps.settings.length - 1]; if ('enab' in item) t.enabled = item.enab; if (item.Ofst) t.offset = { x: item.Ofst.Hrzn, y: item.Ofst.Vrtc }; if (item.FXRefPoint) t.effectsReferencePoint = { x: item.FXRefPoint.Hrzn, y: item.FXRefPoint.Vrtc }; } } else if (key === 'extn') { var desc = (0, descriptor_1.readVersionAndDescriptor)(reader); // console.log(require('util').inspect(desc, false, 99, true)); desc; // TODO: save this reader.logMissingFeatures && reader.log('Unhandled "shmd" section key', key); } else { reader.logMissingFeatures && reader