@@ -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 ] ;
1313const colorModes = [ 'bitmap' , 'grayscale' , 'indexed' , 'RGB' , 'CMYK' , 'multichannel' , 'duotone' , 'lab' ] ;
1414
1515function 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,20 +864,21 @@ 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 ) {
869- const c = srcData [ src ] ;
870- const m = srcData [ src + 1 ] ;
871- const y = srcData [ src + 2 ] ;
872- const k = srcData [ src + 3 ] ;
873- dstData [ dst ] = ( ( ( ( c * k ) | 0 ) / 255 ) | 0 ) ;
874- dstData [ dst + 1 ] = ( ( ( ( m * k ) | 0 ) / 255 ) | 0 ) ;
875- dstData [ dst + 2 ] = ( ( ( ( y * k ) | 0 ) / 255 ) | 0 ) ;
876- dstData [ dst + 3 ] = reverseAlpha ? 255 - srcData [ src + 4 ] : srcData [ src + 4 ] ;
872+ for ( let src = 0 , dst = 0 ; dst < size ; src += channelLen , dst += 4 ) {
873+ const c = 255 - srcData [ src + 0 ] ;
874+ const m = 255 - srcData [ src + 1 ] ;
875+ const y = 255 - srcData [ src + 2 ] ;
876+ const k = 255 - srcData [ src + 3 ] ;
877+ const a = srcData [ src + 4 ] ;
878+ dstData [ dst + 0 ] = ( ( 65535 - ( c * ( 255 - k ) + ( k << 8 ) ) ) >> 8 ) | 0 ;
879+ dstData [ dst + 1 ] = ( ( 65535 - ( m * ( 255 - k ) + ( k << 8 ) ) ) >> 8 ) | 0 ;
880+ dstData [ dst + 2 ] = ( ( 65535 - ( y * ( 255 - k ) + ( k << 8 ) ) ) >> 8 ) | 0 ;
881+ dstData [ dst + 3 ] = reverseAlpha ? 255 - a : a ;
877882 }
878883
879884 // for (let src = 0, dst = 0; dst < size; src += 5, dst += 4) {
@@ -1033,7 +1038,8 @@ export function readDataRLE(reader: PsdReader, pixelData: PixelData | undefined,
10331038
10341039 if ( bitDepth !== 1 && bitDepth !== 8 ) throw new Error ( `Invalid bit depth (${ bitDepth } )` ) ;
10351040
1036- const extraLimit = ( step - 1 ) | 0 ; // 3 for rgb, 4 for cmyk
1041+ const extraLimit = ( step - 1 ) | 0 ; // 3 for rgb, 4 for cmyk, 5 for cmyk+extraColor
1042+
10371043
10381044 for ( let c = 0 , li = 0 ; c < offsets . length ; c ++ ) {
10391045 const offset = offsets [ c ] | 0 ;
0 commit comments