Skip to content

Commit e3cd14c

Browse files
committed
feat: add support for CMYK color mode
1 parent 379759b commit e3cd14c

File tree

2 files changed

+17
-10
lines changed

2 files changed

+17
-10
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,5 @@
1414
.v8-cache
1515
TODO.md
1616
.idea
17+
18+
.DS_Store

src/psdReader.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface ChannelInfo {
99
length: number;
1010
}
1111

12-
export const supportedColorModes = [ColorMode.Bitmap, ColorMode.Grayscale, ColorMode.RGB, ColorMode.Indexed];
12+
export const supportedColorModes = [ColorMode.Bitmap, ColorMode.Grayscale, ColorMode.RGB, ColorMode.Indexed, ColorMode.CMYK];
1313
const colorModes = ['bitmap', 'grayscale', 'indexed', 'RGB', 'CMYK', 'multichannel', 'duotone', 'lab'];
1414

1515
function setupGrayscale(data: PixelData) {
@@ -635,7 +635,7 @@ function readLayerChannelImageData(reader: PsdReader, psd: Psd, layer: Layer, ch
635635
if (cmyk) {
636636
const cmykData = imageData;
637637
imageData = createImageData(cmykData.width, cmykData.height);
638-
cmykToRgb(cmykData, imageData, false);
638+
cmykToRgb(cmykData, imageData);
639639
}
640640

641641
if (reader.useImageData) {
@@ -802,10 +802,14 @@ function readImageData(reader: PsdReader, psd: Psd) {
802802
break;
803803
}
804804
case ColorMode.CMYK: {
805-
if (bitsPerChannel !== 8) throw new Error('bitsPerChannel Not supproted');
806-
if (psd.channels !== 4) throw new Error(`Invalid channel count`);
805+
if (bitsPerChannel !== 8) throw new Error('bitsPerChannel Not supported');
806+
// there is additional color channel for cmyk when channels === 5
807+
if (psd.channels !== 4 && psd.channels !== 5) throw new Error(`Invalid channel count`);
808+
// there is additional alpha channel for cmyk
809+
const channelLen = psd.channels! + 1;
807810

808811
const channels = [0, 1, 2, 3];
812+
const haveAlpha = reader.globalAlpha || psd.channels === 5;
809813
if (reader.globalAlpha) channels.push(4);
810814

811815
if (compression === Compression.RawData) {
@@ -818,12 +822,12 @@ function readImageData(reader: PsdReader, psd: Psd) {
818822
const cmykImageData: PixelData = {
819823
width: imageData.width,
820824
height: imageData.height,
821-
data: new Uint8Array(imageData.width * imageData.height * 5),
825+
data: new Uint8Array(imageData.width * imageData.height * channelLen),
822826
};
823827

824828
const start = reader.offset;
825-
readDataRLE(reader, cmykImageData, psd.width, psd.height, bitsPerChannel, 5, channels, reader.large);
826-
cmykToRgb(cmykImageData, imageData, true);
829+
readDataRLE(reader, cmykImageData, psd.width, psd.height, bitsPerChannel, channelLen, channels, reader.large);
830+
cmykToRgb(cmykImageData, imageData, !haveAlpha, channelLen);
827831

828832
if (RAW_IMAGE_DATA) (psd as any).imageDataRaw = new Uint8Array(reader.view.buffer, reader.view.byteOffset + start, reader.offset - start);
829833
} else {
@@ -860,12 +864,12 @@ function readImageData(reader: PsdReader, psd: Psd) {
860864
}
861865
}
862866

863-
function cmykToRgb(cmyk: PixelData, rgb: PixelData, reverseAlpha: boolean) {
867+
function cmykToRgb(cmyk: PixelData, rgb: PixelData, reverseAlpha = false, channelLen = 5) {
864868
const size = rgb.width * rgb.height * 4;
865869
const srcData = cmyk.data;
866870
const dstData = rgb.data;
867871

868-
for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
872+
for (let src = 0, dst = 0; dst < size; src += channelLen, dst += 4) {
869873
const c = srcData[src];
870874
const m = srcData[src + 1];
871875
const y = srcData[src + 2];
@@ -1033,7 +1037,8 @@ export function readDataRLE(reader: PsdReader, pixelData: PixelData | undefined,
10331037

10341038
if (bitDepth !== 1 && bitDepth !== 8) throw new Error(`Invalid bit depth (${bitDepth})`);
10351039

1036-
const extraLimit = (step - 1) | 0; // 3 for rgb, 4 for cmyk
1040+
const extraLimit = (step - 1) | 0; // 3 for rgb, 4 for cmyk, 5 for cmyk+extraColor
1041+
10371042

10381043
for (let c = 0, li = 0; c < offsets.length; c++) {
10391044
const offset = offsets[c] | 0;

0 commit comments

Comments
 (0)