Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge changes from opendesigndev/psd-ts (Modified #74) #93

Merged
merged 31 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c7ed29b
resolve conflicts
alexanderspevak Nov 16, 2022
28ca61d
work in progress
alexanderspevak Dec 6, 2022
f853eb7
Add pattern test
Dec 6, 2022
3c62470
fix rendering patterns
Dec 6, 2022
d5bdb58
fix rendering propperly now :)
Dec 7, 2022
acd1522
add tests and custom errors
alexanderspevak Dec 7, 2022
fdb947e
address code review comments
alexanderspevak Dec 12, 2022
6deab45
Merge pull request #1 from opendesigndev/feature/enable-props
alexspevak Jan 9, 2023
8fd16d4
throw on unsupported compression
alexanderspevak Jan 16, 2023
5724d7d
Merge pull request #7 from opendesigndev/bugfix/zip-without-prediction
alexspevak Jan 19, 2023
79a4bb8
expose maskData on group
alexanderspevak Jan 19, 2023
5a3f352
Merge pull request #10 from opendesigndev/bugfix/expose-maskData-on-g…
alexspevak Jan 19, 2023
f8b0372
expose image on Group Layer mask
alexspevak Jan 20, 2023
6a2a88e
fix after code review
alexspevak Jan 20, 2023
fe9ad53
Merge pull request #12 from opendesigndev/bugfix/expose-image-on-group
alexspevak Jan 20, 2023
562a319
add padding to pattern reading
alexspevak Jan 24, 2023
7a08263
Update readPatternAliBlock.ts
alexspevak Jan 24, 2023
ed3c604
use method from cursor for padding
alexspevak Jan 25, 2023
0ced991
Merge pull request #13 from opendesigndev/bugfix/add-padding-pattern-…
alexspevak Jan 25, 2023
22415a7
catch on invalid signature
alexspevak Jan 26, 2023
d4b8e99
Merge pull request #15 from opendesigndev/bugfix/invalid-signature-2
alexspevak Jan 26, 2023
b670bda
add RrCm and RrIn
alexspevak Jan 26, 2023
83b3b76
Merge pull request #16 from opendesigndev/bugfix/invalid-unit-float-type
alexspevak Jan 26, 2023
917f76d
make possibility for mask data to be undefined when length is falsy
alexspevak Feb 10, 2023
db2d1ff
Merge pull request #18 from opendesigndev/bugfix/do-not-read-mask-dat…
alexspevak Feb 10, 2023
f087f63
remove +1 for height and width
alexspevak Feb 16, 2023
491a2dd
Merge pull request #19 from opendesigndev/bugfix/rle-compressed-height
alexspevak Feb 16, 2023
f83d274
expose multipbleObjectBasedeffects and ObjectUndocumented
alexspevak Feb 22, 2023
f9ae80c
Merge pull request #20 from opendesigndev/improvement/expose-tagged-b…
alexspevak Feb 27, 2023
2295b53
fix: typo in PatternDataRectangle
pastelmind Jul 13, 2023
b9093f8
feat: Change PatternData.channels to an array
pastelmind Jul 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion packages/psd/src/classes/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// Copyright 2021-present NAVER WEBTOON
// MIT License

import {GroupFrame, LayerProperties} from "../sections";
import {BlendMode, Clipping} from "../interfaces";
import {decodeGrayscale} from "../methods";
import {GroupFrame, LayerProperties, MaskData} from "../sections";
import {area} from "../utils";
import {NodeChild, NodeParent} from "./Node";
import {NodeBase} from "./NodeBase";

Expand Down Expand Up @@ -47,4 +50,46 @@ export class Group implements NodeBase<NodeParent, NodeChild> {
this.children.forEach((node) => (node as NodeBase).freeze?.());
Object.freeze(this.children);
}

get blendMode(): BlendMode | undefined {
return this.layerFrame?.layerProperties.blendMode;
}

get isHidden(): boolean {
return this.layerFrame?.layerProperties.hidden ?? false;
}

get maskData(): MaskData | undefined {
return this.layerFrame?.layerProperties.maskData;
}

get clipping(): Clipping {
return this.layerFrame?.layerProperties.clippingMask ?? Clipping.Base;
}

get id(): number | undefined {
return this.layerFrame?.id;
}

async userMask(): Promise<Uint8Array | undefined> {
const userMask = this.layerFrame?.userMask;
const {maskData} = this;

if (!maskData || !userMask) {
return;
}

return decodeGrayscale(area(maskData), userMask);
}

async realUserMask(): Promise<Uint8Array | undefined> {
const maskData = this.maskData?.realData;
const userMask = this.layerFrame?.realUserMask;

if (!maskData || !userMask) {
return;
}

return decodeGrayscale(area(maskData), userMask);
}
}
17 changes: 14 additions & 3 deletions packages/psd/src/classes/Layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright 2021-present NAVER WEBTOON
// MIT License

import {EngineData, ImageData} from "../interfaces";
import {BlendMode, Clipping, EngineData, ImageData} from "../interfaces";
import {decodeGrayscale} from "../methods";
import {LayerFrame, MaskData, LayerProperties} from "../sections";
import {area} from "../utils";
Expand Down Expand Up @@ -32,6 +32,7 @@ export class Layer
get name(): string {
return this.layerFrame.layerProperties.name;
}

get width(): number {
return this.layerFrame.width;
}
Expand All @@ -47,10 +48,16 @@ export class Layer
get opacity(): number {
return this.layerFrame.layerProperties.opacity;
}

get blendMode(): BlendMode {
return this.layerFrame.layerProperties.blendMode;
}

get composedOpacity(): number {
return this.parent.composedOpacity * (this.opacity / 255);
}
get maskData(): MaskData {

get maskData(): MaskData | undefined {
return this.layerFrame.layerProperties.maskData;
}

Expand All @@ -63,7 +70,7 @@ export class Layer
}

async realUserMask(): Promise<Uint8Array | undefined> {
const maskData = this.maskData.realData;
const maskData = this.maskData?.realData;
const userMask = this.layerFrame.realUserMask;
if (!maskData || !userMask) {
return undefined;
Expand Down Expand Up @@ -104,4 +111,8 @@ export class Layer

return {red, green, blue, alpha};
}

get clipping(): Clipping {
return this.layerFrame.layerProperties.clippingMask;
}
}
39 changes: 38 additions & 1 deletion packages/psd/src/classes/Psd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
// MIT License

import {
ChannelKind,
ColorMode,
Depth,
getChannelKindOffset,
Guide,
ImageData,
ParsingResult,
Pattern,
ResolutionInfo,
ResourceType,
} from "../interfaces";
import {parse} from "../methods";
import {generateRgba, parse} from "../methods";
import {AdditionalLayerProperties} from "../sections";
import {dimensions, InvalidColorMode, MissingColorChannel} from "../utils";
import {Group} from "./Group";
import {Layer} from "./Layer";
import {assertIsNodeParent, Node, NodeChild} from "./Node";
Expand Down Expand Up @@ -100,6 +104,7 @@ export class Psd extends Synthesizable implements NodeBase<never, NodeChild> {

protected get imageData(): ImageData {
const {compression, red, green, blue, alpha} = this.parsingResult.imageData;

return {
red: {compression, data: red},
green: green ? {compression, data: green} : undefined,
Expand All @@ -108,6 +113,38 @@ export class Psd extends Synthesizable implements NodeBase<never, NodeChild> {
};
}

get patterns(): Pattern[] {
const {Patt, Pat2, Pat3} = this.additionalLayerProperties;
return [
...(Patt?.data ?? []),
...(Pat2?.data ?? []),
...(Pat3?.data ?? []),
];
}

public decodePattern(pattern: Pattern): Promise<Uint8ClampedArray> {
if (pattern.imageMode !== ColorMode.Rgb) {
throw new InvalidColorMode();
}

const channels = pattern.patternData?.channels;

const red = channels[getChannelKindOffset(ChannelKind.Red)];
if (!red) {
throw new MissingColorChannel("missing red channel");
}

const green =
channels[getChannelKindOffset(ChannelKind.Green)] || undefined;
const blue = channels[getChannelKindOffset(ChannelKind.Blue)] || undefined;
const alpha =
channels[getChannelKindOffset(ChannelKind.TransparencyMask)] || undefined;

const {width, height} = dimensions(pattern.patternData.rectangle);

return generateRgba(width, height, red, green, blue, alpha);
}

protected buildTreeStructure(): void {
const {groups, layers, orders} = this.parsingResult.layerAndMaskInfo;
const stack: Node[] = [this];
Expand Down
4 changes: 3 additions & 1 deletion packages/psd/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export {
ResolutionUnit,
AliKey,
PathRecordType,
DescriptorValueType,
UnitFloatType,
} from "./interfaces";
export type {Guide} from "./interfaces";
export type {Guide, AdditionalLayerInfo} from "./interfaces";

export default Psd;
24 changes: 24 additions & 0 deletions packages/psd/src/interfaces/AdditionalLayerInfo/AliKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ export enum AliKey {

VectorStrokeData = "vstk",
ObjectBasedEffects = "lfx2",
MultipleObjectBasedEffects = "lmfx",
ObjectBasedUndocumented = "lfxs",
GradientFillSetting = "GdFl",
SolidColorSheetSetting = "SoCo",
PatternFillSetting = "PtFl",
VectorStrokeContentData = "vscg",
VectorOriginationData = "vogk",
BlendOptionsCapacity = "iOpa",
VectorMaskSetting1 = "vmsk",
VectorMaskSetting2 = "vsms",
Expand All @@ -30,4 +33,25 @@ export enum AliKey {
LinkedLayer = "lnkD",
LinkedLayer2 = "lnk2",
LinkedLayer3 = "lnk3",
LayerNameSourceSetting = "lnsr",
BrightnessAndContrast = "brit",
Levels = "levl",
Curves = "curv",
Exposure = "expA",
Vibrance = "vibA",
HueSaturationOld = "hue ",
ColorBalance = "blnc",
BlackAndWhite = "blwh",
PhotoFilter = "phfl",
ChannelMixer = "mixr",
ColorLookup = "clrL",
Invert = "nvrt",
Posterize = "post",
Threshold = "thrs",
GradientMapSettings = "grdm",
SelectiveColor = "selc",

Pattern1 = "Patt",
Pattern2 = "Pat2",
Pattern3 = "Pat3",
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @webtoon/psd
// Copyright 2021-present NAVER WEBTOON
// MIT License

import {Descriptor} from "../Descriptor";
import {KnownAliBlock} from "./AliBlockBase";
import {AliKey} from "./AliKey";

export interface MultipleObjectBasedEffectsAliBlock
extends KnownAliBlock<AliKey.MultipleObjectBasedEffects> {
version: number;
descriptorVersion: number;
descriptor: Descriptor;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// @webtoon/psd
// Copyright 2021-present NAVER WEBTOON
// MIT License

import {Descriptor} from "../Descriptor";
import {KnownAliBlock} from "./AliBlockBase";
import {AliKey} from "./AliKey";

export interface ObjectBasedUndocumentedAliBlock
extends KnownAliBlock<AliKey.ObjectBasedUndocumented> {
version: number;
descriptorVersion: number;
descriptor: Descriptor;
}
48 changes: 48 additions & 0 deletions packages/psd/src/interfaces/AdditionalLayerInfo/PatternAliBlock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// @webtoon/psd
// Copyright 2021-present NAVER WEBTOON
// MIT License

import {ChannelBytes} from "../ChannelBytes";
import {KnownAliBlock} from "./AliBlockBase";
import {AliKey} from "./AliKey";

export interface PatternDataRectangle {
top: number;
left: number;
bottom: number;
right: number;
}

export interface PatternDataChannel extends ChannelBytes {
written: true;
length: number;
pixelDepth1: number;
rectangle: PatternDataRectangle;
pixelDepth2: number;
}

export interface PatternData {
version: number;
length: number;
rectangle: PatternDataRectangle;
numberOfChannels: number;
channels: (PatternDataChannel | null)[];
}

export type ColorTable = [number, number, number][];

export interface Pattern {
version: number;
imageMode: number;
width: number;
height: number;
name: string;
id: string;
colorTable?: ColorTable;
patternData: PatternData;
}

export interface PatternAliBlock
extends KnownAliBlock<AliKey.Pattern1 | AliKey.Pattern2 | AliKey.Pattern3> {
data: Pattern[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// @webtoon/psd
// Copyright 2021-present NAVER WEBTOON
// MIT License

import {VersionedDescriptor} from "../Descriptor";
import {KnownAliBlock} from "./AliBlockBase";
import {AliKey} from "./AliKey";

export interface VectorOriginationDataAliBlock
extends KnownAliBlock<AliKey.VectorOriginationData> {
version: number;
data: VersionedDescriptor;
}
12 changes: 12 additions & 0 deletions packages/psd/src/interfaces/AdditionalLayerInfo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@ import {SolidColorSheetSettingAliBlock} from "./SolidColorSheetSettingAliBlock";
import {TypeToolObjectSettingAliBlock} from "./TypeToolObjectSettingAliBlock";
import {UnicodeLayerNameAliBlock} from "./UnicodeLayerNameAliBlock";
import {VectorMaskSettingAliBlock} from "./VectorMaskSettingAliBlock";
import {VectorOriginationDataAliBlock} from "./VectorOriginationDataAliBlock";
import {VectorStrokeContentDataAliBlock} from "./VectorStrokeContentDataAliBlock";
import {VectorStrokeDataAliBlock} from "./VectorStrokeDataAliBlock";
import {PatternAliBlock} from "./PatternAliBlock";
import {MultipleObjectBasedEffectsAliBlock} from "./MultipleObjectBasedEffectsAliBlock";
import {ObjectBasedUndocumentedAliBlock} from "./ObjectBasedUndocumentedAliBlock";

export * from "./AliKey";
export * from "./SectionDividerSettingAliBlock";
Expand All @@ -31,6 +35,8 @@ export * from "./HueSaturationAliBlock";
export * from "./LayerIdAliBlock";
export * from "./NestedSectionDividerSettingAliBlock";
export * from "./ObjectBasedEffectsAliBlock";
export * from "./MultipleObjectBasedEffectsAliBlock";
export * from "./ObjectBasedUndocumentedAliBlock";
export * from "./PatternFillSettingAliBlock";
export * from "./SolidColorSheetSettingAliBlock";
export * from "./VectorMaskSettingAliBlock";
Expand All @@ -39,6 +45,7 @@ export * from "./VectorStrokeDataAliBlock";
export * from "./ArtboardDataAliBlock";
export * from "./SmartObjectPlacedLayerDataAliBlock";
export * from "./LinkedLayerAliBlock";
export * from "./PatternAliBlock";

/**
* Represents a single Additional Layer Info block ("ALI block").
Expand All @@ -49,16 +56,21 @@ export type AdditionalLayerInfo =
| UnicodeLayerNameAliBlock
| VectorStrokeDataAliBlock
| ObjectBasedEffectsAliBlock
| MultipleObjectBasedEffectsAliBlock
| ObjectBasedUndocumentedAliBlock
| GradientFillSettingAliBlock
| SolidColorSheetSettingAliBlock
| PatternFillSettingAliBlock
| VectorStrokeContentDataAliBlock
| VectorOriginationDataAliBlock
| BlendOptionsCapacityAliBlock
| VectorMaskSettingAliBlock
| PatternFillSettingAliBlock
| HueSaturationAliBlock
| NestedSectionDividerSettingAliBlock
| LayerIdAliBlock
| ArtboardDataAliBlock
| SmartObjectPlacedLayerDataAliBlock
| LinkedLayerAliBlock
| PatternAliBlock
| UnknownAliBlock;
8 changes: 8 additions & 0 deletions packages/psd/src/interfaces/Descriptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ export enum UnitFloatType {
Pixels = "#Pxl",
/** Tagged unit value */
Points = "#Pnt",

/**
* Following descriptions were taken from https://psd-tools.readthedocs.io/en/latest/reference/psd_tools.terminology.html#psd_tools.terminology.Enum.RulerCm
* */
/** Ruler centimeter */
RulerCm = "RrCm",
/**Ruler inches */
RulerInches = "RrIn",
}

/**
Expand Down
Loading