UNPKG

image-in-browser

Version:

Package for encoding / decoding images, transforming images, applying filters, drawing primitives on images on the client side (no need for server Node.js)

426 lines 18.8 kB
import { InputBuffer } from '../../common/input-buffer.js'; import { LibError } from '../../error/lib-error.js'; import { PsdBevelEffect } from './effect/psd-bevel-effect.js'; import { PsdDropShadowEffect } from './effect/psd-drop-shadow-effect.js'; import { PsdInnerGlowEffect } from './effect/psd-inner-glow-effect.js'; import { PsdInnerShadowEffect } from './effect/psd-inner-shadow-effect.js'; import { PsdOuterGlowEffect } from './effect/psd-outer-glow-effect.js'; import { PsdSolidFillEffect } from './effect/psd-solid-fill-effect.js'; import { PsdLayerDataFactory } from './layer-data/psd-layer-data-factory.js'; import { PsdLayerSectionDivider } from './layer-data/psd-layer-section-divider.js'; import { PsdBlendingRanges } from './psd-blending-ranges.js'; import { PsdChannel } from './psd-channel.js'; import { PsdFlag } from './psd-flag.js'; import { PsdImage } from './psd-image.js'; import { PsdMask } from './psd-mask.js'; export class PsdLayer { get top() { return this._top; } get left() { return this._left; } get bottom() { return this._bottom; } get right() { return this._right; } get width() { return this._width; } get height() { return this._height; } get blendMode() { return this._blendMode; } get opacity() { return this._opacity; } get clipping() { return this._clipping; } get flags() { return this._flags; } get compression() { return this._compression; } get name() { return this._name; } get channels() { return this._channels; } get mask() { return this._mask; } get blendingRanges() { return this._blendingRanges; } get additionalData() { return this._additionalData; } get children() { return this._children; } get parent() { return this._parent; } get layerImage() { return this._layerImage; } get effects() { return this._effects; } get isVisible() { return (this._flags & PsdFlag.hidden) === 0; } get type() { if (this._additionalData.has(PsdLayerSectionDivider.tagName)) { const section = this._additionalData.get(PsdLayerSectionDivider.tagName); return section.type; } return PsdLayerSectionDivider.normal; } constructor(input) { this._additionalData = new Map(); this._children = []; this._effects = []; this._top = input.readInt32(); this._left = input.readInt32(); this._bottom = input.readInt32(); this._right = input.readInt32(); this._width = this._right - this._left; this._height = this._bottom - this._top; this._channels = []; const numChannels = input.readUint16(); for (let i = 0; i < numChannels; ++i) { const id = input.readInt16(); const len = input.readUint32(); this._channels.push(new PsdChannel(id, len)); } const sig = input.readUint32(); if (sig !== PsdLayer.signature) { throw new LibError(`Invalid PSD layer signature: ${sig.toString(16)}`); } this._blendMode = input.readUint32(); this._opacity = input.read(); this._clipping = input.read(); this._flags = input.read(); const filler = input.read(); if (filler !== 0) { throw new LibError('Invalid PSD layer data'); } let len = input.readUint32(); const extra = input.readRange(len); if (len > 0) { len = extra.readUint32(); if (len > 0) { const maskData = extra.readRange(len); this._mask = new PsdMask(maskData); } len = extra.readUint32(); if (len > 0) { const data = extra.readRange(len); this._blendingRanges = new PsdBlendingRanges(data); } len = extra.read(); this._name = extra.readString(len); const padding = 4 - (len % 4) - 1; if (padding > 0) { extra.skip(padding); } while (!extra.isEOS) { const sig = extra.readUint32(); if (sig !== PsdLayer.signature) { throw new LibError(`PSD invalid signature for layer additional data: ${sig.toString(16)}`); } const tag = extra.readString(4); len = extra.readUint32(); const data = extra.readRange(len); if ((len & 1) === 1) { extra.skip(1); } this._additionalData.set(tag, PsdLayerDataFactory.createLayerData(tag, data)); if (tag === 'lrFX') { const fxData = this._additionalData.get('lrFX'); const data = InputBuffer.from(fxData.data); data.readUint16(); const numFx = data.readUint16(); for (let j = 0; j < numFx; ++j) { data.readString(4); const fxTag = data.readString(4); const size = data.readUint32(); if (fxTag === 'dsdw') { const version = data.readUint32(); const blur = data.readUint32(); const intensity = data.readUint32(); const angle = data.readUint32(); const distance = data.readUint32(); const color = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const blendMode = data.readString(8); const enabled = data.read() !== 0; const globalAngle = data.read() !== 0; const opacity = data.read(); const nativeColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; this._effects.push(new PsdDropShadowEffect({ version: version, blur: blur, intensity: intensity, angle: angle, distance: distance, color: color, blendMode: blendMode, enabled: enabled, globalAngle: globalAngle, opacity: opacity, nativeColor: nativeColor, })); } else if (fxTag === 'isdw') { const version = data.readUint32(); const blur = data.readUint32(); const intensity = data.readUint32(); const angle = data.readUint32(); const distance = data.readUint32(); const color = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const blendMode = data.readString(8); const enabled = data.read() !== 0; const globalAngle = data.read() !== 0; const opacity = data.read(); const nativeColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; this._effects.push(new PsdInnerShadowEffect({ version: version, blur: blur, intensity: intensity, angle: angle, distance: distance, color: color, blendMode: blendMode, enabled: enabled, globalAngle: globalAngle, opacity: opacity, nativeColor: nativeColor, })); } else if (fxTag === 'oglw') { const version = data.readUint32(); const blur = data.readUint32(); const intensity = data.readUint32(); const color = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const blendMode = data.readString(8); const enabled = data.read() !== 0; const opacity = data.read(); let nativeColor = undefined; if (version === 2) { nativeColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; } this._effects.push(new PsdOuterGlowEffect({ version: version, blur: blur, intensity: intensity, color: color, blendMode: blendMode, enabled: enabled, opacity: opacity, nativeColor: nativeColor, })); } else if (fxTag === 'iglw') { const version = data.readUint32(); const blur = data.readUint32(); const intensity = data.readUint32(); const color = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const blendMode = data.readString(8); const enabled = data.read() !== 0; const opacity = data.read(); let invert = undefined; let nativeColor = undefined; if (version === 2) { invert = data.read() !== 0; nativeColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; } this._effects.push(new PsdInnerGlowEffect({ version: version, blur: blur, intensity: intensity, color: color, blendMode: blendMode, enabled: enabled, opacity: opacity, invert: invert, nativeColor: nativeColor, })); } else if (fxTag === 'bevl') { const version = data.readUint32(); const angle = data.readUint32(); const strength = data.readUint32(); const blur = data.readUint32(); const highlightBlendMode = data.readString(8); const shadowBlendMode = data.readString(8); const highlightColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const shadowColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const bevelStyle = data.read(); const highlightOpacity = data.read(); const shadowOpacity = data.read(); const enabled = data.read() !== 0; const globalAngle = data.read() !== 0; const upOrDown = data.read(); let realHighlightColor = undefined; let realShadowColor = undefined; if (version === 2) { realHighlightColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; realShadowColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; } this._effects.push(new PsdBevelEffect({ version: version, angle: angle, strength: strength, blur: blur, highlightBlendMode: highlightBlendMode, shadowBlendMode: shadowBlendMode, highlightColor: highlightColor, shadowColor: shadowColor, bevelStyle: bevelStyle, highlightOpacity: highlightOpacity, shadowOpacity: shadowOpacity, enabled: enabled, globalAngle: globalAngle, upOrDown: upOrDown, realHighlightColor: realHighlightColor, realShadowColor: realShadowColor, })); } else if (fxTag === 'sofi') { const version = data.readUint32(); const blendMode = data.readString(4); const color = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; const opacity = data.read(); const enabled = data.read() !== 0; const nativeColor = [ data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), data.readUint16(), ]; this._effects.push(new PsdSolidFillEffect({ version: version, blendMode: blendMode, color: color, opacity: opacity, enabled: enabled, nativeColor: nativeColor, })); } else { data.skip(size); } } } } } } getChannel(id) { for (let i = 0; i < this._channels.length; ++i) { if (this._channels[i].id === id) { return this._channels[i]; } } return undefined; } readImageData(input, psd) { for (let i = 0; i < this._channels.length; ++i) { this._channels[i].readPlane({ input: input, width: this._width, height: this._height, bitDepth: psd.depth, }); } this._layerImage = PsdImage.createImageFromChannels(this._width, this._height, this._channels, psd.colorMode, psd.depth); } } PsdLayer.signature = 0x3842494d; //# sourceMappingURL=psd-layer.js.map