支持 mac

This commit is contained in:
onvia
2023-07-24 11:13:08 +08:00
parent 413e79966a
commit 516a7f20c1
1940 changed files with 693119 additions and 1178 deletions

View File

@@ -0,0 +1,132 @@
import { BlendMode, PatternInfo } from './psd';
export interface Abr {
brushes: Brush[];
samples: SampleInfo[];
patterns: PatternInfo[];
}
export interface SampleInfo {
id: string;
bounds: {
x: number;
y: number;
w: number;
h: number;
};
alpha: Uint8Array;
}
export interface BrushDynamics {
control: 'off' | 'fade' | 'pen pressure' | 'pen tilt' | 'stylus wheel' | 'initial direction' | 'direction' | 'initial rotation' | 'rotation';
steps: number;
jitter: number;
minimum: number;
}
export interface BrushShape {
name?: string;
size: number;
angle: number;
roundness: number;
hardness?: number;
spacingOn: boolean;
spacing: number;
flipX: boolean;
flipY: boolean;
sampledData?: string;
}
export interface Brush {
name: string;
shape: BrushShape;
shapeDynamics?: {
sizeDynamics: BrushDynamics;
minimumDiameter: number;
tiltScale: number;
angleDynamics: BrushDynamics;
roundnessDynamics: BrushDynamics;
minimumRoundness: number;
flipX: boolean;
flipY: boolean;
brushProjection: boolean;
};
scatter?: {
bothAxes: boolean;
scatterDynamics: BrushDynamics;
countDynamics: BrushDynamics;
count: number;
};
texture?: {
id: string;
name: string;
invert: boolean;
scale: number;
brightness: number;
contrast: number;
blendMode: BlendMode;
depth: number;
depthMinimum: number;
depthDynamics: BrushDynamics;
};
dualBrush?: {
flip: boolean;
shape: BrushShape;
blendMode: BlendMode;
useScatter: boolean;
spacing: number;
count: number;
bothAxes: boolean;
countDynamics: BrushDynamics;
scatterDynamics: BrushDynamics;
};
colorDynamics?: {
foregroundBackground: BrushDynamics;
hue: number;
saturation: number;
brightness: number;
purity: number;
perTip: boolean;
};
transfer?: {
flowDynamics: BrushDynamics;
opacityDynamics: BrushDynamics;
wetnessDynamics: BrushDynamics;
mixDynamics: BrushDynamics;
};
brushPose?: {
overrideAngle: boolean;
overrideTiltX: boolean;
overrideTiltY: boolean;
overridePressure: boolean;
pressure: number;
tiltX: number;
tiltY: number;
angle: number;
};
noise: boolean;
wetEdges: boolean;
protectTexture?: boolean;
spacing: number;
brushGroup?: undefined;
interpretation?: boolean;
useBrushSize: boolean;
toolOptions?: {
brushPreset: boolean;
flow: number;
smooth: number;
mode: BlendMode;
opacity: number;
smoothing: boolean;
smoothingValue: number;
smoothingRadiusMode: boolean;
smoothingCatchup: boolean;
smoothingCatchupAtEnd: boolean;
smoothingZoomCompensation: boolean;
pressureSmoothing: boolean;
usePressureOverridesSize: boolean;
usePressureOverridesOpacity: boolean;
useLegacy: boolean;
flowDynamics?: BrushDynamics;
opacityDynamics?: BrushDynamics;
sizeDynamics?: BrushDynamics;
};
}
export declare function readAbr(buffer: ArrayBufferView, options?: {
logMissingFeatures?: boolean;
}): Abr;

View File

@@ -0,0 +1,266 @@
import { BlnM, parseAngle, parsePercent, parseUnitsToNumber, readVersionAndDescriptor } from './descriptor';
import { checkSignature, createReader, readBytes, readDataRLE, readInt16, readInt32, readPascalString, readPattern, readSignature, readUint16, readUint32, readUint8, skipBytes } from './psdReader';
var dynamicsControl = ['off', 'fade', 'pen pressure', 'pen tilt', 'stylus wheel', 'initial direction', 'direction', 'initial rotation', 'rotation'];
function parseDynamics(desc) {
return {
control: dynamicsControl[desc.bVTy],
steps: desc.fStp,
jitter: parsePercent(desc.jitter),
minimum: parsePercent(desc['Mnm ']),
};
}
function parseBrushShape(desc) {
var shape = {
size: parseUnitsToNumber(desc.Dmtr, 'Pixels'),
angle: parseAngle(desc.Angl),
roundness: parsePercent(desc.Rndn),
spacingOn: desc.Intr,
spacing: parsePercent(desc.Spcn),
flipX: desc.flipX,
flipY: desc.flipY,
};
if (desc['Nm '])
shape.name = desc['Nm '];
if (desc.Hrdn)
shape.hardness = parsePercent(desc.Hrdn);
if (desc.sampledData)
shape.sampledData = desc.sampledData;
return shape;
}
export function readAbr(buffer, options) {
var _a, _b, _c, _d;
if (options === void 0) { options = {}; }
var reader = createReader(buffer.buffer, buffer.byteOffset, buffer.byteLength);
var version = 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 = readInt16(reader);
if (minorVersion !== 1 && minorVersion !== 2)
throw new Error('Unsupported ABR minor version');
while (reader.offset < reader.view.byteLength) {
checkSignature(reader, '8BIM');
var type = readSignature(reader);
var size = readUint32(reader);
var end = reader.offset + size;
switch (type) {
case 'samp': {
while (reader.offset < end) {
var brushLength = readUint32(reader);
while (brushLength & 3)
brushLength++; // pad to 4 byte alignment
var brushEnd = reader.offset + brushLength;
var id = readPascalString(reader, 1);
// v1 - Skip the Int16 bounds rectangle and the unknown Int16.
// v2 - Skip the unknown bytes.
skipBytes(reader, minorVersion === 1 ? 10 : 264);
var y = readInt32(reader);
var x = readInt32(reader);
var h = readInt32(reader) - y;
var w = readInt32(reader) - x;
if (w <= 0 || h <= 0)
throw new Error('Invalid bounds');
var depth = readInt16(reader);
var compression = readUint8(reader); // 0 - raw, 1 - RLE
var alpha = new Uint8Array(w * h);
if (depth === 8) {
if (compression === 0) {
alpha.set(readBytes(reader, alpha.byteLength));
}
else if (compression === 1) {
readDataRLE(reader, { width: w, height: h, data: alpha }, w, h, 1, [0], false);
}
else {
throw new Error('Invalid compression');
}
}
else if (depth === 16) {
if (compression === 0) {
for (var i = 0; i < alpha.byteLength; i++) {
alpha[i] = 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 = readVersionAndDescriptor(reader);
// 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: 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: 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: parsePercent(brush.minimumDiameter),
minimumRoundness: 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: BlnM.decode(brush.textureBlendMode),
depth: parsePercent(brush.textureDepth),
depthMinimum: parsePercent(brush.minimumDepth),
depthDynamics: parseDynamics(brush.textureDepthDynamics),
scale: 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: BlnM.decode(db.BlnM),
useScatter: db.useScatter,
spacing: 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: parsePercent(brush['H ']),
saturation: parsePercent(brush.Strt),
brightness: parsePercent(brush.Brgh),
purity: 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: parsePercent(brush.brushPosePressure),
tiltX: brush.brushPoseTiltX,
tiltY: brush.brushPoseTiltY,
angle: brush.brushPoseAngle,
};
}
var to = brush.toolOptions;
if (to) {
b.toolOptions = {
brushPreset: to.brushPreset,
flow: (_a = to.flow) !== null && _a !== void 0 ? _a : 100,
smooth: (_b = to.Smoo) !== null && _b !== void 0 ? _b : 0,
mode: 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);
}
}
brushes.push(b);
}
break;
}
case 'patt': {
if (reader.offset < end) { // TODO: check multiple patterns
patterns.push(readPattern(reader));
reader.offset = end;
}
break;
}
case 'phry': {
// TODO: what is this ?
var desc = 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 };
}
//# sourceMappingURL=abr.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
import { LayerAdditionalInfo, BezierPath, Psd, ReadOptions, WriteOptions, BooleanOperation, LayerEffectsInfo, LayerVectorMask } from './psd';
import { PsdReader } from './psdReader';
import { PsdWriter } from './psdWriter';
export interface ExtendedWriteOptions extends WriteOptions {
layerIds: Set<number>;
layerToId: Map<any, number>;
}
type HasMethod = (target: LayerAdditionalInfo) => boolean;
type ReadMethod = (reader: PsdReader, target: LayerAdditionalInfo, left: () => number, psd: Psd, options: ReadOptions) => void;
type WriteMethod = (writer: PsdWriter, target: LayerAdditionalInfo, psd: Psd, options: ExtendedWriteOptions) => void;
export interface InfoHandler {
key: string;
has: HasMethod;
read: ReadMethod;
write: WriteMethod;
}
export declare const infoHandlers: InfoHandler[];
export declare const infoHandlersMap: {
[key: string]: InfoHandler;
};
export declare function readBezierKnot(reader: PsdReader, width: number, height: number): number[];
export declare const booleanOperations: BooleanOperation[];
export declare function readVectorMask(reader: PsdReader, vectorMask: LayerVectorMask, width: number, height: number, size: number): BezierPath[];
export declare function hasMultiEffects(effects: LayerEffectsInfo): boolean;
export {};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
import { LayerVectorMask } from './psd';
export interface Csh {
shapes: (LayerVectorMask & {
name: string;
id: string;
width: number;
height: number;
})[];
}
export declare function readCsh(buffer: ArrayBufferView): Csh;

View File

@@ -0,0 +1,44 @@
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);
};
import { readVectorMask } from './additionalInfo';
import { readUint32, checkSignature, createReader, readPascalString, readUnicodeString } from './psdReader';
export function readCsh(buffer) {
var reader = createReader(buffer.buffer, buffer.byteOffset, buffer.byteLength);
var csh = { shapes: [] };
checkSignature(reader, 'cush');
if (readUint32(reader) !== 2)
throw new Error('Invalid version');
var count = readUint32(reader);
for (var i = 0; i < count; i++) {
var name_1 = readUnicodeString(reader);
while (reader.offset % 4)
reader.offset++; // pad to 4byte bounds
if (readUint32(reader) !== 1)
throw new Error('Invalid shape version');
var size = readUint32(reader);
var end = reader.offset + size;
var id = readPascalString(reader, 1);
// this might not be correct ???
var y1 = readUint32(reader);
var x1 = readUint32(reader);
var y2 = readUint32(reader);
var x2 = readUint32(reader);
var width = x2 - x1;
var height = y2 - y1;
var mask = { paths: [] };
readVectorMask(reader, mask, width, height, end - reader.offset);
csh.shapes.push(__assign({ name: name_1, id: id, width: width, height: height }, mask));
reader.offset = end;
}
return csh;
}
//# sourceMappingURL=csh.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"csh.js","sourceRoot":"../src/","sources":["csh.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAW5G,MAAM,UAAU,OAAO,CAAC,MAAuB;IAC9C,IAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACjF,IAAM,GAAG,GAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IAEhC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACjE,IAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE;QAC/B,IAAM,MAAI,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,sBAAsB;QACjE,IAAI,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvE,IAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAChC,IAAM,GAAG,GAAG,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QACjC,IAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACvC,gCAAgC;QAChC,IAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAM,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC9B,IAAM,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC;QACtB,IAAM,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC;QACvB,IAAM,IAAI,GAAoB,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC5C,cAAc,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QACjE,GAAG,CAAC,MAAM,CAAC,IAAI,YAAG,IAAI,QAAA,EAAE,EAAE,IAAA,EAAE,KAAK,OAAA,EAAE,MAAM,QAAA,IAAK,IAAI,EAAG,CAAC;QAEtD,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;KACpB;IAED,OAAO,GAAG,CAAC;AACZ,CAAC"}

View File

@@ -0,0 +1,415 @@
import { AntiAlias, BevelDirection, BevelStyle, BevelTechnique, BlendMode, Color, GlowSource, GlowTechnique, GradientStyle, InterpolationMethod, LayerEffectsInfo, LineAlignment, LineCapType, LineJoinType, Orientation, TextGridding, TimelineKeyInterpolation, TimelineTrack, TimelineTrackType, Units, UnitsValue, VectorContent, WarpStyle } from './psd';
import { PsdReader } from './psdReader';
import { PsdWriter } from './psdWriter';
export declare function setLogErrors(value: boolean): void;
export declare function readAsciiStringOrClassId(reader: PsdReader): string;
export declare function readDescriptorStructure(reader: PsdReader): any;
export declare function writeDescriptorStructure(writer: PsdWriter, name: string, classId: string, value: any, root: string): void;
export declare function readVersionAndDescriptor(reader: PsdReader): any;
export declare function writeVersionAndDescriptor(writer: PsdWriter, name: string, classID: string, descriptor: any, root?: string): void;
export type DescriptorUnits = 'Angle' | 'Density' | 'Distance' | 'None' | 'Percent' | 'Pixels' | 'Millimeters' | 'Points' | 'Picas' | 'Inches' | 'Centimeters';
export interface DescriptorUnitsValue {
units: DescriptorUnits;
value: number;
}
export type DescriptorColor = {
'Rd ': number;
'Grn ': number;
'Bl ': number;
} | {
'H ': DescriptorUnitsValue;
Strt: number;
Brgh: number;
} | {
'Cyn ': number;
Mgnt: number;
'Ylw ': number;
Blck: number;
} | {
'Gry ': number;
} | {
Lmnc: number;
'A ': number;
'B ': number;
} | {
redFloat: number;
greenFloat: number;
blueFloat: number;
};
export interface DesciptorPattern {
'Nm ': string;
Idnt: string;
}
export type DesciptorGradient = {
'Nm ': string;
GrdF: 'GrdF.CstS';
Intr: number;
Clrs: {
'Clr ': DescriptorColor;
Type: 'Clry.UsrS';
Lctn: number;
Mdpn: number;
}[];
Trns: {
Opct: DescriptorUnitsValue;
Lctn: number;
Mdpn: number;
}[];
} | {
GrdF: 'GrdF.ClNs';
Smth: number;
'Nm ': string;
ClrS: string;
RndS: number;
VctC?: boolean;
ShTr?: boolean;
'Mnm ': number[];
'Mxm ': number[];
};
export interface DescriptorColorContent {
'Clr ': DescriptorColor;
}
export interface DescriptorGradientContent {
Grad: DesciptorGradient;
Type: string;
Dthr?: boolean;
Rvrs?: boolean;
Angl?: DescriptorUnitsValue;
'Scl '?: DescriptorUnitsValue;
Algn?: boolean;
Ofst?: {
Hrzn: DescriptorUnitsValue;
Vrtc: DescriptorUnitsValue;
};
}
export interface DescriptorPatternContent {
Ptrn: DesciptorPattern;
Lnkd?: boolean;
phase?: {
Hrzn: number;
Vrtc: number;
};
}
export type DescriptorVectorContent = DescriptorColorContent | DescriptorGradientContent | DescriptorPatternContent;
export interface StrokeDescriptor {
strokeStyleVersion: number;
strokeEnabled: boolean;
fillEnabled: boolean;
strokeStyleLineWidth: DescriptorUnitsValue;
strokeStyleLineDashOffset: DescriptorUnitsValue;
strokeStyleMiterLimit: number;
strokeStyleLineCapType: string;
strokeStyleLineJoinType: string;
strokeStyleLineAlignment: string;
strokeStyleScaleLock: boolean;
strokeStyleStrokeAdjust: boolean;
strokeStyleLineDashSet: DescriptorUnitsValue[];
strokeStyleBlendMode: string;
strokeStyleOpacity: DescriptorUnitsValue;
strokeStyleContent: DescriptorVectorContent;
strokeStyleResolution: number;
}
export interface TextDescriptor {
'Txt ': string;
textGridding: string;
Ornt: string;
AntA: string;
TextIndex: number;
EngineData?: Uint8Array;
}
export interface WarpDescriptor {
warpStyle: string;
warpValue?: number;
warpValues?: number[];
warpPerspective: number;
warpPerspectiveOther: number;
warpRotate: string;
bounds?: {
'Top ': DescriptorUnitsValue;
Left: DescriptorUnitsValue;
Btom: DescriptorUnitsValue;
Rght: DescriptorUnitsValue;
};
uOrder: number;
vOrder: number;
customEnvelopeWarp?: {
meshPoints: {
type: 'Hrzn' | 'Vrtc';
values: number[];
}[];
};
}
export interface QuiltWarpDescriptor extends WarpDescriptor {
deformNumRows: number;
deformNumCols: number;
customEnvelopeWarp: {
quiltSliceX: {
type: 'quiltSliceX';
values: number[];
}[];
quiltSliceY: {
type: 'quiltSliceY';
values: number[];
}[];
meshPoints: {
type: 'Hrzn' | 'Vrtc';
values: number[];
}[];
};
}
export interface FractionDescriptor {
numerator: number;
denominator: number;
}
export interface HrznVrtcDescriptor {
Hrzn: number;
Vrtc: number;
}
export interface FrameDescriptor {
FrLs: number[];
enab?: boolean;
IMsk?: {
Ofst: HrznVrtcDescriptor;
};
VMsk?: {
Ofst: HrznVrtcDescriptor;
};
Ofst?: HrznVrtcDescriptor;
FXRf?: HrznVrtcDescriptor;
Lefx?: Lfx2Descriptor;
blendOptions?: {
Opct: DescriptorUnitsValue;
};
}
export interface FrameListDescriptor {
LaID: number;
LaSt: FrameDescriptor[];
}
export declare function horzVrtcToXY(hv: HrznVrtcDescriptor): {
x: number;
y: number;
};
export declare function xyToHorzVrtc(xy: {
x: number;
y: number;
}): HrznVrtcDescriptor;
export type TimelineAnimKeyDescriptor = {
Type: 'keyType.Opct';
Opct: DescriptorUnitsValue;
} | {
Type: 'keyType.Trnf';
'Scl ': HrznVrtcDescriptor;
Skew: HrznVrtcDescriptor;
rotation: number;
translation: HrznVrtcDescriptor;
} | {
Type: 'keyType.Pstn';
Hrzn: number;
Vrtc: number;
} | {
Type: 'keyType.sheetStyle';
sheetStyle: {
Vrsn: number;
Lefx?: Lfx2Descriptor;
blendOptions: {};
};
} | {
Type: 'keyType.globalLighting';
gblA: number;
globalAltitude: number;
};
export interface TimelineKeyDescriptor {
Vrsn: 1;
animInterpStyle: 'animInterpStyle.Lnr ' | 'animInterpStyle.hold';
time: FractionDescriptor;
animKey: TimelineAnimKeyDescriptor;
selected: boolean;
}
export interface TimelineTrackDescriptor {
trackID: 'stdTrackID.globalLightingTrack' | 'stdTrackID.opacityTrack' | 'stdTrackID.styleTrack' | 'stdTrackID.sheetTransformTrack' | 'stdTrackID.sheetPositionTrack';
Vrsn: 1;
enab: boolean;
Effc: boolean;
effectParams?: {
keyList: TimelineKeyDescriptor[];
fillCanvas: boolean;
zoomOrigin: number;
};
keyList: TimelineKeyDescriptor[];
}
export interface TimeScopeDescriptor {
Vrsn: 1;
Strt: FractionDescriptor;
duration: FractionDescriptor;
inTime: FractionDescriptor;
outTime: FractionDescriptor;
}
export interface TimelineDescriptor {
Vrsn: 1;
timeScope: TimeScopeDescriptor;
autoScope: boolean;
audioLevel: number;
LyrI: number;
trackList?: TimelineTrackDescriptor[];
}
export interface EffectDescriptor extends Partial<DescriptorGradientContent>, Partial<DescriptorPatternContent> {
enab?: boolean;
Styl: string;
PntT?: string;
'Md '?: string;
Opct?: DescriptorUnitsValue;
'Sz '?: DescriptorUnitsValue;
'Clr '?: DescriptorColor;
present?: boolean;
showInDialog?: boolean;
overprint?: boolean;
}
export interface Lfx2Descriptor {
'Scl '?: DescriptorUnitsValue;
masterFXSwitch?: boolean;
DrSh?: EffectDescriptor;
IrSh?: EffectDescriptor;
OrGl?: EffectDescriptor;
IrGl?: EffectDescriptor;
ebbl?: EffectDescriptor;
SoFi?: EffectDescriptor;
patternFill?: EffectDescriptor;
GrFl?: EffectDescriptor;
ChFX?: EffectDescriptor;
FrFX?: EffectDescriptor;
}
export interface LmfxDescriptor {
'Scl '?: DescriptorUnitsValue;
masterFXSwitch?: boolean;
numModifyingFX?: number;
OrGl?: EffectDescriptor;
IrGl?: EffectDescriptor;
ebbl?: EffectDescriptor;
ChFX?: EffectDescriptor;
dropShadowMulti?: EffectDescriptor[];
innerShadowMulti?: EffectDescriptor[];
solidFillMulti?: EffectDescriptor[];
gradientFillMulti?: EffectDescriptor[];
frameFXMulti?: EffectDescriptor[];
patternFill?: EffectDescriptor;
}
export declare function serializeEffects(e: LayerEffectsInfo, log: boolean, multi: boolean): Lfx2Descriptor & LmfxDescriptor;
export declare function parseEffects(info: Lfx2Descriptor & LmfxDescriptor, log: boolean): LayerEffectsInfo;
export declare function parseTrackList(trackList: TimelineTrackDescriptor[], logMissingFeatures: boolean): TimelineTrack[];
export declare function serializeTrackList(tracks: TimelineTrack[]): TimelineTrackDescriptor[];
export declare function parseVectorContent(descriptor: DescriptorVectorContent): VectorContent;
export declare function serializeVectorContent(content: VectorContent): {
descriptor: DescriptorVectorContent;
key: string;
};
export declare function parseColor(color: DescriptorColor): Color;
export declare function serializeColor(color: Color | undefined): DescriptorColor;
export declare function parseAngle(x: DescriptorUnitsValue): number;
export declare function parsePercent(x: DescriptorUnitsValue | undefined): number;
export declare function parsePercentOrAngle(x: DescriptorUnitsValue | undefined): number;
export declare function parseUnits({ units, value }: DescriptorUnitsValue): UnitsValue;
export declare function parseUnitsOrNumber(value: DescriptorUnitsValue | number, units?: Units): UnitsValue;
export declare function parseUnitsToNumber({ units, value }: DescriptorUnitsValue, expectedUnits: string): number;
export declare function unitsAngle(value: number | undefined): DescriptorUnitsValue;
export declare function unitsPercent(value: number | undefined): DescriptorUnitsValue;
export declare function unitsValue(x: UnitsValue | undefined, key: string): DescriptorUnitsValue;
export declare const textGridding: {
decode: (val: string) => TextGridding;
encode: (val: TextGridding | undefined) => string;
};
export declare const Ornt: {
decode: (val: string) => Orientation;
encode: (val: Orientation | undefined) => string;
};
export declare const Annt: {
decode: (val: string) => AntiAlias;
encode: (val: AntiAlias | undefined) => string;
};
export declare const warpStyle: {
decode: (val: string) => WarpStyle;
encode: (val: WarpStyle | undefined) => string;
};
export declare const BlnM: {
decode: (val: string) => BlendMode;
encode: (val: BlendMode | undefined) => string;
};
export declare const BESl: {
decode: (val: string) => BevelStyle;
encode: (val: BevelStyle | undefined) => string;
};
export declare const bvlT: {
decode: (val: string) => BevelTechnique;
encode: (val: BevelTechnique | undefined) => string;
};
export declare const BESs: {
decode: (val: string) => BevelDirection;
encode: (val: BevelDirection | undefined) => string;
};
export declare const BETE: {
decode: (val: string) => GlowTechnique;
encode: (val: GlowTechnique | undefined) => string;
};
export declare const IGSr: {
decode: (val: string) => GlowSource;
encode: (val: GlowSource | undefined) => string;
};
export declare const GrdT: {
decode: (val: string) => GradientStyle;
encode: (val: GradientStyle | undefined) => string;
};
export declare const animInterpStyleEnum: {
decode: (val: string) => TimelineKeyInterpolation;
encode: (val: TimelineKeyInterpolation | undefined) => string;
};
export declare const stdTrackID: {
decode: (val: string) => TimelineTrackType;
encode: (val: TimelineTrackType | undefined) => string;
};
export declare const gradientInterpolationMethodType: {
decode: (val: string) => InterpolationMethod;
encode: (val: InterpolationMethod | undefined) => string;
};
export declare const ClrS: {
decode: (val: string) => "rgb" | "hsb" | "lab";
encode: (val: "rgb" | "hsb" | "lab" | undefined) => string;
};
export declare const FStl: {
decode: (val: string) => "center" | "inside" | "outside";
encode: (val: "center" | "inside" | "outside" | undefined) => string;
};
export declare const FrFl: {
decode: (val: string) => "color" | "pattern" | "gradient";
encode: (val: "color" | "pattern" | "gradient" | undefined) => string;
};
export declare const ESliceType: {
decode: (val: string) => "image" | "noImage";
encode: (val: "image" | "noImage" | undefined) => string;
};
export declare const ESliceHorzAlign: {
decode: (val: string) => "default";
encode: (val: "default" | undefined) => string;
};
export declare const ESliceVertAlign: {
decode: (val: string) => "default";
encode: (val: "default" | undefined) => string;
};
export declare const ESliceOrigin: {
decode: (val: string) => "userGenerated" | "autoGenerated" | "layer";
encode: (val: "userGenerated" | "autoGenerated" | "layer" | undefined) => string;
};
export declare const ESliceBGColorType: {
decode: (val: string) => "none" | "color" | "matte";
encode: (val: "none" | "color" | "matte" | undefined) => string;
};
export declare const strokeStyleLineCapType: {
decode: (val: string) => LineCapType;
encode: (val: LineCapType | undefined) => string;
};
export declare const strokeStyleLineJoinType: {
decode: (val: string) => LineJoinType;
encode: (val: LineJoinType | undefined) => string;
};
export declare const strokeStyleLineAlignment: {
decode: (val: string) => LineAlignment;
encode: (val: LineAlignment | undefined) => string;
};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
import { LayerEffectsInfo } from './psd';
import { PsdReader } from './psdReader';
import { PsdWriter } from './psdWriter';
export declare function readEffects(reader: PsdReader): LayerEffectsInfo;
export declare function writeEffects(writer: PsdWriter, effects: LayerEffectsInfo): void;

View File

@@ -0,0 +1,304 @@
import { toBlendMode, fromBlendMode } from './helpers';
import { checkSignature, readSignature, skipBytes, readUint16, readUint8, readUint32, readFixedPoint32, readColor } from './psdReader';
import { writeSignature, writeUint16, writeZeros, writeFixedPoint32, writeUint8, writeUint32, writeColor } from './psdWriter';
var bevelStyles = [
undefined, 'outer bevel', 'inner bevel', 'emboss', 'pillow emboss', 'stroke emboss'
];
function readBlendMode(reader) {
checkSignature(reader, '8BIM');
return toBlendMode[readSignature(reader)] || 'normal';
}
function writeBlendMode(writer, mode) {
writeSignature(writer, '8BIM');
writeSignature(writer, fromBlendMode[mode] || 'norm');
}
function readFixedPoint8(reader) {
return readUint8(reader) / 0xff;
}
function writeFixedPoint8(writer, value) {
writeUint8(writer, Math.round(value * 0xff) | 0);
}
export function readEffects(reader) {
var version = readUint16(reader);
if (version !== 0)
throw new Error("Invalid effects layer version: ".concat(version));
var effectsCount = readUint16(reader);
var effects = {};
for (var i = 0; i < effectsCount; i++) {
checkSignature(reader, '8BIM');
var type = readSignature(reader);
switch (type) {
case 'cmnS': { // common state (see See Effects layer, common state info)
var size = readUint32(reader);
var version_1 = readUint32(reader);
var visible = !!readUint8(reader);
skipBytes(reader, 2);
if (size !== 7 || version_1 !== 0 || !visible)
throw new Error("Invalid effects common state");
break;
}
case 'dsdw': // drop shadow (see See Effects layer, drop shadow and inner shadow info)
case 'isdw': { // inner shadow (see See Effects layer, drop shadow and inner shadow info)
var blockSize = readUint32(reader);
var version_2 = readUint32(reader);
if (blockSize !== 41 && blockSize !== 51)
throw new Error("Invalid shadow size: ".concat(blockSize));
if (version_2 !== 0 && version_2 !== 2)
throw new Error("Invalid shadow version: ".concat(version_2));
var size = readFixedPoint32(reader);
readFixedPoint32(reader); // intensity
var angle = readFixedPoint32(reader);
var distance = readFixedPoint32(reader);
var color = readColor(reader);
var blendMode = readBlendMode(reader);
var enabled = !!readUint8(reader);
var useGlobalLight = !!readUint8(reader);
var opacity = readFixedPoint8(reader);
if (blockSize >= 51)
readColor(reader); // native color
var shadowInfo = {
size: { units: 'Pixels', value: size },
distance: { units: 'Pixels', value: distance },
angle: angle,
color: color,
blendMode: blendMode,
enabled: enabled,
useGlobalLight: useGlobalLight,
opacity: opacity
};
if (type === 'dsdw') {
effects.dropShadow = [shadowInfo];
}
else {
effects.innerShadow = [shadowInfo];
}
break;
}
case 'oglw': { // outer glow (see See Effects layer, outer glow info)
var blockSize = readUint32(reader);
var version_3 = readUint32(reader);
if (blockSize !== 32 && blockSize !== 42)
throw new Error("Invalid outer glow size: ".concat(blockSize));
if (version_3 !== 0 && version_3 !== 2)
throw new Error("Invalid outer glow version: ".concat(version_3));
var size = readFixedPoint32(reader);
readFixedPoint32(reader); // intensity
var color = readColor(reader);
var blendMode = readBlendMode(reader);
var enabled = !!readUint8(reader);
var opacity = readFixedPoint8(reader);
if (blockSize >= 42)
readColor(reader); // native color
effects.outerGlow = {
size: { units: 'Pixels', value: size },
color: color,
blendMode: blendMode,
enabled: enabled,
opacity: opacity
};
break;
}
case 'iglw': { // inner glow (see See Effects layer, inner glow info)
var blockSize = readUint32(reader);
var version_4 = readUint32(reader);
if (blockSize !== 32 && blockSize !== 43)
throw new Error("Invalid inner glow size: ".concat(blockSize));
if (version_4 !== 0 && version_4 !== 2)
throw new Error("Invalid inner glow version: ".concat(version_4));
var size = readFixedPoint32(reader);
readFixedPoint32(reader); // intensity
var color = readColor(reader);
var blendMode = readBlendMode(reader);
var enabled = !!readUint8(reader);
var opacity = readFixedPoint8(reader);
if (blockSize >= 43) {
readUint8(reader); // inverted
readColor(reader); // native color
}
effects.innerGlow = {
size: { units: 'Pixels', value: size },
color: color,
blendMode: blendMode,
enabled: enabled,
opacity: opacity
};
break;
}
case 'bevl': { // bevel (see See Effects layer, bevel info)
var blockSize = readUint32(reader);
var version_5 = readUint32(reader);
if (blockSize !== 58 && blockSize !== 78)
throw new Error("Invalid bevel size: ".concat(blockSize));
if (version_5 !== 0 && version_5 !== 2)
throw new Error("Invalid bevel version: ".concat(version_5));
var angle = readFixedPoint32(reader);
var strength = readFixedPoint32(reader);
var size = readFixedPoint32(reader);
var highlightBlendMode = readBlendMode(reader);
var shadowBlendMode = readBlendMode(reader);
var highlightColor = readColor(reader);
var shadowColor = readColor(reader);
var style = bevelStyles[readUint8(reader)] || 'inner bevel';
var highlightOpacity = readFixedPoint8(reader);
var shadowOpacity = readFixedPoint8(reader);
var enabled = !!readUint8(reader);
var useGlobalLight = !!readUint8(reader);
var direction = readUint8(reader) ? 'down' : 'up';
if (blockSize >= 78) {
readColor(reader); // real highlight color
readColor(reader); // real shadow color
}
effects.bevel = {
size: { units: 'Pixels', value: size },
angle: angle,
strength: strength,
highlightBlendMode: highlightBlendMode,
shadowBlendMode: shadowBlendMode,
highlightColor: highlightColor,
shadowColor: shadowColor,
style: style,
highlightOpacity: highlightOpacity,
shadowOpacity: shadowOpacity,
enabled: enabled,
useGlobalLight: useGlobalLight,
direction: direction,
};
break;
}
case 'sofi': { // solid fill (Photoshop 7.0) (see See Effects layer, solid fill (added in Photoshop 7.0))
var size = readUint32(reader);
var version_6 = readUint32(reader);
if (size !== 34)
throw new Error("Invalid effects solid fill info size: ".concat(size));
if (version_6 !== 2)
throw new Error("Invalid effects solid fill info version: ".concat(version_6));
var blendMode = readBlendMode(reader);
var color = readColor(reader);
var opacity = readFixedPoint8(reader);
var enabled = !!readUint8(reader);
readColor(reader); // native color
effects.solidFill = [{ blendMode: blendMode, color: color, opacity: opacity, enabled: enabled }];
break;
}
default:
throw new Error("Invalid effect type: '".concat(type, "'"));
}
}
return effects;
}
function writeShadowInfo(writer, shadow) {
var _a;
writeUint32(writer, 51);
writeUint32(writer, 2);
writeFixedPoint32(writer, shadow.size && shadow.size.value || 0);
writeFixedPoint32(writer, 0); // intensity
writeFixedPoint32(writer, shadow.angle || 0);
writeFixedPoint32(writer, shadow.distance && shadow.distance.value || 0);
writeColor(writer, shadow.color);
writeBlendMode(writer, shadow.blendMode);
writeUint8(writer, shadow.enabled ? 1 : 0);
writeUint8(writer, shadow.useGlobalLight ? 1 : 0);
writeFixedPoint8(writer, (_a = shadow.opacity) !== null && _a !== void 0 ? _a : 1);
writeColor(writer, shadow.color); // native color
}
export function writeEffects(writer, effects) {
var _a, _b, _c, _d, _e, _f;
var dropShadow = (_a = effects.dropShadow) === null || _a === void 0 ? void 0 : _a[0];
var innerShadow = (_b = effects.innerShadow) === null || _b === void 0 ? void 0 : _b[0];
var outerGlow = effects.outerGlow;
var innerGlow = effects.innerGlow;
var bevel = effects.bevel;
var solidFill = (_c = effects.solidFill) === null || _c === void 0 ? void 0 : _c[0];
var count = 1;
if (dropShadow)
count++;
if (innerShadow)
count++;
if (outerGlow)
count++;
if (innerGlow)
count++;
if (bevel)
count++;
if (solidFill)
count++;
writeUint16(writer, 0);
writeUint16(writer, count);
writeSignature(writer, '8BIM');
writeSignature(writer, 'cmnS');
writeUint32(writer, 7); // size
writeUint32(writer, 0); // version
writeUint8(writer, 1); // visible
writeZeros(writer, 2);
if (dropShadow) {
writeSignature(writer, '8BIM');
writeSignature(writer, 'dsdw');
writeShadowInfo(writer, dropShadow);
}
if (innerShadow) {
writeSignature(writer, '8BIM');
writeSignature(writer, 'isdw');
writeShadowInfo(writer, innerShadow);
}
if (outerGlow) {
writeSignature(writer, '8BIM');
writeSignature(writer, 'oglw');
writeUint32(writer, 42);
writeUint32(writer, 2);
writeFixedPoint32(writer, ((_d = outerGlow.size) === null || _d === void 0 ? void 0 : _d.value) || 0);
writeFixedPoint32(writer, 0); // intensity
writeColor(writer, outerGlow.color);
writeBlendMode(writer, outerGlow.blendMode);
writeUint8(writer, outerGlow.enabled ? 1 : 0);
writeFixedPoint8(writer, outerGlow.opacity || 0);
writeColor(writer, outerGlow.color);
}
if (innerGlow) {
writeSignature(writer, '8BIM');
writeSignature(writer, 'iglw');
writeUint32(writer, 43);
writeUint32(writer, 2);
writeFixedPoint32(writer, ((_e = innerGlow.size) === null || _e === void 0 ? void 0 : _e.value) || 0);
writeFixedPoint32(writer, 0); // intensity
writeColor(writer, innerGlow.color);
writeBlendMode(writer, innerGlow.blendMode);
writeUint8(writer, innerGlow.enabled ? 1 : 0);
writeFixedPoint8(writer, innerGlow.opacity || 0);
writeUint8(writer, 0); // inverted
writeColor(writer, innerGlow.color);
}
if (bevel) {
writeSignature(writer, '8BIM');
writeSignature(writer, 'bevl');
writeUint32(writer, 78);
writeUint32(writer, 2);
writeFixedPoint32(writer, bevel.angle || 0);
writeFixedPoint32(writer, bevel.strength || 0);
writeFixedPoint32(writer, ((_f = bevel.size) === null || _f === void 0 ? void 0 : _f.value) || 0);
writeBlendMode(writer, bevel.highlightBlendMode);
writeBlendMode(writer, bevel.shadowBlendMode);
writeColor(writer, bevel.highlightColor);
writeColor(writer, bevel.shadowColor);
var style = bevelStyles.indexOf(bevel.style);
writeUint8(writer, style <= 0 ? 1 : style);
writeFixedPoint8(writer, bevel.highlightOpacity || 0);
writeFixedPoint8(writer, bevel.shadowOpacity || 0);
writeUint8(writer, bevel.enabled ? 1 : 0);
writeUint8(writer, bevel.useGlobalLight ? 1 : 0);
writeUint8(writer, bevel.direction === 'down' ? 1 : 0);
writeColor(writer, bevel.highlightColor);
writeColor(writer, bevel.shadowColor);
}
if (solidFill) {
writeSignature(writer, '8BIM');
writeSignature(writer, 'sofi');
writeUint32(writer, 34);
writeUint32(writer, 2);
writeBlendMode(writer, solidFill.blendMode);
writeColor(writer, solidFill.color);
writeFixedPoint8(writer, solidFill.opacity || 0);
writeUint8(writer, solidFill.enabled ? 1 : 0);
writeColor(writer, solidFill.color);
}
}
//# sourceMappingURL=effectsHelpers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
export declare function parseEngineData(data: number[] | Uint8Array): any;
export declare function serializeEngineData(data: any, condensed?: boolean): Uint8Array;

View File

@@ -0,0 +1,332 @@
function isWhitespace(char) {
// ' ', '\n', '\r', '\t'
return char === 32 || char === 10 || char === 13 || char === 9;
}
function isNumber(char) {
// 0123456789.-
return (char >= 48 && char <= 57) || char === 46 || char === 45;
}
export function parseEngineData(data) {
var index = 0;
function skipWhitespace() {
while (index < data.length && isWhitespace(data[index])) {
index++;
}
}
function getTextByte() {
var byte = data[index];
index++;
if (byte === 92) { // \
byte = data[index];
index++;
}
return byte;
}
function getText() {
var result = '';
if (data[index] === 41) { // )
index++;
return result;
}
// Strings start with utf-16 BOM
if (data[index] !== 0xFE || data[index + 1] !== 0xFF) {
throw new Error('Invalid utf-16 BOM');
}
index += 2;
// ), ( and \ characters are escaped in ascii manner, remove the escapes before interpreting
// the bytes as utf-16
while (index < data.length && data[index] !== 41) { // )
var high = getTextByte();
var low = getTextByte();
var char = (high << 8) | low;
result += String.fromCharCode(char);
}
index++;
return result;
}
var root = null;
var stack = [];
function pushContainer(value) {
if (!stack.length) {
stack.push(value);
root = value;
}
else {
pushValue(value);
stack.push(value);
}
}
function pushValue(value) {
if (!stack.length)
throw new Error('Invalid data');
var top = stack[stack.length - 1];
if (typeof top === 'string') {
stack[stack.length - 2][top] = value;
pop();
}
else if (Array.isArray(top)) {
top.push(value);
}
else {
throw new Error('Invalid data');
}
}
function pushProperty(name) {
if (!stack.length)
pushContainer({});
var top = stack[stack.length - 1];
if (top && typeof top === 'string') {
if (name === 'nil') {
pushValue(null);
}
else {
pushValue("/".concat(name));
}
}
else if (top && typeof top === 'object') {
stack.push(name);
}
else {
throw new Error('Invalid data');
}
}
function pop() {
if (!stack.length)
throw new Error('Invalid data');
stack.pop();
}
skipWhitespace();
while (index < data.length) {
var i = index;
var char = data[i];
if (char === 60 && data[i + 1] === 60) { // <<
index += 2;
pushContainer({});
}
else if (char === 62 && data[i + 1] === 62) { // >>
index += 2;
pop();
}
else if (char === 47) { // /
index += 1;
var start = index;
while (index < data.length && !isWhitespace(data[index])) {
index++;
}
var name_1 = '';
for (var i_1 = start; i_1 < index; i_1++) {
name_1 += String.fromCharCode(data[i_1]);
}
pushProperty(name_1);
}
else if (char === 40) { // (
index += 1;
pushValue(getText());
}
else if (char === 91) { // [
index += 1;
pushContainer([]);
}
else if (char === 93) { // ]
index += 1;
pop();
}
else if (char === 110 && data[i + 1] === 117 && data[i + 2] === 108 && data[i + 3] === 108) { // null
index += 4;
pushValue(null);
}
else if (char === 116 && data[i + 1] === 114 && data[i + 2] === 117 && data[i + 3] === 101) { // true
index += 4;
pushValue(true);
}
else if (char === 102 && data[i + 1] === 97 && data[i + 2] === 108 && data[i + 3] === 115 && data[i + 4] === 101) { // false
index += 5;
pushValue(false);
}
else if (isNumber(char)) {
var value = '';
while (index < data.length && isNumber(data[index])) {
value += String.fromCharCode(data[index]);
index++;
}
pushValue(parseFloat(value));
}
else {
index += 1;
console.log("Invalid token ".concat(String.fromCharCode(char), " at ").concat(index));
// ` near ${String.fromCharCode.apply(null, data.slice(index - 10, index + 20) as any)}` +
// `data [${Array.from(data.slice(index - 10, index + 20)).join(', ')}]`
}
skipWhitespace();
}
return root;
}
var floatKeys = [
'Axis', 'XY', 'Zone', 'WordSpacing', 'FirstLineIndent', 'GlyphSpacing', 'StartIndent', 'EndIndent', 'SpaceBefore',
'SpaceAfter', 'LetterSpacing', 'Values', 'GridSize', 'GridLeading', 'PointBase', 'BoxBounds', 'TransformPoint0', 'TransformPoint1',
'TransformPoint2', 'FontSize', 'Leading', 'HorizontalScale', 'VerticalScale', 'BaselineShift', 'Tsume',
'OutlineWidth', 'AutoLeading',
];
var intArrays = ['RunLengthArray'];
// TODO: handle /nil
export function serializeEngineData(data, condensed) {
if (condensed === void 0) { condensed = false; }
var buffer = new Uint8Array(1024);
var offset = 0;
var indent = 0;
function write(value) {
if (offset >= buffer.length) {
var newBuffer = new Uint8Array(buffer.length * 2);
newBuffer.set(buffer);
buffer = newBuffer;
}
buffer[offset] = value;
offset++;
}
function writeString(value) {
for (var i = 0; i < value.length; i++) {
write(value.charCodeAt(i));
}
}
function writeIndent() {
if (condensed) {
writeString(' ');
}
else {
for (var i = 0; i < indent; i++) {
writeString('\t');
}
}
}
function writeProperty(key, value) {
writeIndent();
writeString("/".concat(key));
writeValue(value, key, true);
if (!condensed)
writeString('\n');
}
function serializeInt(value) {
return value.toString();
}
function serializeFloat(value) {
return value.toFixed(5)
.replace(/(\d)0+$/g, '$1')
.replace(/^0+\.([1-9])/g, '.$1')
.replace(/^-0+\.0(\d)/g, '-.0$1');
}
function serializeNumber(value, key) {
var isFloat = (key && floatKeys.indexOf(key) !== -1) || (value | 0) !== value;
return isFloat ? serializeFloat(value) : serializeInt(value);
}
function getKeys(value) {
var keys = Object.keys(value);
if (keys.indexOf('98') !== -1)
keys.unshift.apply(keys, keys.splice(keys.indexOf('99'), 1));
if (keys.indexOf('99') !== -1)
keys.unshift.apply(keys, keys.splice(keys.indexOf('99'), 1));
return keys;
}
function writeStringByte(value) {
if (value === 40 || value === 41 || value === 92) { // ( ) \
write(92); // \
}
write(value);
}
function writeValue(value, key, inProperty) {
if (inProperty === void 0) { inProperty = false; }
function writePrefix() {
if (inProperty) {
writeString(' ');
}
else {
writeIndent();
}
}
if (value === null) {
writePrefix();
writeString(condensed ? '/nil' : 'null');
}
else if (typeof value === 'number') {
writePrefix();
writeString(serializeNumber(value, key));
}
else if (typeof value === 'boolean') {
writePrefix();
writeString(value ? 'true' : 'false');
}
else if (typeof value === 'string') {
writePrefix();
if ((key === '99' || key === '98') && value.charAt(0) === '/') {
writeString(value);
}
else {
writeString('(');
write(0xfe);
write(0xff);
for (var i = 0; i < value.length; i++) {
var code = value.charCodeAt(i);
writeStringByte((code >> 8) & 0xff);
writeStringByte(code & 0xff);
}
writeString(')');
}
}
else if (Array.isArray(value)) {
writePrefix();
if (value.every(function (x) { return typeof x === 'number'; })) {
writeString('[');
var intArray = intArrays.indexOf(key) !== -1;
for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
var x = value_1[_i];
writeString(' ');
writeString(intArray ? serializeNumber(x) : serializeFloat(x));
}
writeString(' ]');
}
else {
writeString('[');
if (!condensed)
writeString('\n');
for (var _a = 0, value_2 = value; _a < value_2.length; _a++) {
var x = value_2[_a];
writeValue(x, key);
if (!condensed)
writeString('\n');
}
writeIndent();
writeString(']');
}
}
else if (typeof value === 'object') {
if (inProperty && !condensed)
writeString('\n');
writeIndent();
writeString('<<');
if (!condensed)
writeString('\n');
indent++;
for (var _b = 0, _c = getKeys(value); _b < _c.length; _b++) {
var key_1 = _c[_b];
writeProperty(key_1, value[key_1]);
}
indent--;
writeIndent();
writeString('>>');
}
return undefined;
}
if (condensed) {
if (typeof data === 'object') {
for (var _i = 0, _a = getKeys(data); _i < _a.length; _i++) {
var key = _a[_i];
writeProperty(key, data[key]);
}
}
}
else {
writeString('\n\n');
writeValue(data);
}
return buffer.slice(0, offset);
}
//# sourceMappingURL=engineData.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,93 @@
import { Layer, BlendMode, LayerColor } from './psd';
export declare const MOCK_HANDLERS = false;
export declare const RAW_IMAGE_DATA = false;
export declare const fromBlendMode: {
[key: string]: string;
};
export declare const toBlendMode: {
[key: string]: BlendMode;
};
export declare const layerColors: LayerColor[];
export declare const largeAdditionalInfoKeys: string[];
export interface Dict {
[key: string]: string;
}
export declare function revMap(map: Dict): Dict;
export declare function createEnum<T>(prefix: string, def: string, map: Dict): {
decode: (val: string) => T;
encode: (val: T | undefined) => string;
};
export declare const enum ColorSpace {
RGB = 0,
HSB = 1,
CMYK = 2,
Lab = 7,
Grayscale = 8
}
export declare const enum LayerMaskFlags {
PositionRelativeToLayer = 1,
LayerMaskDisabled = 2,
InvertLayerMaskWhenBlending = 4,
LayerMaskFromRenderingOtherData = 8,
MaskHasParametersAppliedToIt = 16
}
export declare const enum MaskParams {
UserMaskDensity = 1,
UserMaskFeather = 2,
VectorMaskDensity = 4,
VectorMaskFeather = 8
}
export declare const enum ChannelID {
Color0 = 0,
Color1 = 1,
Color2 = 2,
Color3 = 3,
Transparency = -1,
UserMask = -2,
RealUserMask = -3
}
export declare const enum Compression {
RawData = 0,
RleCompressed = 1,
ZipWithoutPrediction = 2,
ZipWithPrediction = 3
}
export interface ChannelData {
channelId: ChannelID;
compression: Compression;
buffer: Uint8Array | undefined;
length: number;
}
export interface Bounds {
top: number;
left: number;
right: number;
bottom: number;
}
export interface LayerChannelData {
layer: Layer;
channels: ChannelData[];
top: number;
left: number;
right: number;
bottom: number;
mask?: Bounds;
}
export type PixelArray = Uint8ClampedArray | Uint8Array;
export interface PixelData {
data: PixelArray;
width: number;
height: number;
}
export declare function offsetForChannel(channelId: ChannelID, cmyk: boolean): number;
export declare function clamp(value: number, min: number, max: number): number;
export declare function hasAlpha(data: PixelData): boolean;
export declare function resetImageData({ data }: PixelData): void;
export declare function decodeBitmap(input: PixelArray, output: PixelArray, width: number, height: number): void;
export declare function writeDataRaw(data: PixelData, offset: number, width: number, height: number): Uint8Array | undefined;
export declare function writeDataRLE(buffer: Uint8Array, { data, width, height }: PixelData, offsets: number[], large: boolean): Uint8Array | undefined;
export declare function writeDataZipWithoutPrediction({ data, width, height }: PixelData, offsets: number[]): Uint8Array;
export declare let createCanvas: (width: number, height: number) => HTMLCanvasElement;
export declare let createCanvasFromData: (data: Uint8Array) => HTMLCanvasElement;
export declare let createImageData: (width: number, height: number) => ImageData;
export declare function initializeCanvas(createCanvasMethod: (width: number, height: number) => HTMLCanvasElement, createCanvasFromDataMethod?: (data: Uint8Array) => HTMLCanvasElement, createImageDataMethod?: (width: number, height: number) => ImageData): void;

View File

@@ -0,0 +1,315 @@
import { fromByteArray } from 'base64-js';
import { deflate } from 'pako';
export var MOCK_HANDLERS = false;
export var RAW_IMAGE_DATA = false;
export var fromBlendMode = {};
export var toBlendMode = {
'pass': 'pass through',
'norm': 'normal',
'diss': 'dissolve',
'dark': 'darken',
'mul ': 'multiply',
'idiv': 'color burn',
'lbrn': 'linear burn',
'dkCl': 'darker color',
'lite': 'lighten',
'scrn': 'screen',
'div ': 'color dodge',
'lddg': 'linear dodge',
'lgCl': 'lighter color',
'over': 'overlay',
'sLit': 'soft light',
'hLit': 'hard light',
'vLit': 'vivid light',
'lLit': 'linear light',
'pLit': 'pin light',
'hMix': 'hard mix',
'diff': 'difference',
'smud': 'exclusion',
'fsub': 'subtract',
'fdiv': 'divide',
'hue ': 'hue',
'sat ': 'saturation',
'colr': 'color',
'lum ': 'luminosity',
};
Object.keys(toBlendMode).forEach(function (key) { return fromBlendMode[toBlendMode[key]] = key; });
export var layerColors = [
'none', 'red', 'orange', 'yellow', 'green', 'blue', 'violet', 'gray'
];
export var largeAdditionalInfoKeys = [
// from documentation
'LMsk', 'Lr16', 'Lr32', 'Layr', 'Mt16', 'Mt32', 'Mtrn', 'Alph', 'FMsk', 'lnk2', 'FEid', 'FXid', 'PxSD',
// from guessing
'cinf',
];
export function revMap(map) {
var result = {};
Object.keys(map).forEach(function (key) { return result[map[key]] = key; });
return result;
}
export function createEnum(prefix, def, map) {
var rev = revMap(map);
var decode = function (val) {
var value = val.split('.')[1];
if (value && !rev[value])
throw new Error("Unrecognized value for enum: '".concat(val, "'"));
return rev[value] || def;
};
var encode = function (val) {
if (val && !map[val])
throw new Error("Invalid value for enum: '".concat(val, "'"));
return "".concat(prefix, ".").concat(map[val] || map[def]);
};
return { decode: decode, encode: encode };
}
export var ColorSpace;
(function (ColorSpace) {
ColorSpace[ColorSpace["RGB"] = 0] = "RGB";
ColorSpace[ColorSpace["HSB"] = 1] = "HSB";
ColorSpace[ColorSpace["CMYK"] = 2] = "CMYK";
ColorSpace[ColorSpace["Lab"] = 7] = "Lab";
ColorSpace[ColorSpace["Grayscale"] = 8] = "Grayscale";
})(ColorSpace || (ColorSpace = {}));
export var LayerMaskFlags;
(function (LayerMaskFlags) {
LayerMaskFlags[LayerMaskFlags["PositionRelativeToLayer"] = 1] = "PositionRelativeToLayer";
LayerMaskFlags[LayerMaskFlags["LayerMaskDisabled"] = 2] = "LayerMaskDisabled";
LayerMaskFlags[LayerMaskFlags["InvertLayerMaskWhenBlending"] = 4] = "InvertLayerMaskWhenBlending";
LayerMaskFlags[LayerMaskFlags["LayerMaskFromRenderingOtherData"] = 8] = "LayerMaskFromRenderingOtherData";
LayerMaskFlags[LayerMaskFlags["MaskHasParametersAppliedToIt"] = 16] = "MaskHasParametersAppliedToIt";
})(LayerMaskFlags || (LayerMaskFlags = {}));
export var MaskParams;
(function (MaskParams) {
MaskParams[MaskParams["UserMaskDensity"] = 1] = "UserMaskDensity";
MaskParams[MaskParams["UserMaskFeather"] = 2] = "UserMaskFeather";
MaskParams[MaskParams["VectorMaskDensity"] = 4] = "VectorMaskDensity";
MaskParams[MaskParams["VectorMaskFeather"] = 8] = "VectorMaskFeather";
})(MaskParams || (MaskParams = {}));
export var ChannelID;
(function (ChannelID) {
ChannelID[ChannelID["Color0"] = 0] = "Color0";
ChannelID[ChannelID["Color1"] = 1] = "Color1";
ChannelID[ChannelID["Color2"] = 2] = "Color2";
ChannelID[ChannelID["Color3"] = 3] = "Color3";
ChannelID[ChannelID["Transparency"] = -1] = "Transparency";
ChannelID[ChannelID["UserMask"] = -2] = "UserMask";
ChannelID[ChannelID["RealUserMask"] = -3] = "RealUserMask";
})(ChannelID || (ChannelID = {}));
export var Compression;
(function (Compression) {
Compression[Compression["RawData"] = 0] = "RawData";
Compression[Compression["RleCompressed"] = 1] = "RleCompressed";
Compression[Compression["ZipWithoutPrediction"] = 2] = "ZipWithoutPrediction";
Compression[Compression["ZipWithPrediction"] = 3] = "ZipWithPrediction";
})(Compression || (Compression = {}));
export function offsetForChannel(channelId, cmyk) {
switch (channelId) {
case 0 /* ChannelID.Color0 */: return 0;
case 1 /* ChannelID.Color1 */: return 1;
case 2 /* ChannelID.Color2 */: return 2;
case 3 /* ChannelID.Color3 */: return cmyk ? 3 : channelId + 1;
case -1 /* ChannelID.Transparency */: return cmyk ? 4 : 3;
default: return channelId + 1;
}
}
export function clamp(value, min, max) {
return value < min ? min : (value > max ? max : value);
}
export function hasAlpha(data) {
var size = data.width * data.height * 4;
for (var i = 3; i < size; i += 4) {
if (data.data[i] !== 255) {
return true;
}
}
return false;
}
export function resetImageData(_a) {
var data = _a.data;
var buffer = new Uint32Array(data.buffer);
var size = buffer.length | 0;
for (var p = 0; p < size; p = (p + 1) | 0) {
buffer[p] = 0xff000000;
}
}
export function decodeBitmap(input, output, width, height) {
for (var y = 0, p = 0, o = 0; y < height; y++) {
for (var x = 0; x < width;) {
var b = input[o++];
for (var i = 0; i < 8 && x < width; i++, x++) {
var v = b & 0x80 ? 0 : 255;
b = b << 1;
output[p++] = v;
output[p++] = v;
output[p++] = v;
output[p++] = 255;
}
}
}
}
export function writeDataRaw(data, offset, width, height) {
if (!width || !height)
return undefined;
var array = new Uint8Array(width * height);
for (var i = 0; i < array.length; i++) {
array[i] = data.data[i * 4 + offset];
}
return array;
}
export function writeDataRLE(buffer, _a, offsets, large) {
var data = _a.data, width = _a.width, height = _a.height;
if (!width || !height)
return undefined;
var stride = (4 * width) | 0;
var ol = 0;
var o = (offsets.length * (large ? 4 : 2) * height) | 0;
for (var _i = 0, offsets_1 = offsets; _i < offsets_1.length; _i++) {
var offset = offsets_1[_i];
for (var y = 0, p = offset | 0; y < height; y++) {
var strideStart = (y * stride) | 0;
var strideEnd = (strideStart + stride) | 0;
var lastIndex = (strideEnd + offset - 4) | 0;
var lastIndex2 = (lastIndex - 4) | 0;
var startOffset = o;
for (p = (strideStart + offset) | 0; p < strideEnd; p = (p + 4) | 0) {
if (p < lastIndex2) {
var value1 = data[p];
p = (p + 4) | 0;
var value2 = data[p];
p = (p + 4) | 0;
var value3 = data[p];
if (value1 === value2 && value1 === value3) {
var count = 3;
while (count < 128 && p < lastIndex && data[(p + 4) | 0] === value1) {
count = (count + 1) | 0;
p = (p + 4) | 0;
}
buffer[o++] = 1 - count;
buffer[o++] = value1;
}
else {
var countIndex = o;
var writeLast = true;
var count = 1;
buffer[o++] = 0;
buffer[o++] = value1;
while (p < lastIndex && count < 128) {
p = (p + 4) | 0;
value1 = value2;
value2 = value3;
value3 = data[p];
if (value1 === value2 && value1 === value3) {
p = (p - 12) | 0;
writeLast = false;
break;
}
else {
count++;
buffer[o++] = value1;
}
}
if (writeLast) {
if (count < 127) {
buffer[o++] = value2;
buffer[o++] = value3;
count += 2;
}
else if (count < 128) {
buffer[o++] = value2;
count++;
p = (p - 4) | 0;
}
else {
p = (p - 8) | 0;
}
}
buffer[countIndex] = count - 1;
}
}
else if (p === lastIndex) {
buffer[o++] = 0;
buffer[o++] = data[p];
}
else { // p === lastIndex2
buffer[o++] = 1;
buffer[o++] = data[p];
p = (p + 4) | 0;
buffer[o++] = data[p];
}
}
var length_1 = o - startOffset;
if (large) {
buffer[ol++] = (length_1 >> 24) & 0xff;
buffer[ol++] = (length_1 >> 16) & 0xff;
}
buffer[ol++] = (length_1 >> 8) & 0xff;
buffer[ol++] = length_1 & 0xff;
}
}
return buffer.slice(0, o);
}
export function writeDataZipWithoutPrediction(_a, offsets) {
var data = _a.data, width = _a.width, height = _a.height;
var size = width * height;
var channel = new Uint8Array(size);
var buffers = [];
var totalLength = 0;
for (var _i = 0, offsets_2 = offsets; _i < offsets_2.length; _i++) {
var offset = offsets_2[_i];
for (var i = 0, o = offset; i < size; i++, o += 4) {
channel[i] = data[o];
}
var buffer = deflate(channel);
buffers.push(buffer);
totalLength += buffer.byteLength;
}
if (buffers.length > 0) {
var buffer = new Uint8Array(totalLength);
var offset = 0;
for (var _b = 0, buffers_1 = buffers; _b < buffers_1.length; _b++) {
var b = buffers_1[_b];
buffer.set(b, offset);
offset += b.byteLength;
}
return buffer;
}
else {
return buffers[0];
}
}
export var createCanvas = function () {
throw new Error('Canvas not initialized, use initializeCanvas method to set up createCanvas method');
};
export var createCanvasFromData = function () {
throw new Error('Canvas not initialized, use initializeCanvas method to set up createCanvasFromData method');
};
var tempCanvas = undefined;
export var createImageData = function (width, height) {
if (!tempCanvas)
tempCanvas = createCanvas(1, 1);
return tempCanvas.getContext('2d').createImageData(width, height);
};
if (typeof document !== 'undefined') {
createCanvas = function (width, height) {
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
return canvas;
};
createCanvasFromData = function (data) {
var image = new Image();
image.src = 'data:image/jpeg;base64,' + fromByteArray(data);
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext('2d').drawImage(image, 0, 0);
return canvas;
};
}
export function initializeCanvas(createCanvasMethod, createCanvasFromDataMethod, createImageDataMethod) {
createCanvas = createCanvasMethod;
createCanvasFromData = createCanvasFromDataMethod || createCanvasFromData;
createImageData = createImageDataMethod || createImageData;
}
//# sourceMappingURL=helpers.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,13 @@
import { ImageResources, ReadOptions } from './psd';
import { PsdReader } from './psdReader';
import { PsdWriter } from './psdWriter';
export interface ResourceHandler {
key: number;
has: (target: ImageResources) => boolean | number;
read: (reader: PsdReader, target: ImageResources, left: () => number, options: ReadOptions) => void;
write: (writer: PsdWriter, target: ImageResources, index: number) => void;
}
export declare const resourceHandlers: ResourceHandler[];
export declare const resourceHandlersMap: {
[key: number]: ResourceHandler;
};

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,20 @@
/// <reference types="node" />
import { Psd, ReadOptions, WriteOptions } from './psd';
import { PsdWriter } from './psdWriter';
import { PsdReader } from './psdReader';
export * from './abr';
export * from './csh';
export { initializeCanvas } from './helpers';
export * from './psd';
import { fromByteArray } from 'base64-js';
export { PsdReader, PsdWriter };
interface BufferLike {
buffer: ArrayBuffer;
byteOffset: number;
byteLength: number;
}
export declare const byteArrayToBase64: typeof fromByteArray;
export declare function readPsd(buffer: ArrayBuffer | BufferLike, options?: ReadOptions): Psd;
export declare function writePsd(psd: Psd, options?: WriteOptions): ArrayBuffer;
export declare function writePsdUint8Array(psd: Psd, options?: WriteOptions): Uint8Array;
export declare function writePsdBuffer(psd: Psd, options?: WriteOptions): Buffer;

View File

@@ -0,0 +1,31 @@
import { writePsd as writePsdInternal, getWriterBuffer, createWriter, getWriterBufferNoCopy } from './psdWriter';
import { readPsd as readPsdInternal, createReader } from './psdReader';
export * from './abr';
export * from './csh';
export { initializeCanvas } from './helpers';
export * from './psd';
import { fromByteArray } from 'base64-js';
export var byteArrayToBase64 = fromByteArray;
export function readPsd(buffer, options) {
var reader = 'buffer' in buffer ?
createReader(buffer.buffer, buffer.byteOffset, buffer.byteLength) :
createReader(buffer);
return readPsdInternal(reader, options);
}
export function writePsd(psd, options) {
var writer = createWriter();
writePsdInternal(writer, psd, options);
return getWriterBuffer(writer);
}
export function writePsdUint8Array(psd, options) {
var writer = createWriter();
writePsdInternal(writer, psd, options);
return getWriterBufferNoCopy(writer);
}
export function writePsdBuffer(psd, options) {
if (typeof Buffer === 'undefined') {
throw new Error('Buffer not supported on this platform');
}
return Buffer.from(writePsdUint8Array(psd, options));
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"../src/","sources":["index.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,QAAQ,IAAI,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC5H,OAAO,EAAa,OAAO,IAAI,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAClF,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,cAAc,OAAO,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAS1C,MAAM,CAAC,IAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C,MAAM,UAAU,OAAO,CAAC,MAAgC,EAAE,OAAqB;IAC9E,IAAM,MAAM,GAAG,QAAQ,IAAI,MAAM,CAAC,CAAC;QAClC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACnE,YAAY,CAAC,MAAM,CAAC,CAAC;IACtB,OAAO,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAQ,EAAE,OAAsB;IACxD,IAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAQ,EAAE,OAAsB;IAClE,IAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAQ,EAAE,OAAsB;IAC9D,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;KACzD;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;AACtD,CAAC"}

View File

@@ -0,0 +1 @@
export declare function initialize(): void;

View File

@@ -0,0 +1,22 @@
import { createCanvas } from 'canvas';
import { initializeCanvas } from './index';
import { decodeJpeg } from './jpeg';
function createCanvasFromData(data) {
var canvas = createCanvas(100, 100);
try {
var context_1 = canvas.getContext('2d');
var imageData = decodeJpeg(data, function (w, h) { return context_1.createImageData(w, h); });
canvas.width = imageData.width;
canvas.height = imageData.height;
context_1.putImageData(imageData, 0, 0);
}
catch (e) {
console.error('JPEG decompression error', e.message);
}
return canvas;
}
initializeCanvas(createCanvas, createCanvasFromData);
export function initialize() {
initializeCanvas(createCanvas, createCanvasFromData);
}
//# sourceMappingURL=initializeCanvas.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"initializeCanvas.js","sourceRoot":"../src/","sources":["initializeCanvas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,SAAS,oBAAoB,CAAC,IAAgB;IAC7C,IAAM,MAAM,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAEtC,IAAI;QACH,IAAM,SAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAE,CAAC;QACzC,IAAM,SAAS,GAAG,UAAU,CAAC,IAAI,EAAE,UAAC,CAAC,EAAE,CAAC,IAAK,OAAA,SAAO,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,EAA7B,CAA6B,CAAC,CAAC;QAC5E,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;QAC/B,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QACjC,SAAO,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;KACtC;IAAC,OAAO,CAAM,EAAE;QAChB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;KACrD;IAED,OAAO,MAAM,CAAC;AACf,CAAC;AAED,gBAAgB,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;AAErD,MAAM,UAAU,UAAU;IACzB,gBAAgB,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC;AACtD,CAAC"}

View File

@@ -0,0 +1 @@
export declare function decodeJpeg(encoded: Uint8Array, createImageData: (width: number, height: number) => ImageData): ImageData;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,19 @@
export var ColorMode;
(function (ColorMode) {
ColorMode[ColorMode["Bitmap"] = 0] = "Bitmap";
ColorMode[ColorMode["Grayscale"] = 1] = "Grayscale";
ColorMode[ColorMode["Indexed"] = 2] = "Indexed";
ColorMode[ColorMode["RGB"] = 3] = "RGB";
ColorMode[ColorMode["CMYK"] = 4] = "CMYK";
ColorMode[ColorMode["Multichannel"] = 7] = "Multichannel";
ColorMode[ColorMode["Duotone"] = 8] = "Duotone";
ColorMode[ColorMode["Lab"] = 9] = "Lab";
})(ColorMode || (ColorMode = {}));
export var SectionDividerType;
(function (SectionDividerType) {
SectionDividerType[SectionDividerType["Other"] = 0] = "Other";
SectionDividerType[SectionDividerType["OpenFolder"] = 1] = "OpenFolder";
SectionDividerType[SectionDividerType["ClosedFolder"] = 2] = "ClosedFolder";
SectionDividerType[SectionDividerType["BoundingSectionDivider"] = 3] = "BoundingSectionDivider";
})(SectionDividerType || (SectionDividerType = {}));
//# sourceMappingURL=psd.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"psd.js","sourceRoot":"../src/","sources":["psd.ts"],"names":[],"mappings":"AAMA,MAAM,CAAN,IAAkB,SASjB;AATD,WAAkB,SAAS;IAC1B,6CAAU,CAAA;IACV,mDAAa,CAAA;IACb,+CAAW,CAAA;IACX,uCAAO,CAAA;IACP,yCAAQ,CAAA;IACR,yDAAgB,CAAA;IAChB,+CAAW,CAAA;IACX,uCAAO,CAAA;AACR,CAAC,EATiB,SAAS,KAAT,SAAS,QAS1B;AAED,MAAM,CAAN,IAAkB,kBAKjB;AALD,WAAkB,kBAAkB;IACnC,6DAAS,CAAA;IACT,uEAAc,CAAA;IACd,2EAAgB,CAAA;IAChB,+FAA0B,CAAA;AAC3B,CAAC,EALiB,kBAAkB,KAAlB,kBAAkB,QAKnC"}

View File

@@ -0,0 +1,36 @@
import { Psd, ColorMode, ReadOptions, Color, PatternInfo } from './psd';
import { PixelData } from './helpers';
export declare const supportedColorModes: ColorMode[];
export interface PsdReader {
offset: number;
view: DataView;
strict: boolean;
debug: boolean;
}
export declare function createReader(buffer: ArrayBuffer, offset?: number, length?: number): PsdReader;
export declare function warnOrThrow(reader: PsdReader, message: string): void;
export declare function readUint8(reader: PsdReader): number;
export declare function peekUint8(reader: PsdReader): number;
export declare function readInt16(reader: PsdReader): number;
export declare function readUint16(reader: PsdReader): number;
export declare function readInt32(reader: PsdReader): number;
export declare function readInt32LE(reader: PsdReader): number;
export declare function readUint32(reader: PsdReader): number;
export declare function readFloat32(reader: PsdReader): number;
export declare function readFloat64(reader: PsdReader): number;
export declare function readFixedPoint32(reader: PsdReader): number;
export declare function readFixedPointPath32(reader: PsdReader): number;
export declare function readBytes(reader: PsdReader, length: number): Uint8Array;
export declare function readSignature(reader: PsdReader): string;
export declare function readPascalString(reader: PsdReader, padTo: number): string;
export declare function readUnicodeString(reader: PsdReader): string;
export declare function readUnicodeStringWithLength(reader: PsdReader, length: number): string;
export declare function readAsciiString(reader: PsdReader, length: number): string;
export declare function skipBytes(reader: PsdReader, count: number): void;
export declare function checkSignature(reader: PsdReader, a: string, b?: string): void;
export declare function readPsd(reader: PsdReader, options?: ReadOptions): Psd;
export declare function readDataZipWithoutPrediction(reader: PsdReader, length: number, pixelData: PixelData | undefined, width: number, height: number, step: number, offset: number): void;
export declare function readDataRLE(reader: PsdReader, pixelData: PixelData | undefined, _width: number, height: number, step: number, offsets: number[], large: boolean): void;
export declare function readSection<T>(reader: PsdReader, round: number, func: (left: () => number) => T, skipEmpty?: boolean, eightBytes?: boolean): T | undefined;
export declare function readColor(reader: PsdReader): Color;
export declare function readPattern(reader: PsdReader): PatternInfo;

View File

@@ -0,0 +1,956 @@
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);
};
import { inflate } from 'pako';
import { resetImageData, offsetForChannel, decodeBitmap, createCanvas, createImageData, toBlendMode, RAW_IMAGE_DATA, largeAdditionalInfoKeys } from './helpers';
import { infoHandlersMap } from './additionalInfo';
import { resourceHandlersMap } from './imageResources';
export var supportedColorModes = [0 /* ColorMode.Bitmap */, 1 /* ColorMode.Grayscale */, 3 /* ColorMode.RGB */];
var colorModes = ['bitmap', 'grayscale', 'indexed', 'RGB', 'CMYK', 'multichannel', 'duotone', 'lab'];
function setupGrayscale(data) {
var size = data.width * data.height * 4;
for (var i = 0; i < size; i += 4) {
data.data[i + 1] = data.data[i];
data.data[i + 2] = data.data[i];
}
}
export function createReader(buffer, offset, length) {
var view = new DataView(buffer, offset, length);
return { view: view, offset: 0, strict: false, debug: false };
}
export function warnOrThrow(reader, message) {
if (reader.strict)
throw new Error(message);
if (reader.debug)
console.warn(message);
}
export function readUint8(reader) {
reader.offset += 1;
return reader.view.getUint8(reader.offset - 1);
}
export function peekUint8(reader) {
return reader.view.getUint8(reader.offset);
}
export function readInt16(reader) {
reader.offset += 2;
return reader.view.getInt16(reader.offset - 2, false);
}
export function readUint16(reader) {
reader.offset += 2;
return reader.view.getUint16(reader.offset - 2, false);
}
export function readInt32(reader) {
reader.offset += 4;
return reader.view.getInt32(reader.offset - 4, false);
}
export function readInt32LE(reader) {
reader.offset += 4;
return reader.view.getInt32(reader.offset - 4, true);
}
export function readUint32(reader) {
reader.offset += 4;
return reader.view.getUint32(reader.offset - 4, false);
}
export function readFloat32(reader) {
reader.offset += 4;
return reader.view.getFloat32(reader.offset - 4, false);
}
export function readFloat64(reader) {
reader.offset += 8;
return reader.view.getFloat64(reader.offset - 8, false);
}
// 32-bit fixed-point number 16.16
export function readFixedPoint32(reader) {
return readInt32(reader) / (1 << 16);
}
// 32-bit fixed-point number 8.24
export function readFixedPointPath32(reader) {
return readInt32(reader) / (1 << 24);
}
export function readBytes(reader, length) {
var start = reader.view.byteOffset + reader.offset;
reader.offset += length;
if ((start + length) > reader.view.buffer.byteLength) {
// fix for broken PSD files that are missing part of file at the end
warnOrThrow(reader, 'Reading bytes exceeding buffer length');
if (length > (100 * 1024 * 1024))
throw new Error('Reading past end of file'); // limit to 100MB
var result = new Uint8Array(length);
var len = Math.min(length, reader.view.byteLength - start);
if (len > 0)
result.set(new Uint8Array(reader.view.buffer, start, len));
return result;
}
else {
return new Uint8Array(reader.view.buffer, start, length);
}
}
export function readSignature(reader) {
return readShortString(reader, 4);
}
export function readPascalString(reader, padTo) {
var length = readUint8(reader);
var text = length ? readShortString(reader, length) : '';
while (++length % padTo) {
reader.offset++;
}
return text;
}
export function readUnicodeString(reader) {
var length = readUint32(reader);
return readUnicodeStringWithLength(reader, length);
}
export function readUnicodeStringWithLength(reader, length) {
var text = '';
while (length--) {
var value = readUint16(reader);
if (value || length > 0) { // remove trailing \0
text += String.fromCharCode(value);
}
}
return text;
}
export function readAsciiString(reader, length) {
var text = '';
while (length--) {
text += String.fromCharCode(readUint8(reader));
}
return text;
}
export function skipBytes(reader, count) {
reader.offset += count;
}
export function checkSignature(reader, a, b) {
var offset = reader.offset;
var signature = readSignature(reader);
if (signature !== a && signature !== b) {
throw new Error("Invalid signature: '".concat(signature, "' at 0x").concat(offset.toString(16)));
}
}
function readShortString(reader, length) {
var buffer = readBytes(reader, length);
var result = '';
for (var i = 0; i < buffer.length; i++) {
result += String.fromCharCode(buffer[i]);
}
return result;
}
function isValidSignature(sig) {
return sig === '8BIM' || sig === 'MeSa' || sig === 'AgHg' || sig === 'PHUT' || sig === 'DCSR';
}
export function readPsd(reader, options) {
var _a;
if (options === void 0) { options = {}; }
// header
checkSignature(reader, '8BPS');
var version = readUint16(reader);
if (version !== 1 && version !== 2)
throw new Error("Invalid PSD file version: ".concat(version));
skipBytes(reader, 6);
var channels = readUint16(reader);
var height = readUint32(reader);
var width = readUint32(reader);
var bitsPerChannel = readUint16(reader);
var colorMode = readUint16(reader);
var maxSize = version === 1 ? 30000 : 300000;
if (width > maxSize || height > maxSize)
throw new Error("Invalid size");
if (channels > 16)
throw new Error("Invalid channel count");
if (bitsPerChannel > 32)
throw new Error("Invalid bitsPerChannel count");
if (supportedColorModes.indexOf(colorMode) === -1)
throw new Error("Color mode not supported: ".concat((_a = colorModes[colorMode]) !== null && _a !== void 0 ? _a : colorMode));
var psd = { width: width, height: height, channels: channels, bitsPerChannel: bitsPerChannel, colorMode: colorMode };
var opt = __assign(__assign({}, options), { large: version === 2 });
var fixOffsets = [0, 1, -1, 2, -2, 3, -3, 4, -4];
// color mode data
readSection(reader, 1, function (left) {
if (opt.throwForMissingFeatures)
throw new Error('Color mode data not supported');
skipBytes(reader, left());
});
// image resources
readSection(reader, 1, function (left) {
var _loop_1 = function () {
var sigOffset = reader.offset;
var sig = '';
// attempt to fix broken document by realigning with the signature
for (var _i = 0, fixOffsets_1 = fixOffsets; _i < fixOffsets_1.length; _i++) {
var offset = fixOffsets_1[_i];
try {
reader.offset = sigOffset + offset;
sig = readSignature(reader);
}
catch (_a) { }
if (isValidSignature(sig))
break;
}
if (!isValidSignature(sig)) {
throw new Error("Invalid signature: '".concat(sig, "' at 0x").concat((sigOffset).toString(16)));
}
var id = readUint16(reader);
readPascalString(reader, 2); // name
readSection(reader, 2, function (left) {
var handler = resourceHandlersMap[id];
var skip = id === 1036 && !!opt.skipThumbnail;
if (!psd.imageResources) {
psd.imageResources = {};
}
if (handler && !skip) {
try {
handler.read(reader, psd.imageResources, left, opt);
}
catch (e) {
if (opt.throwForMissingFeatures)
throw e;
skipBytes(reader, left());
}
}
else {
// options.logMissingFeatures && console.log(`Unhandled image resource: ${id}`);
skipBytes(reader, left());
}
});
};
while (left()) {
_loop_1();
}
});
// layer and mask info
var globalAlpha = false;
readSection(reader, 1, function (left) {
globalAlpha = readLayerInfo(reader, psd, opt);
// SAI does not include this section
if (left() > 0) {
var globalLayerMaskInfo = readGlobalLayerMaskInfo(reader);
if (globalLayerMaskInfo)
psd.globalLayerMaskInfo = globalLayerMaskInfo;
}
else {
// revert back to end of section if exceeded section limits
// opt.logMissingFeatures && console.log('reverting to end of section');
skipBytes(reader, left());
}
while (left() > 0) {
// sometimes there are empty bytes here
while (left() && peekUint8(reader) === 0) {
// opt.logMissingFeatures && console.log('skipping 0 byte');
skipBytes(reader, 1);
}
if (left() >= 12) {
readAdditionalLayerInfo(reader, psd, psd, opt);
}
else {
// opt.logMissingFeatures && console.log('skipping leftover bytes', left());
skipBytes(reader, left());
}
}
}, undefined, opt.large);
var hasChildren = psd.children && psd.children.length;
var skipComposite = opt.skipCompositeImageData && (opt.skipLayerImageData || hasChildren);
if (!skipComposite) {
readImageData(reader, psd, globalAlpha, opt);
}
// TODO: show converted color mode instead of original PSD file color mode
// but add option to preserve file color mode (need to return image data instead of canvas in that case)
// psd.colorMode = ColorMode.RGB; // we convert all color modes to RGB
return psd;
}
function readLayerInfo(reader, psd, options) {
var globalAlpha = false;
readSection(reader, 2, function (left) {
var layerCount = readInt16(reader);
if (layerCount < 0) {
globalAlpha = true;
layerCount = -layerCount;
}
var layers = [];
var layerChannels = [];
for (var i = 0; i < layerCount; i++) {
var _a = readLayerRecord(reader, psd, options), layer = _a.layer, channels = _a.channels;
layers.push(layer);
layerChannels.push(channels);
}
if (!options.skipLayerImageData) {
for (var i = 0; i < layerCount; i++) {
readLayerChannelImageData(reader, psd, layers[i], layerChannels[i], options);
}
}
skipBytes(reader, left());
if (!psd.children)
psd.children = [];
var stack = [psd];
for (var i = layers.length - 1; i >= 0; i--) {
var l = layers[i];
var type = l.sectionDivider ? l.sectionDivider.type : 0 /* SectionDividerType.Other */;
if (type === 1 /* SectionDividerType.OpenFolder */ || type === 2 /* SectionDividerType.ClosedFolder */) {
l.opened = type === 1 /* SectionDividerType.OpenFolder */;
l.children = [];
stack[stack.length - 1].children.unshift(l);
stack.push(l);
}
else if (type === 3 /* SectionDividerType.BoundingSectionDivider */) {
stack.pop();
// this was workaround because I didn't know what `lsdk` section was, now it's probably not needed anymore
// } else if (l.name === '</Layer group>' && !l.sectionDivider && !l.top && !l.left && !l.bottom && !l.right) {
// // sometimes layer group terminator doesn't have sectionDivider, so we just guess here (PS bug ?)
// stack.pop();
}
else {
stack[stack.length - 1].children.unshift(l);
}
}
}, undefined, options.large);
return globalAlpha;
}
function readLayerRecord(reader, psd, options) {
var layer = {};
layer.top = readInt32(reader);
layer.left = readInt32(reader);
layer.bottom = readInt32(reader);
layer.right = readInt32(reader);
var channelCount = readUint16(reader);
var channels = [];
for (var i = 0; i < channelCount; i++) {
var channelID = readInt16(reader);
var channelLength = readUint32(reader);
if (options.large) {
if (channelLength !== 0)
throw new Error('Sizes larger than 4GB are not supported');
channelLength = readUint32(reader);
}
channels.push({ id: channelID, length: channelLength });
}
checkSignature(reader, '8BIM');
var blendMode = readSignature(reader);
if (!toBlendMode[blendMode])
throw new Error("Invalid blend mode: '".concat(blendMode, "'"));
layer.blendMode = toBlendMode[blendMode];
layer.opacity = readUint8(reader) / 0xff;
layer.clipping = readUint8(reader) === 1;
var flags = readUint8(reader);
layer.transparencyProtected = (flags & 0x01) !== 0;
layer.hidden = (flags & 0x02) !== 0;
// 0x04 - obsolete
// 0x08 - 1 for Photoshop 5.0 and later, tells if bit 4 has useful information
// 0x10 - pixel data irrelevant to appearance of document
// 0x20 - ???
// if (flags & 0x20) (layer as any)._2 = true; // TEMP !!!!
skipBytes(reader, 1);
readSection(reader, 1, function (left) {
var mask = readLayerMaskData(reader, options);
if (mask)
layer.mask = mask;
/*const blendingRanges =*/ readLayerBlendingRanges(reader);
layer.name = readPascalString(reader, 4);
while (left()) {
readAdditionalLayerInfo(reader, layer, psd, options);
}
});
return { layer: layer, channels: channels };
}
function readLayerMaskData(reader, options) {
return readSection(reader, 1, function (left) {
if (!left())
return undefined;
var mask = {};
mask.top = readInt32(reader);
mask.left = readInt32(reader);
mask.bottom = readInt32(reader);
mask.right = readInt32(reader);
mask.defaultColor = readUint8(reader);
var flags = readUint8(reader);
mask.positionRelativeToLayer = (flags & 1 /* LayerMaskFlags.PositionRelativeToLayer */) !== 0;
mask.disabled = (flags & 2 /* LayerMaskFlags.LayerMaskDisabled */) !== 0;
mask.fromVectorData = (flags & 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */) !== 0;
if (flags & 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */) {
var params = readUint8(reader);
if (params & 1 /* MaskParams.UserMaskDensity */)
mask.userMaskDensity = readUint8(reader) / 0xff;
if (params & 2 /* MaskParams.UserMaskFeather */)
mask.userMaskFeather = readFloat64(reader);
if (params & 4 /* MaskParams.VectorMaskDensity */)
mask.vectorMaskDensity = readUint8(reader) / 0xff;
if (params & 8 /* MaskParams.VectorMaskFeather */)
mask.vectorMaskFeather = readFloat64(reader);
}
if (left() > 2) {
options.logMissingFeatures && console.log('Unhandled extra mask params');
// TODO: handle these values
/*const realFlags =*/ readUint8(reader);
/*const realUserMaskBackground =*/ readUint8(reader);
/*const top2 =*/ readInt32(reader);
/*const left2 =*/ readInt32(reader);
/*const bottom2 =*/ readInt32(reader);
/*const right2 =*/ readInt32(reader);
}
skipBytes(reader, left());
return mask;
});
}
function readLayerBlendingRanges(reader) {
return readSection(reader, 1, function (left) {
var compositeGrayBlendSource = readUint32(reader);
var compositeGraphBlendDestinationRange = readUint32(reader);
var ranges = [];
while (left()) {
var sourceRange = readUint32(reader);
var destRange = readUint32(reader);
ranges.push({ sourceRange: sourceRange, destRange: destRange });
}
return { compositeGrayBlendSource: compositeGrayBlendSource, compositeGraphBlendDestinationRange: compositeGraphBlendDestinationRange, ranges: ranges };
});
}
function readLayerChannelImageData(reader, psd, layer, channels, options) {
var layerWidth = (layer.right || 0) - (layer.left || 0);
var layerHeight = (layer.bottom || 0) - (layer.top || 0);
var cmyk = psd.colorMode === 4 /* ColorMode.CMYK */;
var imageData;
if (layerWidth && layerHeight) {
if (cmyk) {
imageData = { width: layerWidth, height: layerHeight, data: new Uint8ClampedArray(layerWidth * layerHeight * 5) };
for (var p = 4; p < imageData.data.byteLength; p += 5)
imageData.data[p] = 255;
}
else {
imageData = createImageData(layerWidth, layerHeight);
resetImageData(imageData);
}
}
if (RAW_IMAGE_DATA)
layer.imageDataRaw = [];
for (var _i = 0, channels_1 = channels; _i < channels_1.length; _i++) {
var channel = channels_1[_i];
if (channel.length === 0)
continue;
if (channel.length < 2)
throw new Error('Invalid channel length');
var start = reader.offset;
var compression = readUint16(reader);
// try to fix broken files where there's 1 byte shift of channel
if (compression > 3) {
reader.offset -= 1;
compression = readUint16(reader);
}
// try to fix broken files where there's 1 byte shift of channel
if (compression > 3) {
reader.offset -= 3;
compression = readUint16(reader);
}
if (compression > 3)
throw new Error("Invalid compression: ".concat(compression));
if (channel.id === -2 /* ChannelID.UserMask */) {
var mask = layer.mask;
if (!mask)
throw new Error("Missing layer mask data");
var maskWidth = (mask.right || 0) - (mask.left || 0);
var maskHeight = (mask.bottom || 0) - (mask.top || 0);
if (maskWidth && maskHeight) {
var maskData = createImageData(maskWidth, maskHeight);
resetImageData(maskData);
var start_1 = reader.offset;
readData(reader, channel.length, maskData, compression, maskWidth, maskHeight, 0, options.large, 4);
if (RAW_IMAGE_DATA) {
layer.maskDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start_1, reader.offset - start_1);
}
setupGrayscale(maskData);
if (options.useImageData) {
mask.imageData = maskData;
}
else {
mask.canvas = createCanvas(maskWidth, maskHeight);
mask.canvas.getContext('2d').putImageData(maskData, 0, 0);
}
}
}
else {
var offset = offsetForChannel(channel.id, cmyk);
var targetData = imageData;
if (offset < 0) {
targetData = undefined;
if (options.throwForMissingFeatures) {
throw new Error("Channel not supported: ".concat(channel.id));
}
}
readData(reader, channel.length, targetData, compression, layerWidth, layerHeight, offset, options.large, cmyk ? 5 : 4);
if (RAW_IMAGE_DATA) {
layer.imageDataRaw[channel.id] = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start + 2, channel.length - 2);
}
reader.offset = start + channel.length;
if (targetData && psd.colorMode === 1 /* ColorMode.Grayscale */) {
setupGrayscale(targetData);
}
}
}
if (imageData) {
if (cmyk) {
var cmykData = imageData;
imageData = createImageData(cmykData.width, cmykData.height);
cmykToRgb(cmykData, imageData, false);
}
if (options.useImageData) {
layer.imageData = imageData;
}
else {
layer.canvas = createCanvas(layerWidth, layerHeight);
layer.canvas.getContext('2d').putImageData(imageData, 0, 0);
}
}
}
function readData(reader, length, data, compression, width, height, offset, large, step) {
if (compression === 0 /* Compression.RawData */) {
readDataRaw(reader, data, width, height, step, offset);
}
else if (compression === 1 /* Compression.RleCompressed */) {
readDataRLE(reader, data, width, height, step, [offset], large);
}
else if (compression === 2 /* Compression.ZipWithoutPrediction */) {
readDataZipWithoutPrediction(reader, length, data, width, height, step, offset);
}
else if (compression === 3 /* Compression.ZipWithPrediction */) {
throw new Error("Compression type not supported: ".concat(compression));
}
else {
throw new Error("Invalid Compression type: ".concat(compression));
}
}
function readGlobalLayerMaskInfo(reader) {
return readSection(reader, 1, function (left) {
if (!left())
return undefined;
var overlayColorSpace = readUint16(reader);
var colorSpace1 = readUint16(reader);
var colorSpace2 = readUint16(reader);
var colorSpace3 = readUint16(reader);
var colorSpace4 = readUint16(reader);
var opacity = readUint16(reader) / 0xff;
var kind = readUint8(reader);
skipBytes(reader, left()); // 3 bytes of padding ?
return { overlayColorSpace: overlayColorSpace, colorSpace1: colorSpace1, colorSpace2: colorSpace2, colorSpace3: colorSpace3, colorSpace4: colorSpace4, opacity: opacity, kind: kind };
});
}
function readAdditionalLayerInfo(reader, target, psd, options) {
var sig = readSignature(reader);
if (sig !== '8BIM' && sig !== '8B64')
throw new Error("Invalid signature: '".concat(sig, "' at 0x").concat((reader.offset - 4).toString(16)));
var key = readSignature(reader);
// `largeAdditionalInfoKeys` fallback, because some keys don't have 8B64 signature even when they are 64bit
var u64 = sig === '8B64' || (options.large && largeAdditionalInfoKeys.indexOf(key) !== -1);
readSection(reader, 2, function (left) {
var handler = infoHandlersMap[key];
if (handler) {
try {
handler.read(reader, target, left, psd, options);
}
catch (e) {
if (options.throwForMissingFeatures)
throw e;
}
}
else {
options.logMissingFeatures && console.log("Unhandled additional info: ".concat(key));
skipBytes(reader, left());
}
if (left()) {
options.logMissingFeatures && console.log("Unread ".concat(left(), " bytes left for additional info: ").concat(key));
skipBytes(reader, left());
}
}, false, u64);
}
function readImageData(reader, psd, globalAlpha, options) {
var compression = readUint16(reader);
if (supportedColorModes.indexOf(psd.colorMode) === -1)
throw new Error("Color mode not supported: ".concat(psd.colorMode));
if (compression !== 0 /* Compression.RawData */ && compression !== 1 /* Compression.RleCompressed */)
throw new Error("Compression type not supported: ".concat(compression));
var imageData = createImageData(psd.width, psd.height);
resetImageData(imageData);
switch (psd.colorMode) {
case 0 /* ColorMode.Bitmap */: {
var bytes = void 0;
if (compression === 0 /* Compression.RawData */) {
bytes = readBytes(reader, Math.ceil(psd.width / 8) * psd.height);
}
else if (compression === 1 /* Compression.RleCompressed */) {
bytes = new Uint8Array(psd.width * psd.height);
readDataRLE(reader, { data: bytes, width: psd.width, height: psd.height }, psd.width, psd.height, 1, [0], options.large);
}
else {
throw new Error("Bitmap compression not supported: ".concat(compression));
}
decodeBitmap(bytes, imageData.data, psd.width, psd.height);
break;
}
case 3 /* ColorMode.RGB */:
case 1 /* ColorMode.Grayscale */: {
var channels = psd.colorMode === 1 /* ColorMode.Grayscale */ ? [0] : [0, 1, 2];
if (psd.channels && psd.channels > 3) {
for (var i = 3; i < psd.channels; i++) {
// TODO: store these channels in additional image data
channels.push(i);
}
}
else if (globalAlpha) {
channels.push(3);
}
if (compression === 0 /* Compression.RawData */) {
for (var i = 0; i < channels.length; i++) {
readDataRaw(reader, imageData, psd.width, psd.height, 4, channels[i]);
}
}
else if (compression === 1 /* Compression.RleCompressed */) {
var start = reader.offset;
readDataRLE(reader, imageData, psd.width, psd.height, 4, channels, options.large);
if (RAW_IMAGE_DATA)
psd.imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
}
if (psd.colorMode === 1 /* ColorMode.Grayscale */) {
setupGrayscale(imageData);
}
break;
}
case 4 /* ColorMode.CMYK */: {
if (psd.channels !== 4)
throw new Error("Invalid channel count");
var channels = [0, 1, 2, 3];
if (globalAlpha)
channels.push(4);
if (compression === 0 /* Compression.RawData */) {
throw new Error("Not implemented");
// TODO: ...
// for (let i = 0; i < channels.length; i++) {
// readDataRaw(reader, imageData, channels[i], psd.width, psd.height);
// }
}
else if (compression === 1 /* Compression.RleCompressed */) {
var cmykImageData = {
width: imageData.width,
height: imageData.height,
data: new Uint8Array(imageData.width * imageData.height * 5),
};
var start = reader.offset;
readDataRLE(reader, cmykImageData, psd.width, psd.height, 5, channels, options.large);
cmykToRgb(cmykImageData, imageData, true);
if (RAW_IMAGE_DATA)
psd.imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
}
break;
}
default: throw new Error("Color mode not supported: ".concat(psd.colorMode));
}
// remove weird white matte
if (globalAlpha) {
var p = imageData.data;
var size = imageData.width * imageData.height * 4;
for (var i = 0; i < size; i += 4) {
var pa = p[i + 3];
if (pa != 0 && pa != 255) {
var a = pa / 255;
var ra = 1 / a;
var invA = 255 * (1 - ra);
p[i + 0] = p[i + 0] * ra + invA;
p[i + 1] = p[i + 1] * ra + invA;
p[i + 2] = p[i + 2] * ra + invA;
}
}
}
if (options.useImageData) {
psd.imageData = imageData;
}
else {
psd.canvas = createCanvas(psd.width, psd.height);
psd.canvas.getContext('2d').putImageData(imageData, 0, 0);
}
}
function cmykToRgb(cmyk, rgb, reverseAlpha) {
var size = rgb.width * rgb.height * 4;
var srcData = cmyk.data;
var dstData = rgb.data;
for (var src = 0, dst = 0; dst < size; src += 5, dst += 4) {
var c = srcData[src];
var m = srcData[src + 1];
var y = srcData[src + 2];
var k = srcData[src + 3];
dstData[dst] = ((((c * k) | 0) / 255) | 0);
dstData[dst + 1] = ((((m * k) | 0) / 255) | 0);
dstData[dst + 2] = ((((y * k) | 0) / 255) | 0);
dstData[dst + 3] = reverseAlpha ? 255 - srcData[src + 4] : srcData[src + 4];
}
// for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
// const c = 1 - (srcData[src + 0] / 255);
// const m = 1 - (srcData[src + 1] / 255);
// const y = 1 - (srcData[src + 2] / 255);
// // const k = srcData[src + 3] / 255;
// dstData[dst + 0] = ((1 - c * 0.8) * 255) | 0;
// dstData[dst + 1] = ((1 - m * 0.8) * 255) | 0;
// dstData[dst + 2] = ((1 - y * 0.8) * 255) | 0;
// dstData[dst + 3] = reverseAlpha ? 255 - srcData[src + 4] : srcData[src + 4];
// }
}
function readDataRaw(reader, pixelData, width, height, step, offset) {
var size = width * height;
var buffer = readBytes(reader, size);
if (pixelData && offset < step) {
var data = pixelData.data;
for (var i = 0, p = offset | 0; i < size; i++, p = (p + step) | 0) {
data[p] = buffer[i];
}
}
}
export function readDataZipWithoutPrediction(reader, length, pixelData, width, height, step, offset) {
var compressed = readBytes(reader, length);
var decompressed = inflate(compressed);
var size = width * height;
if (pixelData && offset < step) {
var data = pixelData.data;
for (var i = 0, p = offset | 0; i < size; i++, p = (p + step) | 0) {
data[p] = decompressed[i];
}
}
}
export function readDataRLE(reader, pixelData, _width, height, step, offsets, large) {
var data = pixelData && pixelData.data;
var lengths;
if (large) {
lengths = new Uint32Array(offsets.length * height);
for (var o = 0, li = 0; o < offsets.length; o++) {
for (var y = 0; y < height; y++, li++) {
lengths[li] = readUint32(reader);
}
}
}
else {
lengths = new Uint16Array(offsets.length * height);
for (var o = 0, li = 0; o < offsets.length; o++) {
for (var y = 0; y < height; y++, li++) {
lengths[li] = readUint16(reader);
}
}
}
var extraLimit = (step - 1) | 0; // 3 for rgb, 4 for cmyk
for (var c = 0, li = 0; c < offsets.length; c++) {
var offset = offsets[c] | 0;
var extra = c > extraLimit || offset > extraLimit;
if (!data || extra) {
for (var y = 0; y < height; y++, li++) {
skipBytes(reader, lengths[li]);
}
}
else {
for (var y = 0, p = offset | 0; y < height; y++, li++) {
var length_1 = lengths[li];
var buffer = readBytes(reader, length_1);
for (var i = 0; i < length_1; i++) {
var header = buffer[i];
if (header > 128) {
var value = buffer[++i];
header = (256 - header) | 0;
for (var j = 0; j <= header; j = (j + 1) | 0) {
data[p] = value;
p = (p + step) | 0;
}
}
else if (header < 128) {
for (var j = 0; j <= header; j = (j + 1) | 0) {
data[p] = buffer[++i];
p = (p + step) | 0;
}
}
else {
// ignore 128
}
// This showed up on some images from non-photoshop programs, ignoring it seems to work just fine.
// if (i >= length) throw new Error(`Invalid RLE data: exceeded buffer size ${i}/${length}`);
}
}
}
}
}
export function readSection(reader, round, func, skipEmpty, eightBytes) {
if (skipEmpty === void 0) { skipEmpty = true; }
if (eightBytes === void 0) { eightBytes = false; }
var length = readUint32(reader);
if (eightBytes) {
if (length !== 0)
throw new Error('Sizes larger than 4GB are not supported');
length = readUint32(reader);
}
if (length <= 0 && skipEmpty)
return undefined;
var end = reader.offset + length;
if (end > reader.view.byteLength)
throw new Error('Section exceeds file size');
var result = func(function () { return end - reader.offset; });
if (reader.offset !== end) {
if (reader.offset > end) {
warnOrThrow(reader, 'Exceeded section limits');
}
else {
warnOrThrow(reader, "Unread section data"); // : ${end - reader.offset} bytes at 0x${reader.offset.toString(16)}`);
}
}
while (end % round)
end++;
reader.offset = end;
return result;
}
export function readColor(reader) {
var colorSpace = readUint16(reader);
switch (colorSpace) {
case 0 /* ColorSpace.RGB */: {
var r = readUint16(reader) / 257;
var g = readUint16(reader) / 257;
var b = readUint16(reader) / 257;
skipBytes(reader, 2);
return { r: r, g: g, b: b };
}
case 1 /* ColorSpace.HSB */: {
var h = readUint16(reader) / 0xffff;
var s = readUint16(reader) / 0xffff;
var b = readUint16(reader) / 0xffff;
skipBytes(reader, 2);
return { h: h, s: s, b: b };
}
case 2 /* ColorSpace.CMYK */: {
var c = readUint16(reader) / 257;
var m = readUint16(reader) / 257;
var y = readUint16(reader) / 257;
var k = readUint16(reader) / 257;
return { c: c, m: m, y: y, k: k };
}
case 7 /* ColorSpace.Lab */: {
var l = readInt16(reader) / 10000;
var ta = readInt16(reader);
var tb = readInt16(reader);
var a = ta < 0 ? (ta / 12800) : (ta / 12700);
var b = tb < 0 ? (tb / 12800) : (tb / 12700);
skipBytes(reader, 2);
return { l: l, a: a, b: b };
}
case 8 /* ColorSpace.Grayscale */: {
var k = readUint16(reader) * 255 / 10000;
skipBytes(reader, 6);
return { k: k };
}
default:
throw new Error('Invalid color space');
}
}
export function readPattern(reader) {
readUint32(reader); // length
var version = readUint32(reader);
if (version !== 1)
throw new Error("Invalid pattern version: ".concat(version));
var colorMode = readUint32(reader);
var x = readInt16(reader);
var y = readInt16(reader);
// we only support RGB and grayscale for now
if (colorMode !== 3 /* ColorMode.RGB */ && colorMode !== 1 /* ColorMode.Grayscale */ && colorMode !== 2 /* ColorMode.Indexed */) {
throw new Error("Unsupported pattern color mode: ".concat(colorMode));
}
var name = readUnicodeString(reader);
var id = readPascalString(reader, 1);
var palette = [];
if (colorMode === 2 /* ColorMode.Indexed */) {
for (var i = 0; i < 256; i++) {
palette.push({
r: readUint8(reader),
g: readUint8(reader),
b: readUint8(reader),
});
}
skipBytes(reader, 4); // no idea what this is
}
// virtual memory array list
var version2 = readUint32(reader);
if (version2 !== 3)
throw new Error("Invalid pattern VMAL version: ".concat(version2));
readUint32(reader); // length
var top = readUint32(reader);
var left = readUint32(reader);
var bottom = readUint32(reader);
var right = readUint32(reader);
var channelsCount = readUint32(reader);
var width = right - left;
var height = bottom - top;
var data = new Uint8Array(width * height * 4);
for (var i = 3; i < data.byteLength; i += 4) {
data[i] = 255;
}
for (var i = 0, ch = 0; i < (channelsCount + 2); i++) {
var has = readUint32(reader);
if (!has)
continue;
var length_2 = readUint32(reader);
var pixelDepth = readUint32(reader);
var ctop = readUint32(reader);
var cleft = readUint32(reader);
var cbottom = readUint32(reader);
var cright = readUint32(reader);
var pixelDepth2 = readUint16(reader);
var compressionMode = readUint8(reader); // 0 - raw, 1 - zip
var dataLength = length_2 - (4 + 16 + 2 + 1);
var cdata = readBytes(reader, dataLength);
if (pixelDepth !== 8 || pixelDepth2 !== 8) {
throw new Error('16bit pixel depth not supported for patterns');
}
var w = cright - cleft;
var h = cbottom - ctop;
var ox = cleft - left;
var oy = ctop - top;
if (compressionMode === 0) {
if (colorMode === 3 /* ColorMode.RGB */ && ch < 3) {
for (var y_1 = 0; y_1 < h; y_1++) {
for (var x_1 = 0; x_1 < w; x_1++) {
var src = x_1 + y_1 * w;
var dst = (ox + x_1 + (y_1 + oy) * width) * 4;
data[dst + ch] = cdata[src];
}
}
}
if (colorMode === 1 /* ColorMode.Grayscale */ && ch < 1) {
for (var y_2 = 0; y_2 < h; y_2++) {
for (var x_2 = 0; x_2 < w; x_2++) {
var src = x_2 + y_2 * w;
var dst = (ox + x_2 + (y_2 + oy) * width) * 4;
var value = cdata[src];
data[dst + 0] = value;
data[dst + 1] = value;
data[dst + 2] = value;
}
}
}
if (colorMode === 2 /* ColorMode.Indexed */) {
// TODO:
throw new Error('Indexed pattern color mode not implemented');
}
}
else if (compressionMode === 1) {
// console.log({ colorMode });
// require('fs').writeFileSync('zip.bin', Buffer.from(cdata));
// const data = require('zlib').inflateRawSync(cdata);
// const data = require('zlib').unzipSync(cdata);
// console.log(data);
// throw new Error('Zip compression not supported for pattern');
// throw new Error('Unsupported pattern compression');
console.error('Unsupported pattern compression');
name += ' (failed to decode)';
}
else {
throw new Error('Invalid pattern compression mode');
}
ch++;
}
// TODO: use canvas instead of data ?
return { id: id, name: name, x: x, y: y, bounds: { x: left, y: top, w: width, h: height }, data: data };
}
//# sourceMappingURL=psdReader.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,27 @@
import { Psd, WriteOptions, Color } from './psd';
export interface PsdWriter {
offset: number;
buffer: ArrayBuffer;
view: DataView;
}
export declare function createWriter(size?: number): PsdWriter;
export declare function getWriterBuffer(writer: PsdWriter): ArrayBuffer;
export declare function getWriterBufferNoCopy(writer: PsdWriter): Uint8Array;
export declare function writeUint8(writer: PsdWriter, value: number): void;
export declare function writeInt16(writer: PsdWriter, value: number): void;
export declare function writeUint16(writer: PsdWriter, value: number): void;
export declare function writeInt32(writer: PsdWriter, value: number): void;
export declare function writeUint32(writer: PsdWriter, value: number): void;
export declare function writeFloat32(writer: PsdWriter, value: number): void;
export declare function writeFloat64(writer: PsdWriter, value: number): void;
export declare function writeFixedPoint32(writer: PsdWriter, value: number): void;
export declare function writeFixedPointPath32(writer: PsdWriter, value: number): void;
export declare function writeBytes(writer: PsdWriter, buffer: Uint8Array | undefined): void;
export declare function writeZeros(writer: PsdWriter, count: number): void;
export declare function writeSignature(writer: PsdWriter, signature: string): void;
export declare function writePascalString(writer: PsdWriter, text: string, padTo: number): void;
export declare function writeUnicodeString(writer: PsdWriter, text: string): void;
export declare function writeUnicodeStringWithPadding(writer: PsdWriter, text: string): void;
export declare function writeSection(writer: PsdWriter, round: number, func: () => void, writeTotalLength?: boolean, large?: boolean): void;
export declare function writePsd(writer: PsdWriter, psd: Psd, options?: WriteOptions): void;
export declare function writeColor(writer: PsdWriter, color: Color | undefined): void;

View File

@@ -0,0 +1,692 @@
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);
};
import { hasAlpha, createCanvas, writeDataRLE, offsetForChannel, createImageData, fromBlendMode, clamp, largeAdditionalInfoKeys, RAW_IMAGE_DATA, writeDataZipWithoutPrediction } from './helpers';
import { hasMultiEffects, infoHandlers } from './additionalInfo';
import { resourceHandlers } from './imageResources';
export function createWriter(size) {
if (size === void 0) { size = 4096; }
var buffer = new ArrayBuffer(size);
var view = new DataView(buffer);
var offset = 0;
return { buffer: buffer, view: view, offset: offset };
}
export function getWriterBuffer(writer) {
return writer.buffer.slice(0, writer.offset);
}
export function getWriterBufferNoCopy(writer) {
return new Uint8Array(writer.buffer, 0, writer.offset);
}
export function writeUint8(writer, value) {
var offset = addSize(writer, 1);
writer.view.setUint8(offset, value);
}
export function writeInt16(writer, value) {
var offset = addSize(writer, 2);
writer.view.setInt16(offset, value, false);
}
export function writeUint16(writer, value) {
var offset = addSize(writer, 2);
writer.view.setUint16(offset, value, false);
}
export function writeInt32(writer, value) {
var offset = addSize(writer, 4);
writer.view.setInt32(offset, value, false);
}
export function writeUint32(writer, value) {
var offset = addSize(writer, 4);
writer.view.setUint32(offset, value, false);
}
export function writeFloat32(writer, value) {
var offset = addSize(writer, 4);
writer.view.setFloat32(offset, value, false);
}
export function writeFloat64(writer, value) {
var offset = addSize(writer, 8);
writer.view.setFloat64(offset, value, false);
}
// 32-bit fixed-point number 16.16
export function writeFixedPoint32(writer, value) {
writeInt32(writer, value * (1 << 16));
}
// 32-bit fixed-point number 8.24
export function writeFixedPointPath32(writer, value) {
writeInt32(writer, value * (1 << 24));
}
export function writeBytes(writer, buffer) {
if (buffer) {
ensureSize(writer, writer.offset + buffer.length);
var bytes = new Uint8Array(writer.buffer);
bytes.set(buffer, writer.offset);
writer.offset += buffer.length;
}
}
export function writeZeros(writer, count) {
for (var i = 0; i < count; i++) {
writeUint8(writer, 0);
}
}
export function writeSignature(writer, signature) {
if (signature.length !== 4)
throw new Error("Invalid signature: '".concat(signature, "'"));
for (var i = 0; i < 4; i++) {
writeUint8(writer, signature.charCodeAt(i));
}
}
export function writePascalString(writer, text, padTo) {
var length = text.length;
writeUint8(writer, length);
for (var i = 0; i < length; i++) {
var code = text.charCodeAt(i);
writeUint8(writer, code < 128 ? code : '?'.charCodeAt(0));
}
while (++length % padTo) {
writeUint8(writer, 0);
}
}
export function writeUnicodeString(writer, text) {
writeUint32(writer, text.length);
for (var i = 0; i < text.length; i++) {
writeUint16(writer, text.charCodeAt(i));
}
}
export function writeUnicodeStringWithPadding(writer, text) {
writeUint32(writer, text.length + 1);
for (var i = 0; i < text.length; i++) {
writeUint16(writer, text.charCodeAt(i));
}
writeUint16(writer, 0);
}
function getLargestLayerSize(layers) {
if (layers === void 0) { layers = []; }
var max = 0;
for (var _i = 0, layers_1 = layers; _i < layers_1.length; _i++) {
var layer = layers_1[_i];
if (layer.canvas || layer.imageData) {
var _a = getLayerDimentions(layer), width = _a.width, height = _a.height;
max = Math.max(max, 2 * height + 2 * width * height);
}
if (layer.children) {
max = Math.max(max, getLargestLayerSize(layer.children));
}
}
return max;
}
export function writeSection(writer, round, func, writeTotalLength, large) {
if (writeTotalLength === void 0) { writeTotalLength = false; }
if (large === void 0) { large = false; }
if (large)
writeUint32(writer, 0);
var offset = writer.offset;
writeUint32(writer, 0);
func();
var length = writer.offset - offset - 4;
var len = length;
while ((len % round) !== 0) {
writeUint8(writer, 0);
len++;
}
if (writeTotalLength) {
length = len;
}
writer.view.setUint32(offset, length, false);
}
export function writePsd(writer, psd, options) {
if (options === void 0) { options = {}; }
if (!(+psd.width > 0 && +psd.height > 0))
throw new Error('Invalid document size');
if ((psd.width > 30000 || psd.height > 30000) && !options.psb)
throw new Error('Document size is too large (max is 30000x30000, use PSB format instead)');
var imageResources = psd.imageResources || {};
var opt = __assign(__assign({}, options), { layerIds: new Set(), layerToId: new Map() });
if (opt.generateThumbnail) {
imageResources = __assign(__assign({}, imageResources), { thumbnail: createThumbnail(psd) });
}
var imageData = psd.imageData;
if (!imageData && psd.canvas) {
imageData = psd.canvas.getContext('2d').getImageData(0, 0, psd.canvas.width, psd.canvas.height);
}
if (imageData && (psd.width !== imageData.width || psd.height !== imageData.height))
throw new Error('Document canvas must have the same size as document');
var globalAlpha = !!imageData && hasAlpha(imageData);
var maxBufferSize = Math.max(getLargestLayerSize(psd.children), 4 * 2 * psd.width * psd.height + 2 * psd.height);
var tempBuffer = new Uint8Array(maxBufferSize);
// header
writeSignature(writer, '8BPS');
writeUint16(writer, options.psb ? 2 : 1); // version
writeZeros(writer, 6);
writeUint16(writer, globalAlpha ? 4 : 3); // channels
writeUint32(writer, psd.height);
writeUint32(writer, psd.width);
writeUint16(writer, 8); // bits per channel
writeUint16(writer, 3 /* ColorMode.RGB */); // we only support saving RGB right now
// color mode data
writeSection(writer, 1, function () {
// TODO: implement
});
// image resources
writeSection(writer, 1, function () {
var _loop_1 = function (handler) {
var has = handler.has(imageResources);
var count = has === false ? 0 : (has === true ? 1 : has);
var _loop_2 = function (i) {
writeSignature(writer, '8BIM');
writeUint16(writer, handler.key);
writePascalString(writer, '', 2);
writeSection(writer, 2, function () { return handler.write(writer, imageResources, i); });
};
for (var i = 0; i < count; i++) {
_loop_2(i);
}
};
for (var _i = 0, resourceHandlers_1 = resourceHandlers; _i < resourceHandlers_1.length; _i++) {
var handler = resourceHandlers_1[_i];
_loop_1(handler);
}
});
// layer and mask info
writeSection(writer, 2, function () {
writeLayerInfo(tempBuffer, writer, psd, globalAlpha, opt);
writeGlobalLayerMaskInfo(writer, psd.globalLayerMaskInfo);
writeAdditionalLayerInfo(writer, psd, psd, opt);
}, undefined, !!opt.psb);
// image data
var channels = globalAlpha ? [0, 1, 2, 3] : [0, 1, 2];
var width = imageData ? imageData.width : psd.width;
var height = imageData ? imageData.height : psd.height;
var data = { data: new Uint8Array(width * height * 4), width: width, height: height };
writeUint16(writer, 1 /* Compression.RleCompressed */); // Photoshop doesn't support zip compression of composite image data
if (RAW_IMAGE_DATA && psd.imageDataRaw) {
console.log('writing raw image data');
writeBytes(writer, psd.imageDataRaw);
}
else {
if (imageData)
data.data.set(new Uint8Array(imageData.data.buffer, imageData.data.byteOffset, imageData.data.byteLength));
// add weird white matte
if (globalAlpha) {
var size = data.width * data.height * 4;
var p = data.data;
for (var i = 0; i < size; i += 4) {
var pa = p[i + 3];
if (pa != 0 && pa != 255) {
var a = pa / 255;
var ra = 255 * (1 - a);
p[i + 0] = p[i + 0] * a + ra;
p[i + 1] = p[i + 1] * a + ra;
p[i + 2] = p[i + 2] * a + ra;
}
}
}
writeBytes(writer, writeDataRLE(tempBuffer, data, channels, !!options.psb));
}
}
function writeLayerInfo(tempBuffer, writer, psd, globalAlpha, options) {
writeSection(writer, 4, function () {
var _a;
var layers = [];
addChildren(layers, psd.children);
if (!layers.length)
layers.push({});
writeInt16(writer, globalAlpha ? -layers.length : layers.length);
var layersData = layers.map(function (l, i) { return getChannels(tempBuffer, l, i === 0, options); });
var _loop_3 = function (layerData) {
var layer = layerData.layer, top_1 = layerData.top, left = layerData.left, bottom = layerData.bottom, right = layerData.right, channels = layerData.channels;
writeInt32(writer, top_1);
writeInt32(writer, left);
writeInt32(writer, bottom);
writeInt32(writer, right);
writeUint16(writer, channels.length);
for (var _e = 0, channels_1 = channels; _e < channels_1.length; _e++) {
var c = channels_1[_e];
writeInt16(writer, c.channelId);
if (options.psb)
writeUint32(writer, 0);
writeUint32(writer, c.length);
}
writeSignature(writer, '8BIM');
writeSignature(writer, fromBlendMode[layer.blendMode] || 'norm');
writeUint8(writer, Math.round(clamp((_a = layer.opacity) !== null && _a !== void 0 ? _a : 1, 0, 1) * 255));
writeUint8(writer, layer.clipping ? 1 : 0);
var flags = 0x08; // 1 for Photoshop 5.0 and later, tells if bit 4 has useful information
if (layer.transparencyProtected)
flags |= 0x01;
if (layer.hidden)
flags |= 0x02;
if (layer.vectorMask || (layer.sectionDivider && layer.sectionDivider.type !== 0 /* SectionDividerType.Other */)) {
flags |= 0x10; // pixel data irrelevant to appearance of document
}
if (layer.effects && hasMultiEffects(layer.effects)) { // TODO: this is not correct
flags |= 0x20; // just guessing this one, might be completely incorrect
}
// if ('_2' in layer) flags |= 0x20; // TEMP!!!
writeUint8(writer, flags);
writeUint8(writer, 0); // filler
writeSection(writer, 1, function () {
writeLayerMaskData(writer, layer, layerData);
writeLayerBlendingRanges(writer, psd);
writePascalString(writer, layer.name || '', 4);
writeAdditionalLayerInfo(writer, layer, psd, options);
});
};
// layer records
for (var _i = 0, layersData_1 = layersData; _i < layersData_1.length; _i++) {
var layerData = layersData_1[_i];
_loop_3(layerData);
}
// layer channel image data
for (var _b = 0, layersData_2 = layersData; _b < layersData_2.length; _b++) {
var layerData = layersData_2[_b];
for (var _c = 0, _d = layerData.channels; _c < _d.length; _c++) {
var channel = _d[_c];
writeUint16(writer, channel.compression);
if (channel.buffer) {
writeBytes(writer, channel.buffer);
}
}
}
}, true, options.psb);
}
function writeLayerMaskData(writer, _a, layerData) {
var mask = _a.mask;
writeSection(writer, 1, function () {
if (!mask)
return;
var m = layerData.mask || {};
writeInt32(writer, m.top);
writeInt32(writer, m.left);
writeInt32(writer, m.bottom);
writeInt32(writer, m.right);
writeUint8(writer, mask.defaultColor);
var params = 0;
if (mask.userMaskDensity !== undefined)
params |= 1 /* MaskParams.UserMaskDensity */;
if (mask.userMaskFeather !== undefined)
params |= 2 /* MaskParams.UserMaskFeather */;
if (mask.vectorMaskDensity !== undefined)
params |= 4 /* MaskParams.VectorMaskDensity */;
if (mask.vectorMaskFeather !== undefined)
params |= 8 /* MaskParams.VectorMaskFeather */;
var flags = 0;
if (mask.disabled)
flags |= 2 /* LayerMaskFlags.LayerMaskDisabled */;
if (mask.positionRelativeToLayer)
flags |= 1 /* LayerMaskFlags.PositionRelativeToLayer */;
if (mask.fromVectorData)
flags |= 8 /* LayerMaskFlags.LayerMaskFromRenderingOtherData */;
if (params)
flags |= 16 /* LayerMaskFlags.MaskHasParametersAppliedToIt */;
writeUint8(writer, flags);
if (params) {
writeUint8(writer, params);
if (mask.userMaskDensity !== undefined)
writeUint8(writer, Math.round(mask.userMaskDensity * 0xff));
if (mask.userMaskFeather !== undefined)
writeFloat64(writer, mask.userMaskFeather);
if (mask.vectorMaskDensity !== undefined)
writeUint8(writer, Math.round(mask.vectorMaskDensity * 0xff));
if (mask.vectorMaskFeather !== undefined)
writeFloat64(writer, mask.vectorMaskFeather);
}
// TODO: handle rest of the fields
writeZeros(writer, 2);
});
}
function writeLayerBlendingRanges(writer, psd) {
writeSection(writer, 1, function () {
writeUint32(writer, 65535);
writeUint32(writer, 65535);
var channels = psd.channels || 0; // TODO: use always 4 instead ?
// channels = 4; // TESTING
for (var i = 0; i < channels; i++) {
writeUint32(writer, 65535);
writeUint32(writer, 65535);
}
});
}
function writeGlobalLayerMaskInfo(writer, info) {
writeSection(writer, 1, function () {
if (info) {
writeUint16(writer, info.overlayColorSpace);
writeUint16(writer, info.colorSpace1);
writeUint16(writer, info.colorSpace2);
writeUint16(writer, info.colorSpace3);
writeUint16(writer, info.colorSpace4);
writeUint16(writer, info.opacity * 0xff);
writeUint8(writer, info.kind);
writeZeros(writer, 3);
}
});
}
function writeAdditionalLayerInfo(writer, target, psd, options) {
var _loop_4 = function (handler) {
var key = handler.key;
if (key === 'Txt2' && options.invalidateTextLayers)
return "continue";
if (key === 'vmsk' && options.psb)
key = 'vsms';
if (handler.has(target)) {
var large = options.psb && largeAdditionalInfoKeys.indexOf(key) !== -1;
writeSignature(writer, large ? '8B64' : '8BIM');
writeSignature(writer, key);
var fourBytes = key === 'Txt2' || key === 'luni' || key === 'vmsk' || key === 'artb' || key === 'artd' ||
key === 'vogk' || key === 'SoLd' || key === 'lnk2' || key === 'vscg' || key === 'vsms' || key === 'GdFl' ||
key === 'lmfx' || key === 'lrFX' || key === 'cinf' || key === 'PlLd' || key === 'Anno';
writeSection(writer, fourBytes ? 4 : 2, function () {
handler.write(writer, target, psd, options);
}, key !== 'Txt2' && key !== 'cinf' && key !== 'extn', large);
}
};
for (var _i = 0, infoHandlers_1 = infoHandlers; _i < infoHandlers_1.length; _i++) {
var handler = infoHandlers_1[_i];
_loop_4(handler);
}
}
function addChildren(layers, children) {
if (!children)
return;
for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
var c = children_1[_i];
if (c.children && c.canvas)
throw new Error("Invalid layer, cannot have both 'canvas' and 'children' properties");
if (c.children && c.imageData)
throw new Error("Invalid layer, cannot have both 'imageData' and 'children' properties");
if (c.children) {
layers.push({
name: '</Layer group>',
sectionDivider: {
type: 3 /* SectionDividerType.BoundingSectionDivider */,
},
// TESTING
// nameSource: 'lset',
// id: [4, 0, 0, 8, 11, 0, 0, 0, 0, 14][layers.length] || 0,
// layerColor: 'none',
// timestamp: [1611346817.349021, 0, 0, 1611346817.349175, 1611346817.3491833, 0, 0, 0, 0, 1611346817.349832][layers.length] || 0,
// protected: {},
// referencePoint: { x: 0, y: 0 },
});
addChildren(layers, c.children);
layers.push(__assign({ sectionDivider: {
type: c.opened === false ? 2 /* SectionDividerType.ClosedFolder */ : 1 /* SectionDividerType.OpenFolder */,
key: fromBlendMode[c.blendMode] || 'pass',
subType: 0,
} }, c));
}
else {
layers.push(__assign({}, c));
}
}
}
function resizeBuffer(writer, size) {
var newLength = writer.buffer.byteLength;
do {
newLength *= 2;
} while (size > newLength);
var newBuffer = new ArrayBuffer(newLength);
var newBytes = new Uint8Array(newBuffer);
var oldBytes = new Uint8Array(writer.buffer);
newBytes.set(oldBytes);
writer.buffer = newBuffer;
writer.view = new DataView(writer.buffer);
}
function ensureSize(writer, size) {
if (size > writer.buffer.byteLength) {
resizeBuffer(writer, size);
}
}
function addSize(writer, size) {
var offset = writer.offset;
ensureSize(writer, writer.offset += size);
return offset;
}
function createThumbnail(psd) {
var canvas = createCanvas(10, 10);
var scale = 1;
if (psd.width > psd.height) {
canvas.width = 160;
canvas.height = Math.floor(psd.height * (canvas.width / psd.width));
scale = canvas.width / psd.width;
}
else {
canvas.height = 160;
canvas.width = Math.floor(psd.width * (canvas.height / psd.height));
scale = canvas.height / psd.height;
}
var context = canvas.getContext('2d');
context.scale(scale, scale);
if (psd.imageData) {
var temp = createCanvas(psd.imageData.width, psd.imageData.height);
temp.getContext('2d').putImageData(psd.imageData, 0, 0);
context.drawImage(temp, 0, 0);
}
else if (psd.canvas) {
context.drawImage(psd.canvas, 0, 0);
}
return canvas;
}
function getChannels(tempBuffer, layer, background, options) {
var layerData = getLayerChannels(tempBuffer, layer, background, options);
var mask = layer.mask;
if (mask) {
var top_2 = mask.top | 0;
var left = mask.left | 0;
var right = mask.right | 0;
var bottom = mask.bottom | 0;
var _a = getLayerDimentions(mask), width = _a.width, height = _a.height;
var imageData = mask.imageData;
if (!imageData && mask.canvas && width && height) {
imageData = mask.canvas.getContext('2d').getImageData(0, 0, width, height);
}
if (width && height && imageData) {
right = left + width;
bottom = top_2 + height;
if (imageData.width !== width || imageData.height !== height) {
throw new Error('Invalid imageData dimentions');
}
var buffer = void 0;
var compression = void 0;
if (RAW_IMAGE_DATA && layer.maskDataRaw) {
// console.log('written raw layer image data');
buffer = layer.maskDataRaw;
compression = 1 /* Compression.RleCompressed */;
}
else if (options.compress) {
buffer = writeDataZipWithoutPrediction(imageData, [0]);
compression = 2 /* Compression.ZipWithoutPrediction */;
}
else {
buffer = writeDataRLE(tempBuffer, imageData, [0], !!options.psb);
compression = 1 /* Compression.RleCompressed */;
}
layerData.mask = { top: top_2, left: left, right: right, bottom: bottom };
layerData.channels.push({ channelId: -2 /* ChannelID.UserMask */, compression: compression, buffer: buffer, length: 2 + buffer.length });
}
else {
layerData.mask = { top: 0, left: 0, right: 0, bottom: 0 };
layerData.channels.push({ channelId: -2 /* ChannelID.UserMask */, compression: 0 /* Compression.RawData */, buffer: new Uint8Array(0), length: 0 });
}
}
return layerData;
}
function getLayerDimentions(_a) {
var canvas = _a.canvas, imageData = _a.imageData;
return imageData || canvas || { width: 0, height: 0 };
}
function cropImageData(data, left, top, width, height) {
var croppedData = createImageData(width, height);
var srcData = data.data;
var dstData = croppedData.data;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var src = ((x + left) + (y + top) * width) * 4;
var dst = (x + y * width) * 4;
dstData[dst] = srcData[src];
dstData[dst + 1] = srcData[src + 1];
dstData[dst + 2] = srcData[src + 2];
dstData[dst + 3] = srcData[src + 3];
}
}
return croppedData;
}
function getLayerChannels(tempBuffer, layer, background, options) {
var _a;
var top = layer.top | 0;
var left = layer.left | 0;
var right = layer.right | 0;
var bottom = layer.bottom | 0;
var channels = [
{ channelId: -1 /* ChannelID.Transparency */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
{ channelId: 0 /* ChannelID.Color0 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
{ channelId: 1 /* ChannelID.Color1 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
{ channelId: 2 /* ChannelID.Color2 */, compression: 0 /* Compression.RawData */, buffer: undefined, length: 2 },
];
var _b = getLayerDimentions(layer), width = _b.width, height = _b.height;
if (!(layer.canvas || layer.imageData) || !width || !height) {
right = left;
bottom = top;
return { layer: layer, top: top, left: left, right: right, bottom: bottom, channels: channels };
}
right = left + width;
bottom = top + height;
var data = layer.imageData || layer.canvas.getContext('2d').getImageData(0, 0, width, height);
if (options.trimImageData) {
var trimmed = trimData(data);
if (trimmed.left !== 0 || trimmed.top !== 0 || trimmed.right !== data.width || trimmed.bottom !== data.height) {
left += trimmed.left;
top += trimmed.top;
right -= (data.width - trimmed.right);
bottom -= (data.height - trimmed.bottom);
width = right - left;
height = bottom - top;
if (!width || !height) {
return { layer: layer, top: top, left: left, right: right, bottom: bottom, channels: channels };
}
if (layer.imageData) {
data = cropImageData(data, trimmed.left, trimmed.top, width, height);
}
else {
data = layer.canvas.getContext('2d').getImageData(trimmed.left, trimmed.top, width, height);
}
}
}
var channelIds = [
0 /* ChannelID.Color0 */,
1 /* ChannelID.Color1 */,
2 /* ChannelID.Color2 */,
];
if (!background || options.noBackground || layer.mask || hasAlpha(data) || (RAW_IMAGE_DATA && ((_a = layer.imageDataRaw) === null || _a === void 0 ? void 0 : _a['-1']))) {
channelIds.unshift(-1 /* ChannelID.Transparency */);
}
channels = channelIds.map(function (channelId) {
var offset = offsetForChannel(channelId, false); // TODO: psd.colorMode === ColorMode.CMYK);
var buffer;
var compression;
if (RAW_IMAGE_DATA && layer.imageDataRaw) {
// console.log('written raw layer image data');
buffer = layer.imageDataRaw[channelId];
compression = 1 /* Compression.RleCompressed */;
}
else if (options.compress) {
buffer = writeDataZipWithoutPrediction(data, [offset]);
compression = 2 /* Compression.ZipWithoutPrediction */;
}
else {
buffer = writeDataRLE(tempBuffer, data, [offset], !!options.psb);
compression = 1 /* Compression.RleCompressed */;
}
return { channelId: channelId, compression: compression, buffer: buffer, length: 2 + buffer.length };
});
return { layer: layer, top: top, left: left, right: right, bottom: bottom, channels: channels };
}
function isRowEmpty(_a, y, left, right) {
var data = _a.data, width = _a.width;
var start = ((y * width + left) * 4 + 3) | 0;
var end = (start + (right - left) * 4) | 0;
for (var i = start; i < end; i = (i + 4) | 0) {
if (data[i] !== 0) {
return false;
}
}
return true;
}
function isColEmpty(_a, x, top, bottom) {
var data = _a.data, width = _a.width;
var stride = (width * 4) | 0;
var start = (top * stride + x * 4 + 3) | 0;
for (var y = top, i = start; y < bottom; y++, i = (i + stride) | 0) {
if (data[i] !== 0) {
return false;
}
}
return true;
}
function trimData(data) {
var top = 0;
var left = 0;
var right = data.width;
var bottom = data.height;
while (top < bottom && isRowEmpty(data, top, left, right))
top++;
while (bottom > top && isRowEmpty(data, bottom - 1, left, right))
bottom--;
while (left < right && isColEmpty(data, left, top, bottom))
left++;
while (right > left && isColEmpty(data, right - 1, top, bottom))
right--;
return { top: top, left: left, right: right, bottom: bottom };
}
export function writeColor(writer, color) {
if (!color) {
writeUint16(writer, 0 /* ColorSpace.RGB */);
writeZeros(writer, 8);
}
else if ('r' in color) {
writeUint16(writer, 0 /* ColorSpace.RGB */);
writeUint16(writer, Math.round(color.r * 257));
writeUint16(writer, Math.round(color.g * 257));
writeUint16(writer, Math.round(color.b * 257));
writeUint16(writer, 0);
}
else if ('fr' in color) {
writeUint16(writer, 0 /* ColorSpace.RGB */);
writeUint16(writer, Math.round(color.fr * 255 * 257));
writeUint16(writer, Math.round(color.fg * 255 * 257));
writeUint16(writer, Math.round(color.fb * 255 * 257));
writeUint16(writer, 0);
}
else if ('l' in color) {
writeUint16(writer, 7 /* ColorSpace.Lab */);
writeInt16(writer, Math.round(color.l * 10000));
writeInt16(writer, Math.round(color.a < 0 ? (color.a * 12800) : (color.a * 12700)));
writeInt16(writer, Math.round(color.b < 0 ? (color.b * 12800) : (color.b * 12700)));
writeUint16(writer, 0);
}
else if ('h' in color) {
writeUint16(writer, 1 /* ColorSpace.HSB */);
writeUint16(writer, Math.round(color.h * 0xffff));
writeUint16(writer, Math.round(color.s * 0xffff));
writeUint16(writer, Math.round(color.b * 0xffff));
writeUint16(writer, 0);
}
else if ('c' in color) {
writeUint16(writer, 2 /* ColorSpace.CMYK */);
writeUint16(writer, Math.round(color.c * 257));
writeUint16(writer, Math.round(color.m * 257));
writeUint16(writer, Math.round(color.y * 257));
writeUint16(writer, Math.round(color.k * 257));
}
else {
writeUint16(writer, 8 /* ColorSpace.Grayscale */);
writeUint16(writer, Math.round(color.k * 10000 / 255));
writeZeros(writer, 6);
}
}
//# sourceMappingURL=psdWriter.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,168 @@
import { LayerTextData } from './psd';
interface Adjustments {
Axis: number[];
XY: number[];
}
interface TypeValues {
Type: number;
Values: number[];
}
interface ParagraphProperties {
Justification?: number;
FirstLineIndent?: number;
StartIndent?: number;
EndIndent?: number;
SpaceBefore?: number;
SpaceAfter?: number;
AutoHyphenate?: boolean;
HyphenatedWordSize?: number;
PreHyphen?: number;
PostHyphen?: number;
ConsecutiveHyphens?: number;
Zone?: number;
WordSpacing?: number[];
LetterSpacing?: number[];
GlyphSpacing?: number[];
AutoLeading?: number;
LeadingType?: number;
Hanging?: boolean;
Burasagari?: boolean;
KinsokuOrder?: number;
EveryLineComposer?: boolean;
}
interface ParagraphSheet {
Name?: string;
DefaultStyleSheet: number;
Properties: ParagraphProperties;
}
interface StyleSheetData {
Font?: number;
FontSize?: number;
FauxBold?: boolean;
FauxItalic?: boolean;
AutoLeading?: boolean;
Leading?: number;
HorizontalScale?: number;
VerticalScale?: number;
Tracking?: number;
AutoKerning?: boolean;
Kerning?: number;
BaselineShift?: number;
FontCaps?: number;
FontBaseline?: number;
Underline?: boolean;
Strikethrough?: boolean;
Ligatures?: boolean;
DLigatures?: boolean;
BaselineDirection?: number;
Tsume?: number;
StyleRunAlignment?: number;
Language?: number;
NoBreak?: boolean;
FillColor?: TypeValues;
StrokeColor?: TypeValues;
FillFlag?: boolean;
StrokeFlag?: boolean;
FillFirst?: boolean;
YUnderline?: number;
OutlineWidth?: number;
CharacterDirection?: number;
HindiNumbers?: boolean;
Kashida?: number;
DiacriticPos?: number;
}
interface FontSet {
Name: string;
Script: number;
FontType: number;
Synthetic: number;
}
interface ResourceDict {
KinsokuSet: any[];
MojiKumiSet: any[];
TheNormalStyleSheet: number;
TheNormalParagraphSheet: number;
ParagraphSheetSet: ParagraphSheet[];
StyleSheetSet: {
Name: string;
StyleSheetData: StyleSheetData;
}[];
FontSet: FontSet[];
SuperscriptSize: number;
SuperscriptPosition: number;
SubscriptSize: number;
SubscriptPosition: number;
SmallCapSize: number;
}
interface ParagraphRun {
ParagraphSheet: ParagraphSheet;
Adjustments: Adjustments;
}
interface StyleRun {
StyleSheet: {
StyleSheetData: StyleSheetData;
};
}
interface PhotoshopNode {
ShapeType?: number;
PointBase?: number[];
BoxBounds?: number[];
Base?: {
ShapeType: number;
TransformPoint0: number[];
TransformPoint1: number[];
TransformPoint2: number[];
};
}
interface EngineData {
EngineDict: {
Editor: {
Text: string;
};
ParagraphRun: {
DefaultRunData: ParagraphRun;
RunArray: ParagraphRun[];
RunLengthArray: number[];
IsJoinable: number;
};
StyleRun: {
DefaultRunData: StyleRun;
RunArray: StyleRun[];
RunLengthArray: number[];
IsJoinable: number;
};
GridInfo: {
GridIsOn: boolean;
ShowGrid: boolean;
GridSize: number;
GridLeading: number;
GridColor: TypeValues;
GridLeadingFillColor: TypeValues;
AlignLineHeightToGridFlags: boolean;
};
AntiAlias: number;
UseFractionalGlyphWidths: boolean;
Rendered?: {
Version: number;
Shapes?: {
WritingDirection: number;
Children?: {
ShapeType?: number;
Procession: number;
Lines: {
WritingDirection: number;
Children: any[];
};
Cookie?: {
Photoshop?: PhotoshopNode;
};
}[];
};
};
};
ResourceDict: ResourceDict;
DocumentResources: ResourceDict;
}
export declare function decodeEngineData(engineData: EngineData): LayerTextData;
export declare function encodeEngineData(data: LayerTextData): EngineData;
export {};

View File

@@ -0,0 +1,554 @@
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);
};
var defaultFont = {
name: 'MyriadPro-Regular',
script: 0,
type: 0,
synthetic: 0,
};
var defaultParagraphStyle = {
justification: 'left',
firstLineIndent: 0,
startIndent: 0,
endIndent: 0,
spaceBefore: 0,
spaceAfter: 0,
autoHyphenate: true,
hyphenatedWordSize: 6,
preHyphen: 2,
postHyphen: 2,
consecutiveHyphens: 8,
zone: 36,
wordSpacing: [0.8, 1, 1.33],
letterSpacing: [0, 0, 0],
glyphSpacing: [1, 1, 1],
autoLeading: 1.2,
leadingType: 0,
hanging: false,
burasagari: false,
kinsokuOrder: 0,
everyLineComposer: false,
};
var defaultStyle = {
font: defaultFont,
fontSize: 12,
fauxBold: false,
fauxItalic: false,
autoLeading: true,
leading: 0,
horizontalScale: 1,
verticalScale: 1,
tracking: 0,
autoKerning: true,
kerning: 0,
baselineShift: 0,
fontCaps: 0,
fontBaseline: 0,
underline: false,
strikethrough: false,
ligatures: true,
dLigatures: false,
baselineDirection: 2,
tsume: 0,
styleRunAlignment: 2,
language: 0,
noBreak: false,
fillColor: { r: 0, g: 0, b: 0 },
strokeColor: { r: 0, g: 0, b: 0 },
fillFlag: true,
strokeFlag: false,
fillFirst: true,
yUnderline: 1,
outlineWidth: 1,
characterDirection: 0,
hindiNumbers: false,
kashida: 1,
diacriticPos: 2,
};
var defaultGridInfo = {
isOn: false,
show: false,
size: 18,
leading: 22,
color: { r: 0, g: 0, b: 255 },
leadingFillColor: { r: 0, g: 0, b: 255 },
alignLineHeightToGridFlags: false,
};
var paragraphStyleKeys = [
'justification', 'firstLineIndent', 'startIndent', 'endIndent', 'spaceBefore', 'spaceAfter',
'autoHyphenate', 'hyphenatedWordSize', 'preHyphen', 'postHyphen', 'consecutiveHyphens',
'zone', 'wordSpacing', 'letterSpacing', 'glyphSpacing', 'autoLeading', 'leadingType',
'hanging', 'burasagari', 'kinsokuOrder', 'everyLineComposer',
];
var styleKeys = [
'font', 'fontSize', 'fauxBold', 'fauxItalic', 'autoLeading', 'leading', 'horizontalScale',
'verticalScale', 'tracking', 'autoKerning', 'kerning', 'baselineShift', 'fontCaps', 'fontBaseline',
'underline', 'strikethrough', 'ligatures', 'dLigatures', 'baselineDirection', 'tsume',
'styleRunAlignment', 'language', 'noBreak', 'fillColor', 'strokeColor', 'fillFlag',
'strokeFlag', 'fillFirst', 'yUnderline', 'outlineWidth', 'characterDirection', 'hindiNumbers',
'kashida', 'diacriticPos',
];
var antialias = ['none', 'crisp', 'strong', 'smooth', 'sharp'];
var justification = ['left', 'right', 'center'];
function upperFirst(value) {
return value.substr(0, 1).toUpperCase() + value.substr(1);
}
function decodeColor(color) {
var c = color.Values;
if (color.Type === 0) { // grayscale
return { r: c[1] * 255, g: c[1] * 255, b: c[1] * 255 }; // , c[0] * 255];
}
else { // rgb
return { r: c[1] * 255, g: c[2] * 255, b: c[3] * 255, a: c[0] }; // , c[0] * 255];
}
}
function encodeColor(color) {
if (color && 'r' in color) {
return ['a' in color ? color.a : 1, color.r / 255, color.g / 255, color.b / 255];
}
else {
return [0, 0, 0, 0];
}
}
function arraysEqual(a, b) {
if (!a || !b)
return false;
if (a.length !== b.length)
return false;
for (var i = 0; i < a.length; i++)
if (a[i] !== b[i])
return false;
return true;
}
function objectsEqual(a, b) {
if (!a || !b)
return false;
for (var _i = 0, _a = Object.keys(a); _i < _a.length; _i++) {
var key = _a[_i];
if (a[key] !== b[key])
return false;
}
for (var _b = 0, _c = Object.keys(b); _b < _c.length; _b++) {
var key = _c[_b];
if (a[key] !== b[key])
return false;
}
return true;
}
function findOrAddFont(fonts, font) {
for (var i = 0; i < fonts.length; i++) {
if (fonts[i].name === font.name)
return i;
}
fonts.push(font);
return fonts.length - 1;
}
function decodeObject(obj, keys, fonts) {
var result = {};
for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
var key = keys_1[_i];
var Key = upperFirst(key);
if (obj[Key] === undefined)
continue;
if (key === 'justification') {
result[key] = justification[obj[Key]];
}
else if (key === 'font') {
result[key] = fonts[obj[Key]];
}
else if (key === 'fillColor' || key === 'strokeColor') {
result[key] = decodeColor(obj[Key]);
}
else {
result[key] = obj[Key];
}
}
return result;
}
function encodeObject(obj, keys, fonts) {
var _a;
var result = {};
for (var _i = 0, keys_2 = keys; _i < keys_2.length; _i++) {
var key = keys_2[_i];
var Key = upperFirst(key);
if (obj[key] === undefined)
continue;
if (key === 'justification') {
result[Key] = justification.indexOf((_a = obj[key]) !== null && _a !== void 0 ? _a : 'left');
}
else if (key === 'font') {
result[Key] = findOrAddFont(fonts, obj[key]);
}
else if (key === 'fillColor' || key === 'strokeColor') {
result[Key] = { Type: 1, Values: encodeColor(obj[key]) };
}
else {
result[Key] = obj[key];
}
}
return result;
}
function decodeParagraphStyle(obj, fonts) {
return decodeObject(obj, paragraphStyleKeys, fonts);
}
function decodeStyle(obj, fonts) {
return decodeObject(obj, styleKeys, fonts);
}
function encodeParagraphStyle(obj, fonts) {
return encodeObject(obj, paragraphStyleKeys, fonts);
}
function encodeStyle(obj, fonts) {
return encodeObject(obj, styleKeys, fonts);
}
function deduplicateValues(base, runs, keys) {
if (!runs.length)
return;
var _loop_1 = function (key) {
var value = runs[0].style[key];
if (value !== undefined) {
var identical = false;
if (Array.isArray(value)) {
identical = runs.every(function (r) { return arraysEqual(r.style[key], value); });
}
else if (typeof value === 'object') {
identical = runs.every(function (r) { return objectsEqual(r.style[key], value); });
}
else {
identical = runs.every(function (r) { return r.style[key] === value; });
}
if (identical) {
base[key] = value;
}
}
var styleValue = base[key];
if (styleValue !== undefined) {
for (var _a = 0, runs_1 = runs; _a < runs_1.length; _a++) {
var r = runs_1[_a];
var same = false;
if (Array.isArray(value)) {
same = arraysEqual(r.style[key], value);
}
else if (typeof value === 'object') {
same = objectsEqual(r.style[key], value);
}
else {
same = r.style[key] === value;
}
if (same)
delete r.style[key];
}
}
};
for (var _i = 0, keys_3 = keys; _i < keys_3.length; _i++) {
var key = keys_3[_i];
_loop_1(key);
}
if (runs.every(function (x) { return Object.keys(x.style).length === 0; })) {
runs.length = 0;
}
}
export function decodeEngineData(engineData) {
var _a, _b, _c, _d, _e, _f;
// console.log('engineData', require('util').inspect(engineData, false, 99, true));
var engineDict = engineData.EngineDict;
var resourceDict = engineData.ResourceDict;
var fonts = resourceDict.FontSet.map(function (f) { return ({
name: f.Name,
script: f.Script,
type: f.FontType,
synthetic: f.Synthetic,
}); });
var text = engineDict.Editor.Text.replace(/\r/g, '\n');
var removedCharacters = 0;
while (/\n$/.test(text)) {
text = text.substr(0, text.length - 1);
removedCharacters++;
}
var result = {
text: text,
antiAlias: (_a = antialias[engineDict.AntiAlias]) !== null && _a !== void 0 ? _a : 'smooth',
useFractionalGlyphWidths: !!engineDict.UseFractionalGlyphWidths,
superscriptSize: resourceDict.SuperscriptSize,
superscriptPosition: resourceDict.SuperscriptPosition,
subscriptSize: resourceDict.SubscriptSize,
subscriptPosition: resourceDict.SubscriptPosition,
smallCapSize: resourceDict.SmallCapSize,
};
// shape
var photoshop = (_f = (_e = (_d = (_c = (_b = engineDict.Rendered) === null || _b === void 0 ? void 0 : _b.Shapes) === null || _c === void 0 ? void 0 : _c.Children) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.Cookie) === null || _f === void 0 ? void 0 : _f.Photoshop;
if (photoshop) {
result.shapeType = photoshop.ShapeType === 1 ? 'box' : 'point';
if (photoshop.PointBase)
result.pointBase = photoshop.PointBase;
if (photoshop.BoxBounds)
result.boxBounds = photoshop.BoxBounds;
}
// paragraph style
// const theNormalParagraphSheet = resourceDict.TheNormalParagraphSheet;
// const paragraphSheetSet = resourceDict.ParagraphSheetSet;
// const paragraphProperties = paragraphSheetSet[theNormalParagraphSheet].Properties;
var paragraphRun = engineData.EngineDict.ParagraphRun;
result.paragraphStyle = {}; // decodeParagraphStyle(paragraphProperties, fonts);
result.paragraphStyleRuns = [];
for (var i = 0; i < paragraphRun.RunArray.length; i++) {
var run_1 = paragraphRun.RunArray[i];
var length_1 = paragraphRun.RunLengthArray[i];
var style = decodeParagraphStyle(run_1.ParagraphSheet.Properties, fonts);
// const adjustments = {
// axis: run.Adjustments.Axis,
// xy: run.Adjustments.XY,
// };
result.paragraphStyleRuns.push({ length: length_1, style: style /*, adjustments*/ });
}
for (var counter = removedCharacters; result.paragraphStyleRuns.length && counter > 0; counter--) {
if (--result.paragraphStyleRuns[result.paragraphStyleRuns.length - 1].length === 0) {
result.paragraphStyleRuns.pop();
}
}
deduplicateValues(result.paragraphStyle, result.paragraphStyleRuns, paragraphStyleKeys);
if (!result.paragraphStyleRuns.length)
delete result.paragraphStyleRuns;
// style
// const theNormalStyleSheet = resourceDict.TheNormalStyleSheet;
// const styleSheetSet = resourceDict.StyleSheetSet;
// const styleSheetData = styleSheetSet[theNormalStyleSheet].StyleSheetData;
var styleRun = engineData.EngineDict.StyleRun;
result.style = {}; // decodeStyle(styleSheetData, fonts);
result.styleRuns = [];
for (var i = 0; i < styleRun.RunArray.length; i++) {
var length_2 = styleRun.RunLengthArray[i];
var style = decodeStyle(styleRun.RunArray[i].StyleSheet.StyleSheetData, fonts);
if (!style.font)
style.font = fonts[0];
result.styleRuns.push({ length: length_2, style: style });
}
for (var counter = removedCharacters; result.styleRuns.length && counter > 0; counter--) {
if (--result.styleRuns[result.styleRuns.length - 1].length === 0) {
result.styleRuns.pop();
}
}
deduplicateValues(result.style, result.styleRuns, styleKeys);
if (!result.styleRuns.length)
delete result.styleRuns;
return result;
}
export function encodeEngineData(data) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
var text = "".concat((data.text || '').replace(/\r?\n/g, '\r'), "\r");
var fonts = [
{ name: 'AdobeInvisFont', script: 0, type: 0, synthetic: 0 },
];
var defFont = ((_a = data.style) === null || _a === void 0 ? void 0 : _a.font) || ((_c = (_b = data.styleRuns) === null || _b === void 0 ? void 0 : _b.find(function (s) { return s.style.font; })) === null || _c === void 0 ? void 0 : _c.style.font) || defaultFont;
var paragraphRunArray = [];
var paragraphRunLengthArray = [];
var paragraphRuns = data.paragraphStyleRuns;
if (paragraphRuns && paragraphRuns.length) {
var leftLength_1 = text.length;
for (var _i = 0, paragraphRuns_1 = paragraphRuns; _i < paragraphRuns_1.length; _i++) {
var run_2 = paragraphRuns_1[_i];
var runLength = Math.min(run_2.length, leftLength_1);
leftLength_1 -= runLength;
if (!runLength)
continue; // ignore 0 size runs
// extend last run if it's only for trailing \r
if (leftLength_1 === 1 && run_2 === paragraphRuns[paragraphRuns.length - 1]) {
runLength++;
leftLength_1--;
}
paragraphRunLengthArray.push(runLength);
paragraphRunArray.push({
ParagraphSheet: {
DefaultStyleSheet: 0,
Properties: encodeParagraphStyle(__assign(__assign(__assign({}, defaultParagraphStyle), data.paragraphStyle), run_2.style), fonts),
},
Adjustments: { Axis: [1, 0, 1], XY: [0, 0] },
});
}
if (leftLength_1) {
paragraphRunLengthArray.push(leftLength_1);
paragraphRunArray.push({
ParagraphSheet: {
DefaultStyleSheet: 0,
Properties: encodeParagraphStyle(__assign(__assign({}, defaultParagraphStyle), data.paragraphStyle), fonts),
},
Adjustments: { Axis: [1, 0, 1], XY: [0, 0] },
});
}
}
else {
for (var i = 0, last = 0; i < text.length; i++) {
if (text.charCodeAt(i) === 13) { // \r
paragraphRunLengthArray.push(i - last + 1);
paragraphRunArray.push({
ParagraphSheet: {
DefaultStyleSheet: 0,
Properties: encodeParagraphStyle(__assign(__assign({}, defaultParagraphStyle), data.paragraphStyle), fonts),
},
Adjustments: { Axis: [1, 0, 1], XY: [0, 0] },
});
last = i + 1;
}
}
}
var styleSheetData = encodeStyle(__assign(__assign({}, defaultStyle), { font: defFont }), fonts);
var styleRuns = data.styleRuns || [{ length: text.length, style: data.style || {} }];
var styleRunArray = [];
var styleRunLengthArray = [];
var leftLength = text.length;
for (var _o = 0, styleRuns_1 = styleRuns; _o < styleRuns_1.length; _o++) {
var run_3 = styleRuns_1[_o];
var runLength = Math.min(run_3.length, leftLength);
leftLength -= runLength;
if (!runLength)
continue; // ignore 0 size runs
// extend last run if it's only for trailing \r
if (leftLength === 1 && run_3 === styleRuns[styleRuns.length - 1]) {
runLength++;
leftLength--;
}
styleRunLengthArray.push(runLength);
styleRunArray.push({
StyleSheet: {
StyleSheetData: encodeStyle(__assign(__assign({ kerning: 0, autoKerning: true, fillColor: { r: 0, g: 0, b: 0 } }, data.style), run_3.style), fonts),
},
});
}
// add extra run to the end if existing ones didn't fill it up
if (leftLength && styleRuns.length) {
styleRunLengthArray.push(leftLength);
styleRunArray.push({
StyleSheet: {
StyleSheetData: encodeStyle(__assign({ kerning: 0, autoKerning: true, fillColor: { r: 0, g: 0, b: 0 } }, data.style), fonts),
},
});
}
var gridInfo = __assign(__assign({}, defaultGridInfo), data.gridInfo);
var WritingDirection = data.orientation === 'vertical' ? 2 : 0;
var Procession = data.orientation === 'vertical' ? 1 : 0;
var ShapeType = data.shapeType === 'box' ? 1 : 0;
var Photoshop = {
ShapeType: ShapeType,
};
if (ShapeType === 0) {
Photoshop.PointBase = data.pointBase || [0, 0];
}
else {
Photoshop.BoxBounds = data.boxBounds || [0, 0, 0, 0];
}
// needed for correct order of properties
Photoshop.Base = {
ShapeType: ShapeType,
TransformPoint0: [1, 0],
TransformPoint1: [0, 1],
TransformPoint2: [0, 0],
};
var defaultResources = {
KinsokuSet: [
{
Name: 'PhotoshopKinsokuHard',
NoStart: '、。,.・:;?!ー―’”)〕]}〉》」』】ヽヾゝゞ々ぁぃぅぇぉっゃゅょゎァィゥェォッャュョヮヵヶ゛゜?!)]},.:;℃℉¢%‰',
NoEnd: '‘“(〔[{〈《「『【([{¥$£@§〒#',
Keep: '―‥',
Hanging: '、。.,',
},
{
Name: 'PhotoshopKinsokuSoft',
NoStart: '、。,.・:;?!’”)〕]}〉》」』】ヽヾゝゞ々',
NoEnd: '‘“(〔[{〈《「『【',
Keep: '―‥',
Hanging: '、。.,',
},
],
MojiKumiSet: [
{ InternalName: 'Photoshop6MojiKumiSet1' },
{ InternalName: 'Photoshop6MojiKumiSet2' },
{ InternalName: 'Photoshop6MojiKumiSet3' },
{ InternalName: 'Photoshop6MojiKumiSet4' },
],
TheNormalStyleSheet: 0,
TheNormalParagraphSheet: 0,
ParagraphSheetSet: [
{
Name: 'Normal RGB',
DefaultStyleSheet: 0,
Properties: encodeParagraphStyle(__assign(__assign({}, defaultParagraphStyle), data.paragraphStyle), fonts),
},
],
StyleSheetSet: [
{
Name: 'Normal RGB',
StyleSheetData: styleSheetData,
},
],
FontSet: fonts.map(function (f) { return ({
Name: f.name,
Script: f.script || 0,
FontType: f.type || 0,
Synthetic: f.synthetic || 0,
}); }),
SuperscriptSize: (_d = data.superscriptSize) !== null && _d !== void 0 ? _d : 0.583,
SuperscriptPosition: (_e = data.superscriptPosition) !== null && _e !== void 0 ? _e : 0.333,
SubscriptSize: (_f = data.subscriptSize) !== null && _f !== void 0 ? _f : 0.583,
SubscriptPosition: (_g = data.subscriptPosition) !== null && _g !== void 0 ? _g : 0.333,
SmallCapSize: (_h = data.smallCapSize) !== null && _h !== void 0 ? _h : 0.7,
};
var engineData = {
EngineDict: {
Editor: { Text: text },
ParagraphRun: {
DefaultRunData: {
ParagraphSheet: { DefaultStyleSheet: 0, Properties: {} },
Adjustments: { Axis: [1, 0, 1], XY: [0, 0] },
},
RunArray: paragraphRunArray,
RunLengthArray: paragraphRunLengthArray,
IsJoinable: 1,
},
StyleRun: {
DefaultRunData: { StyleSheet: { StyleSheetData: {} } },
RunArray: styleRunArray,
RunLengthArray: styleRunLengthArray,
IsJoinable: 2,
},
GridInfo: {
GridIsOn: !!gridInfo.isOn,
ShowGrid: !!gridInfo.show,
GridSize: (_j = gridInfo.size) !== null && _j !== void 0 ? _j : 18,
GridLeading: (_k = gridInfo.leading) !== null && _k !== void 0 ? _k : 22,
GridColor: { Type: 1, Values: encodeColor(gridInfo.color) },
GridLeadingFillColor: { Type: 1, Values: encodeColor(gridInfo.color) },
AlignLineHeightToGridFlags: !!gridInfo.alignLineHeightToGridFlags,
},
AntiAlias: antialias.indexOf((_l = data.antiAlias) !== null && _l !== void 0 ? _l : 'sharp'),
UseFractionalGlyphWidths: (_m = data.useFractionalGlyphWidths) !== null && _m !== void 0 ? _m : true,
Rendered: {
Version: 1,
Shapes: {
WritingDirection: WritingDirection,
Children: [
{
ShapeType: ShapeType,
Procession: Procession,
Lines: { WritingDirection: WritingDirection, Children: [] },
Cookie: { Photoshop: Photoshop },
},
],
},
},
},
ResourceDict: __assign({}, defaultResources),
DocumentResources: __assign({}, defaultResources),
};
// console.log('encodeEngineData', require('util').inspect(engineData, false, 99, true));
return engineData;
}
//# sourceMappingURL=text.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/// <reference types="node" />
export declare function stringLengthInBytes(value: string): number;
export declare function encodeStringTo(buffer: Uint8Array | Buffer, offset: number, value: string): number;
export declare function encodeString(value: string): Uint8Array;
export declare function decodeString(value: Uint8Array): string;

View File

@@ -0,0 +1,145 @@
function charLengthInBytes(code) {
if ((code & 0xffffff80) === 0) {
return 1;
}
else if ((code & 0xfffff800) === 0) {
return 2;
}
else if ((code & 0xffff0000) === 0) {
return 3;
}
else {
return 4;
}
}
export function stringLengthInBytes(value) {
var result = 0;
for (var i = 0; i < value.length; i++) {
var code = value.charCodeAt(i);
// high surrogate
if (code >= 0xd800 && code <= 0xdbff) {
if ((i + 1) < value.length) {
var extra = value.charCodeAt(i + 1);
// low surrogate
if ((extra & 0xfc00) === 0xdc00) {
i++;
result += charLengthInBytes(((code & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000);
}
}
}
else {
result += charLengthInBytes(code);
}
}
return result;
}
function writeCharacter(buffer, offset, code) {
var length = charLengthInBytes(code);
switch (length) {
case 1:
buffer[offset] = code;
break;
case 2:
buffer[offset] = ((code >> 6) & 0x1f) | 0xc0;
buffer[offset + 1] = (code & 0x3f) | 0x80;
break;
case 3:
buffer[offset] = ((code >> 12) & 0x0f) | 0xe0;
buffer[offset + 1] = ((code >> 6) & 0x3f) | 0x80;
buffer[offset + 2] = (code & 0x3f) | 0x80;
break;
default:
buffer[offset] = ((code >> 18) & 0x07) | 0xf0;
buffer[offset + 1] = ((code >> 12) & 0x3f) | 0x80;
buffer[offset + 2] = ((code >> 6) & 0x3f) | 0x80;
buffer[offset + 3] = (code & 0x3f) | 0x80;
break;
}
return length;
}
export function encodeStringTo(buffer, offset, value) {
for (var i = 0; i < value.length; i++) {
var code = value.charCodeAt(i);
// high surrogate
if (code >= 0xd800 && code <= 0xdbff) {
if ((i + 1) < value.length) {
var extra = value.charCodeAt(i + 1);
// low surrogate
if ((extra & 0xfc00) === 0xdc00) {
i++;
var fullCode = ((code & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
offset += writeCharacter(buffer, offset, fullCode);
}
}
}
else {
offset += writeCharacter(buffer, offset, code);
}
}
return offset;
}
export function encodeString(value) {
var buffer = new Uint8Array(stringLengthInBytes(value));
encodeStringTo(buffer, 0, value);
return buffer;
}
function continuationByte(buffer, index) {
if (index >= buffer.length) {
throw Error('Invalid byte index');
}
var continuationByte = buffer[index];
if ((continuationByte & 0xC0) === 0x80) {
return continuationByte & 0x3F;
}
else {
throw Error('Invalid continuation byte');
}
}
export function decodeString(value) {
var result = '';
for (var i = 0; i < value.length;) {
var byte1 = value[i++];
var code = void 0;
if ((byte1 & 0x80) === 0) {
code = byte1;
}
else if ((byte1 & 0xe0) === 0xc0) {
var byte2 = continuationByte(value, i++);
code = ((byte1 & 0x1f) << 6) | byte2;
if (code < 0x80) {
throw Error('Invalid continuation byte');
}
}
else if ((byte1 & 0xf0) === 0xe0) {
var byte2 = continuationByte(value, i++);
var byte3 = continuationByte(value, i++);
code = ((byte1 & 0x0f) << 12) | (byte2 << 6) | byte3;
if (code < 0x0800) {
throw Error('Invalid continuation byte');
}
if (code >= 0xd800 && code <= 0xdfff) {
throw Error("Lone surrogate U+".concat(code.toString(16).toUpperCase(), " is not a scalar value"));
}
}
else if ((byte1 & 0xf8) === 0xf0) {
var byte2 = continuationByte(value, i++);
var byte3 = continuationByte(value, i++);
var byte4 = continuationByte(value, i++);
code = ((byte1 & 0x0f) << 0x12) | (byte2 << 0x0c) | (byte3 << 0x06) | byte4;
if (code < 0x010000 || code > 0x10ffff) {
throw Error('Invalid continuation byte');
}
}
else {
throw Error('Invalid UTF-8 detected');
}
if (code > 0xffff) {
code -= 0x10000;
result += String.fromCharCode(code >>> 10 & 0x3ff | 0xd800);
code = 0xdc00 | code & 0x3ff;
}
result += String.fromCharCode(code);
}
return result;
}
//# sourceMappingURL=utf8.js.map

File diff suppressed because one or more lines are too long