27 KiB
PSD document format
This document describes structure of the Psd object used in readPsd and writePsd functions, you can see instructions on how to use these functions in our main README document
You can see examples of different PSD documents and their corresponding JSON data in our test folder. Each subfolder contains src.psd document and corresponding data.json file with object generated by our library. Additionally there is canvas.png file represending composite image data, thumb.png file representing thumbnail image data and layer-#.png files with image data of each layer.
Basic document structure
// example psd document structure
const psd: Psd = {
"width": 300,
"height": 200,
"channels": 3,
"bitsPerChannel": 8,
"colorMode": 3,
"canvas": <Canvas>,
"children": [],
};
-
The
widthandheightproperties specify PSD document size in pixels. These values are required when writing a document. -
channelsproperty specifies number of color channels in the document, it's usually 3 channels (red, green, and blue, when document is in typical RGB color mode) Other color modes will have different channel count (grayscale - 1 channel, CMYK - 4 channels). This property can be ommited when writing, this library only supports RGB color mode with 3 channels at the moment. -
bitsPerChannelproperty specifies number of bits per each color channel, this value will ba 1 for one bit bitmap color mode and 8 in all other cases as this library is not supporting 16 or 32 bit color channels at the moment. It can also be ommited when writing a document and default value of 8 will be assumed. -
colorModespecifies color mode of the PSD document.Value is one of the numbers that can be matched to this enumerable:
enum ColorMode { Bitmap = 0, Grayscale = 1, Indexed = 2, RGB = 3, CMYK = 4, Multichannel = 7, Duotone = 8, Lab = 9, }The library supports "Bitmap", "Grayscale" and "RGB" color modes at the moment. "Bitmap" and "Grayscale" colors will be converted to "RGB" colors when reading PSD file. Writing is only supported for "RGB" mode. The value can be ommited for writing and "RGB" color mode will be assumed.
-
canvas(orimageData) is a property containing bitmap with composite image data for the entire document. PSD file contains this extra bitmap additionally to bitmaps of each layer.canvasfield will be an instance ofHTMLCanvasElement(in browser environment) orCanvasobject ofnode-canvaslibrary (in nodejs environment).You can choose to instead use
imageDatafield by choosinguseImageData: trueoption when reading PSD file. In that canimageDatawill be an instance ofImageDataobject, containingwidth,heightanddataproperties. This is useful if you want to use bitmap data directly, and not use it for drawing using canvas. Additionally this will preserve accurate color information as canvas element will premultiply image alpha which will change color values slightly.If you don't need to use this field you can specify
skipCompositeImageData: trueoption, while reading PSD file, to skip reading this field and save on processing time and memory usage.This image data is optional in PSD file so it may be missing in some PSD files that opted to skip it.
When writing you can provide either
canvasorimageDataproperty and the library will use the one you provide. You can also skip the field entirely and not write this data at all as it's not needed by Photohop to read the file. It might be used in some other application, for thumbnails or by some old versions of Adobe software, so you may want to still provide it to remain compatible with those programs.If you're generating your own PSD file and want to provide this composite image data you will have to generate one yourself by composing all layer image data and effects yourself, this library does not provide any utilities to generate this image data for you.
-
childrenlist of layers and groups at the root of the document. see Layers and Groups -
imageResourcescontains all document-wide parameters see Image Resouces -
linkedFilescontains list of files linked in smart objects see Smart Objects -
artboardscontains global options for artboards. Artboards is a feature in new versions of Photoshop that lets you have multiple canvases in a single PSD document. The information about positioning, name and color of each artboard is stored inside each layer, inartboardproperty. This property will be absent if the document does not have any artboards specified. It can be ommited when writing.type Artboards = { count: number; // number of artboards in the document autoExpandOffset?: { horizontal: number; vertical: number; }; origin?: { horizontal: number; vertical: number; }; autoExpandEnabled?: boolean; autoNestEnabled?: boolean; autoPositionEnabled?: boolean; shrinkwrapOnSaveEnabled?: boolean; docDefaultNewArtboardBackgroundColor?: Color; docDefaultNewArtboardBackgroundType?: number; } -
annotationscontains array of annotations, this field will be absent if the document does not have any annotations. It can be ommited when writing. Sound annotations are not supported by this library right at the moment.Each annotation object has a following structure:
interface Annotation { type: 'text' | 'sound'; open: boolean; iconLocation: { left: number; top: number; right: number; bottom: number }; popupLocation: { left: number; top: number; right: number; bottom: number }; color: Color; author: string; name: string; date: string; data: string | Uint8Array; // annotation text or sound buffer } -
globalLayerMaskInfodon't really know what this is, it can be ommited when writing. -
filterMaskdon't really know what this is, it can be ommited when writing.
Layers and Groups
Psd document object has children property that contains all root level layers and groups in order from top to bottom as they appear in Photoshop (take note that if you want to draw the layer images to generate document image then you need to draw them in reverse order). The children property will contain both regular layers and groups. Each group will have children property, containing all the layers and groups that are inside that group. So the document will have a tree structure like this:
var psd = {
// ... other fields
children: [
{
name: "layer 1",
// ... other fields
}
{
name: "group 1",
// ... other fields
children: [
{
name: "layer 2, inside group 1",
// ... other fields
},
{
name: "group 2, inside group 1",
// ... other fields
children: []
}
]
}
]
}
Layer types
You can distinguish between different layer types by checking which properties thay have set on them. If a layer has children property set it meas the it's a group, if it has text property it's a text layer and so on. If you're only interested in the basic parsing of layers and want to just extract image data or layer parameter a simple parsing like this can be enough:
// simple parsing
function parseLayer(layer) {
if ('children' in layer) {
// group
layer.children.forEach(parseLayer);
} else if (layer.canvas) {
// regular layer with canvas
} else {
// empty or special layer
}
}
If you need to know type of each layer, something like this could be a good approach:
// complex parsing
function parseLayer(layer) {
if ('children' in layer) {
// group
layer.children.forEach(parseLayer);
} else if ('text' in layer) {
// text layer
} else if ('adjustment' in layer) {
// adjustment layer
} else if ('placedLayer' in layer) {
// smart object layer
} else if ('vectorMask' in layer) {
// vector layer
} else {
// bitmap layer
}
}
But thake into account that a lot of properties are shared for different types of layers. Any layer can have a mask property for example.
Layer
Example layer structure:
{
"top": 0,
"left": 0,
"bottom": 200,
"right": 300,
"blendMode": "normal",
"opacity": 1,
"clipping": false,
"timestamp": 1448235572.7235785,
"transparencyProtected": true,
"protected": {
"transparency": true,
"composite": false,
"position": true
},
"hidden": false,
"name": "Background",
"nameSource": "bgnd",
"id": 1,
"layerColor": "none",
"blendClippendElements": true,
"blendInteriorElements": false,
"knockout": false,
"referencePoint": {
"x": 0,
"y": 0
},
"canvas": <Canvas>
},
-
top,left,bottom,rightproperties specify location of layer image data withing the document.topspecifies offset in pixel of the top of layer image data from the top edge of the document,bottomspecifies offset of the bottom of the layer image data from the top adge of the document and similar forleftandright.This is necessary as layer image data can be smaller or large than the document size. This can cause in some cases the values of these fields to be negative. A value of
left: -100means that the layer image data starts 100 pixels outside the left document edge. This can happen if you move the layer left beyond document edge in Photoshop.topandleftvalues can be ommited when writing and will be assumed to be 0.bottomandrightvalues can be ommited and will always be ignored when writing and will instead be calculated fromcanvas(orimageData) width and height. -
blendModeis a layer blending mode and will be one of the following values:type BlendMode = 'pass through' | 'normal' | 'dissolve' | 'darken' | 'multiply' | 'color burn' | 'linear burn' | 'darker color' | 'lighten'| 'screen' | 'color dodge' | 'linear dodge' | 'lighter color' | 'overlay' | 'soft light' | 'hard light' | 'vivid light' | 'linear light' | 'pin light' | 'hard mix' | 'difference' | 'exclusion' | 'subtract' | 'divide' | 'hue' | 'saturation' | 'color' | 'luminosity'These values correspond to naming in layer blend mode dropdown. If ommited a value of
normalwill be assumed. -
canvas(orimageData) seecanvasproperty description in Basic document structureVector, text and smart object layers still have image data with pregenerated bitmap. You also need to provide that image data when writing PSD files.
Reading this property can be skipped if
skipLayerImageData: trueoption is passed toreadPsdfunction. This can be done to save on memory usage and processing time if layer image data is not needed. -
opacityspecifies level of layer transparency (the value range is from 0 to 1). Can be ommited when writing, a default value of 1 will be assumed. -
clippingindicates if layer clipping is enabled (if enabled the layer is clipped to the layer below it). Can be ommited when writing, a default value offalsewill be assumed. -
timestamptimestamp of last time layer was modified (in unix time). Can be ommited when writing. -
transparencyProtectedandprotectedproperties specify status of various locks that you can set for each layer.protected.positionindicates if moving layer is lockedprotected.compositeindicates if drawing on the layer is lockedprotected.transparencyindicates if drawing transparent pixels are locked
If the
transparencyProtectedistruebutprotected.transparencyisfalseit means that the layer has "lock all" enabled. Both this fields can be ommited when writing, a values offalsewill be assumed for all of the ommited fields. -
hiddenindicates if the layer is hidden. Can be ommited when writing, a value offalsewill be assumed. -
namename of the layer, can be any unicode string, can be empty. Can be ommited when writing, a value of''will be assumed. -
nameSourceinternal Photoshop information, can be ignored and ommited when writing. -
idunique ID number for layer, it may be missing in some PSD files. Can be ommited when writing, but if provided it has to be a unique number, if duplicate IDs are found they will be changed to a unique ones when writing the file. -
layerColorcolor of the layer in layer list, property will be missing or will be one of the following values:type LayerColor = 'none' | 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'violet' | 'gray' -
versionunknown functionality -
referencePointunknown functionality -
maskLayer mask, property has the following structure.interface LayerMaskData { top?: number; left?: number; bottom?: number; right?: number; defaultColor?: number; disabled?: boolean; positionRelativeToLayer?: boolean; fromVectorData?: boolean; // set to true if the mask is generated from vector data, false if it's a bitmap provided by user userMaskDensity?: number; userMaskFeather?: number; // px vectorMaskDensity?: number; vectorMaskFeather?: number; canvas?: HTMLCanvasElement; imageData?: ImageData; }Similar to layer image data this data has
top,left,bottomandrightoffsets specified.fromVectorDataSpecifies if the mask image data was generated fromvectorMask, iffromVectorDatais set to false and bothvectorMaskandmaskproperties are present it means that the layer has 2 active masks, bitmap mask and a vector mask.maskproperty will be missing when layer has no mask, it can be ommited when writing. -
effectsObject describing layer "Blending Options"Effects property follows the following structure:
interface LayerEffectsInfo { disabled?: boolean; // indicates if all effects are disabled scale?: number; dropShadow?: LayerEffectShadow[]; innerShadow?: LayerEffectShadow[]; outerGlow?: LayerEffectsOuterGlow; innerGlow?: LayerEffectInnerGlow; bevel?: LayerEffectBevel; solidFill?: LayerEffectSolidFill[]; satin?: LayerEffectSatin; stroke?: LayerEffectStroke[]; gradientOverlay?: LayerEffectGradientOverlay[]; patternOverlay?: LayerEffectPatternOverlay; // not supported yet }Some of the effects (specified here as arrays) can be specified multiple times. This is new feature, only supported in more recent versions of Photoshop.
This property is not present if there are not blending options set for the layer. This property can be ommited when writing.
-
texttext properties of text layerTODO
-
patternsnot supported yet -
vectorFillFill color, gradient or pattern for the vector mask. Usetypefield to distinguish between different vector fill types, like this:switch (vectorFill.type) { case 'color': // solid color fill ({ color: Color } type) break; case 'solid': // solid gradient fill (EffectSolidGradient type) break; case 'noise': // noise gradient fill (EffectNoiseGradient type) break; case 'pattern': // pattern fill (EffectPattern type) break; } -
vectorStrokeVector stroke parameters for the vector mask. This field also contains parameters related tovectorFill. This property has following structure:type VectorStroke = { strokeEnabled?: boolean; // vector drawing has stroke fillEnabled?: boolean; // vector drawing has fill (specified by vectorFill property) lineWidth?: UnitsValue; lineDashOffset?: UnitsValue; miterLimit?: number; lineCapType?: LineCapType; lineJoinType?: LineJoinType; lineAlignment?: LineAlignment; scaleLock?: boolean; strokeAdjust?: boolean; lineDashSet?: UnitsValue[]; blendMode?: BlendMode; opacity?: number; content?: VectorContent; // stroke color, gradient or pattern (see `vectorFill` field for more information) resolution?: number; } -
vectorMaskSpecifies vector mask used byvectorFillandvectorStroketo draw vector images.TODO: expand this description
-
usingAlignedRenderingunknown functionality -
pathListnot supported yet -
adjustmentindicates that the layer is an adjustment layer. Adjustment layer do not have image data. This property is not present on non-adjustment layers.Use
typefield of the adjustment object to distinguish between different adjustment layer types.switch (adjustment.type) { case 'brightness/contrast': // handle BrightnessAdjustment layer break; case 'levels': // handle LevelsAdjustment layer break; // ... other cases ... }see all Adjustment layer types in psd.ts file
-
placedLayerindicates that this is smart object layer, see Smart Objects section for more information. This property is only present on smart object layers. -
vectorOriginationTODO -
compositorUsedinternal photoshop information -
artboardArtboard location and parameters, this property is only present when using artboards. Artbord is object is following this structure:type Artboard = { rect: { top: number; left: number; bottom: number; right: number; }; guideIndices?: any[]; presetName?: string; color?: Color; backgroundType?: number; } -
Advanced blending options
-
engineDatainternal text information
Group
Example group structure:
{
"top": 0,
"left": 0,
"bottom": 0,
"right": 0,
"blendMode": "normal",
"opacity": 1,
"clipping": false,
"timestamp": 1450198418.5245173,
"transparencyProtected": false,
"hidden": false,
"name": "Group 1",
"nameSource": "lset",
"id": 5,
"sectionDivider": {
"type": 1,
"key": "pass",
"subType": 0
},
"protected": {
"transparency": false,
"composite": false,
"position": false
},
"layerColor": "none",
"referencePoint": {
"x": 0,
"y": 0
},
"opened": true,
"children": [
// layers here
]
}
Groups don't have canvas / imageData property, as you can't draw directly on a group. Groups don't have any other special layer property like text, vectorFill, adjustment or placedLayer.
Group-only fields:
-
childrencontains list of all layers in this group. Cannot be ommited when writing, without this field a group will be assumed to be a regular layer. Use emptychildrenarray when writing empty group. -
openedindicates if the group is expanded or collapsed in the layer list. If ommited a default values oftruewill be assumed. -
sectionDividerinternal Photoshop property, can be ignored and ommited when writing.
Image Resources
Image resources are global document settings. Any of these settings can be ommited when writing. PSD file can have following global options:
-
versionInfoVersion information of Program that generated the PSD file, example value:versionInfo = { "hasRealMergedData": true, "writerName": "Adobe Photoshop", "readerName": "Adobe Photoshop CS6", "fileVersion": 1 } -
layerSelectionIdslist of layer IDs of selected layers, these layers will be selected when you open PSD document in Photoshop. -
pixelAspectRatioSpecifies aspect ratio of the PSD document pixels, almost always 1pixelAspectRatio = { "aspect": 1 } -
gridAndGuidesInformationInformation about document guidesExample value:
gridAndGuidesInformation = { "grid": { "horizontal": 576, "vertical": 576 }, "guides": [ { "location": 531.4375, "direction": "vertical" // "horizontal" or "vertical" }, // ... more guides here ... ] }; -
resolutionInfoImage resolution info, specifies physical size of the image pixels. Example value:resolutionInfo: { "horizontalResolution": 72, "horizontalResolutionUnit": "PPI", // 'PPI' (pixels per inch) or 'PPCM' (pixels per centimeter) "widthUnit": "Inches", "verticalResolution": 72, "verticalResolutionUnit": "PPI", "heightUnit": "Inches" // 'Inches', 'Centimeters', 'Points', 'Picas' or 'Columns' }, -
thumbnailCanvas element with thumbnail image for the document, this property can be missing in some PSD files. This property can be ommited when writing if there's no need to support tumbnails, this field can be automatically generated from composite image data ifgenerateThumbnail: trueoption is passed towritePsdfunction. -
thumbnailRawThis property will be used instead ifuseRawThumbnailoption is specitied when reading PSD file. -
xmpMetadataXMP metadata. File info as XML description. See http://www.adobe.com/devnet/xmp/ -
iccUntaggedProfileICC Untagged Profile -
printInformation,printScaleandprintFlagsSpecifies options for printing the document. -
layerStateTODO -
layersGroupTODO -
layerGroupsEnabledIdTODO -
alphaIdentifiersTODO -
alphaChannelNamesTODO -
globalAngleTODO -
globalAltitudeTODO -
urlsListTODO -
captionDigestTODO -
backgroundColorTODO -
idsSeedNumberTODO -
pathSelectionStateTODO -
imageReadyVariablesTODO -
imageReadyDataSetsTODO
Smart Objects
Layers with placedLayer property are smart object layers. placedLayer property has the following structure:
interface PlacedLayer {
id: string; // id of linked image file (psd.linkedFiles)
placed?: string; // unique id
type: PlacedLayerType;
transform: number[]; // x, y of 4 corners of the transform
nonAffineTransform?: number[]; // x, y of 4 corners of the transform
width?: number;
height?: number;
resolution?: UnitsValue;
warp?: Warp;
crop?: number;
}
The Psd object has linkedFiles property, that specifies list of all files linked in smart objects. Each linked file has following structure:
interface LinkedFile {
id: string;
name: string;
type?: string;
creator?: string;
data?: Uint8Array;
time?: Date; // for external files
childDocumentID?: string;
assetModTime?: number;
assetLockedState?: number;
}
id field in PlacedLayer refers to the id in LinkedFile. Example values:
layer.placedLayer = {
"id": "20953ddb-9391-11ec-b4f1-c15674f50bc4", // id that matches linkedFiles ID
"placed": "20953dda-9391-11ec-b4f1-c15674f50bc4", // unique id for this object
"type": "raster", // one of the 'unknown', 'vector', 'raster' or 'image stack'
"transform": [ // x, y of 4 corners of the transform box
29,
28,
83,
28,
83,
82,
29,
82
],
"width": 32, // width and height of the target image
"height": 32,
"resolution": {
"value": 299.99940490722656,
"units": "Density"
}
};
psd.linkedFiles = [
{
"id": "20953ddb-9391-11ec-b4f1-c15674f50bc4",
"name": "cat.png"
"data": fileContentsAsUint8Array,
}
];
Units value
Some fields in the PSD document specity a value with units, those fields use UnitsValue type:
interface UnitsValue {
units: Units;
value: number;
}
value fields can be any number value, units fields has to be one of the supported units: "Pixels", "Points", "Picas", "Millimeters", "Centimeters", "Inches", "None", "Density". Some fields only support some of the units, check with Photoshop for supported units.
Example values:
var distance = { value: 5, units: "Pixels" };
var lineWidth = { value: 3, units: "Points" };
Colors
Many fields in PSD file support passing color in different color formats (RGBA, RGB, HSB, CMYK, LAB, Grayscale) Those fields will use Color type which is a union of all of these color formats. The color types have following structure:
type RGBA = { r: number; g: number; b: number; a: number; }; // values from 0 to 255
type RGB = { r: number; g: number; b: number; }; // values from 0 to 255
type FRGB = { fr: number; fg: number; fb: number; }; // values from 0 to 1 (can be above 1)
type HSB = { h: number; s: number; b: number; }; // values from 0 to 1
type CMYK = { c: number; m: number; y: number; k: number; }; // values from 0 to 255
type LAB = { l: number; a: number; b: number; }; // values `l` from 0 to 1; `a` and `b` from -1 to 1
type Grayscale = { k: number }; // values from 0 to 255
type Color = RGBA | RGB | FRGB | HSB | CMYK | LAB | Grayscale;
When you want to set field with a Color type, it's pretty straightforward, you can just choose any of the formats you like and set it on the field:
strokeEffect.color = { h: 0.79, s: 0.54, b: 0.93 };
Reading a color field is more complicated, you need to check what color format the field is in and then run correct code to handle it, here's how to do it for all color types:
if ('l' in color) {
// color is LAB
} else if ('c' in color) {
// color is CMYK
} else if ('h' in color) {
// color is HSB
} else if ('k' in color) {
// color is Grayscale
} else if ('a' in color) {
// color is RGBA
} else if ('rf' in color) {
// color is FRGB
} else {
// color is RGB
}
If you expect the fields to be in one specific format you can just verity that it's correct and throw an error if it's a format that you didn't expect:
// handle only RGB colors
if ('r' in color && !('a' in color)) {
// color is RGB
} else {
throw new Error('Invalid color');
}

















