Fast zero-dependency PSD parser for the web and Node.js
A lightweight Adobe Photoshop .psd/.psb file parser in typescript with zero-dependency for web browsers and NodeJS
@webtoon/psd is a fast, lightweight parser for Adobe Photoshop PSD/PSB files. It uses standard (ES2015+) features and can be used both in web browsers and in Node.js. It pulls in zero dependencies, making it smaller (~100 KiB minified) than other PSD parsers (ag-psd: 200 KiB, PSD.js: 443 KiB). It uses WebAssembly to speed up decoding image data.
| Chrome | Firefox | Safari | Edge | Node |
|---|---|---|---|---|
| 57 | 52 | 11 | 79 | 12 |
*Internet Explorer is not supported
$ npm install @webtoon/psdYou can run benchmarks for @webtoon/psd in your browser.
.psb)@webtoon/psd is provided as a pure ECMAScript module.
Check out the live demo (source code) for web browser.
@webtoon/psd must be bundled with a bundler such as Webpack or Rollup.
@webtoon/psd reads a PSD file as an ArrayBuffer. You can use FileReader or File to load a PSD file:
…For performance, we recommend parsing PSD files in a Web Worker rather than the main thread.
Check out the source code for the Node.js example for web browser.
@webtoon/psd does not support the Node.js Buffer. You must explicitly supply the underlying ArrayBuffer.
import * as fs from "fs";
import Psd from "@webtoon/psd";
const psdData = fs.readFileSync("./my-file.psd");
// Pass the ArrayBuffer instance inside the Buffer
const psdFile = Psd.parse(psdData.buffer);Since @webtoon/psd is provided as an ES module, you must use dynamic import() or a bundler to run it in CommonJS code:
const Psd = await import("@webtoon/psd");This library provides the Psd class as the default export.
Psd.parse(ArrayBuffer) takes an ArrayBuffer containing a PSD or PSB file and returns a new Psd object.
const psdFile = Psd.parse(myBuffer);A Psd object contains a tree of Layer and Group (i.e. layer group) objects.
Psd object provides a children property, which is an array of top-level Layers and Groups.Group object provides a children property, which is an array of Layers and Groups that belong immediately under the current layer group.Psd, Group, and Layer objects provide a type field, which can be used to discriminate each type:import Psd, {Node} from "@webtoon/psd";
// Recursively traverse layers and layer groups
function traverseNode(node: Node) {
if (node.type === "Layer") {
// Do something with Layer
} else if (node.type === "Group") {
// Do something with Group
} else if (node.type === "Psd") {
// Do something with Psd
} else {
throw new Error("Invalid node type");
}
node.children?.forEach((child) => traverseNode(child));
}
traverseNode(psdFile);The Psd object also provides the layers property, which is an array of all Layers in the image (including nested).
for (const layer of psdFile.layers) {
doSomething(layer);
}Use Psd.prototype.composite() and Layer.prototype.composite() to decode the pixel information for the entire image or an individual layer.
Note that for Psd.prototype.composite() to work, PSD/PSB files need to be saved in "Maximize Compatibility" mode. Otherwise, it will return no data. You can enable it in Preferences > File Handling > File Compatibility > Maximize PSD and PSB File Compatibility
// Decode the pixel data of the entire image
pixelData = await psd.composite();
// Extract the pixel data of a layer, with all layer and layer group effects applied
// (currently, only the opacity is supported)
layerPixelData = await layer.composite();
// Extract the pixel data of a layer, with only the layer's own effects applied
layerPixelData = await layer.composite(true, false);
// Extract the pixel data of a layer, without any effects
layerPixelData = await layer.composite(false);@webtoon/psd is released under the MIT license.
…No open issues yet, or sync has not completed.