Skip to content

Commit

Permalink
cmyka (disabled)
Browse files Browse the repository at this point in the history
  • Loading branch information
qbnu committed Dec 10, 2023
1 parent a0bb74c commit 65e2f32
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 25 deletions.
14 changes: 11 additions & 3 deletions src/JPEGView/ICCProfileTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#define FLAGS (cmsFLAGS_BLACKPOINTCOMPENSATION|cmsFLAGS_COPY_ALPHA)
#define TYPE_LabA_8 (COLORSPACE_SH(PT_Lab)|EXTRA_SH(1)|CHANNELS_SH(3)|BYTES_SH(1))
#define TYPE_YMCK_8 (COLORSPACE_SH(PT_CMYK)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1)|SWAPFIRST_SH(1))
#define TYPE_AKYMC_8 (COLORSPACE_SH(PT_CMYK)|EXTRA_SH(1)|CHANNELS_SH(4)|BYTES_SH(1)|DOSWAP_SH(1))


void* ICCProfileTransform::sRGBProfile = NULL;
Expand Down Expand Up @@ -85,6 +86,10 @@ void* ICCProfileTransform::CreateTransform(const void* profile, unsigned int siz
inFormat = TYPE_YMCK_8;
outFormat = TYPE_BGR_8;
break;
case FORMAT_AKYMC:
inFormat = TYPE_AKYMC_8;
outFormat = TYPE_BGRA_8;
break;
default:
return NULL;
}
Expand Down Expand Up @@ -117,10 +122,13 @@ bool ICCProfileTransform::DoTransform(void* transform, const void* inputBuffer,
if (transform == NULL || inputBuffer == NULL || outputBuffer == NULL || numPixels == 0)
return false;

cmsUInt32Number defaultStride = width * T_CHANNELS(cmsGetTransformInputFormat(transform));
cmsUInt32Number bytesPerLineOut = Helpers::DoPadding(width * T_CHANNELS(cmsGetTransformOutputFormat(transform)), 4);
cmsUInt32Number inFormat = cmsGetTransformInputFormat(transform);
cmsUInt32Number bppIn = T_CHANNELS(inFormat) + T_EXTRA(inFormat);
cmsUInt32Number outFormat = cmsGetTransformOutputFormat(transform);
cmsUInt32Number bppOut = T_CHANNELS(outFormat) + T_EXTRA(outFormat);
cmsUInt32Number bytesPerLineOut = Helpers::DoPadding(width * bppOut, 4);
if (stride == 0)
stride = defaultStride;
stride = width * bppIn;
cmsDoTransformLineStride(transform, inputBuffer, outputBuffer, width, height, stride, bytesPerLineOut, stride * height, bytesPerLineOut * height);
return true;
}
Expand Down
1 change: 1 addition & 0 deletions src/JPEGView/ICCProfileTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ICCProfileTransform
FORMAT_Lab,
FORMAT_LabA,
FORMAT_YMCK,
FORMAT_AKYMC,
};

// Create a transform from given ICC Profile to standard sRGB color space.
Expand Down
68 changes: 46 additions & 22 deletions src/JPEGView/PSDWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ static inline unsigned short ReadUShortFromFile(HANDLE file) {
}

// Read and return an unsigned char from file
static inline unsigned short ReadUCharFromFile(HANDLE file) {
static inline unsigned char ReadUCharFromFile(HANDLE file) {
unsigned char val;
ReadFromFile(&val, file, 1);
return val;
Expand Down Expand Up @@ -158,14 +158,16 @@ CJPEGImage* PsdReader::ReadImage(LPCTSTR strFileName, bool& bOutOfMemory)
break;
case MODE_Lab:
case MODE_RGB:
case MODE_CMYK:
nChannels = min(nRealChannels, 4);
break;
case MODE_CMYK:
nChannels = min(nRealChannels, 5);
break;
}
if (nChannels == 2) {
nChannels = 1;
}
ThrowIf(nChannels != 1 && nChannels != 3 && nChannels != 4);
ThrowIf(!nChannels);

// Skip color mode data
unsigned int nColorDataSize = ReadUIntFromFile(hFile);
Expand All @@ -175,7 +177,7 @@ CJPEGImage* PsdReader::ReadImage(LPCTSTR strFileName, bool& bOutOfMemory)
unsigned int nResourceSectionSize = ReadUIntFromFile(hFile);

// This default value should detect alpha channels for PSDs created by programs which don't save alpha identifiers (e.g. Krita, GIMP)
bool bUseAlpha = nChannels == 4;
bool bUseAlpha = nChannels >= 4;

for (;;) {
// Resource block signature
Expand Down Expand Up @@ -273,17 +275,21 @@ CJPEGImage* PsdReader::ReadImage(LPCTSTR strFileName, bool& bOutOfMemory)
}

// Apply ICC Profile
if (nChannels == 3 || nChannels == 4) {
if (nChannels >= 3) {
if (nColorMode == MODE_Lab) {
transform = ICCProfileTransform::CreateTransform(pICCProfile, nICCProfileSize, nChannels == 4 ? ICCProfileTransform::FORMAT_LabA : ICCProfileTransform::FORMAT_Lab);
if (transform == NULL) {
// If we can't convert Lab to sRGB then just use the Lightness channel as grayscale
nChannels = min(nChannels, 1);
nChannels = 1;
}
} else if (nColorMode == MODE_RGB) {
transform = ICCProfileTransform::CreateTransform(pICCProfile, nICCProfileSize, nChannels == 4 ? ICCProfileTransform::FORMAT_BGRA : ICCProfileTransform::FORMAT_BGR);
} else if (nColorMode == MODE_CMYK) {
transform = ICCProfileTransform::CreateTransform(pICCProfile, nICCProfileSize, ICCProfileTransform::FORMAT_YMCK);
} else if (nChannels >= 4 && nColorMode == MODE_CMYK) {
transform = ICCProfileTransform::CreateTransform(pICCProfile, nICCProfileSize, nChannels == 5 ? ICCProfileTransform::FORMAT_AKYMC : ICCProfileTransform::FORMAT_YMCK);

// Uncommenting this enables alpha channels in CMYK. It works for most images but causes weird bugs for one, so I disabled it.
// if (transform == NULL)
nChannels = 4;
}
}

Expand Down Expand Up @@ -369,25 +375,43 @@ CJPEGImage* PsdReader::ReadImage(LPCTSTR strFileName, bool& bOutOfMemory)
}
}

if (nColorMode != MODE_CMYK)
ICCProfileTransform::DoTransform(transform, pPixelData, pPixelData, nWidth, nHeight, nRowSize);
COLORREF backgroundColor = CSettingsProvider::This().ColorTransparency();

if (nChannels == 4) {
uint32* pImage32 = (uint32*)pPixelData;
if (nColorMode == MODE_CMYK) {
if (transform != NULL) {
uint32* pImage32 = (uint32*)pPixelData;

if (nColorMode == MODE_CMYK && transform != NULL) {
// Do proper color management for CMYK
for (int i = 0; i < nWidth * nHeight; i++)
for (int i = 0; i < nWidth * nHeight; i++) {
if (nChannels == 5)
pImage32 = (uint32*)((uint8*)pImage32 + 1);
*pImage32++ = ~(*pImage32);
ICCProfileTransform::DoTransform(transform, pPixelData, pPixelData, nWidth, nHeight, nRowSize);
nChannels = 3;
}

if (nChannels == 5) {
void* tempBuffer = new(std::nothrow) char[nRowSize * nHeight];
if (ICCProfileTransform::DoTransform(transform, pPixelData, tempBuffer, nWidth, nHeight, nRowSize)) {
delete[] pPixelData;
pPixelData = tempBuffer;
} else {
delete[] tempBuffer;
}
} else {
ICCProfileTransform::DoTransform(transform, pPixelData, pPixelData, nWidth, nHeight, nRowSize);
}
nChannels -= 1;
} else {
// Multiply alpha value into each AABBGGRR pixel
// Blend K channel for CMYK images, alpha channel for RGBA images
COLORREF backgroundColor = nColorMode == MODE_CMYK ? 0 : CSettingsProvider::This().ColorTransparency();
for (int i = 0; i < nWidth * nHeight; i++)
*pImage32++ = Helpers::AlphaBlendBackground(*pImage32, backgroundColor);
// Blend K channel for CMYK images if ICC profiles not supported
backgroundColor = 0;
}
} else {
ICCProfileTransform::DoTransform(transform, pPixelData, pPixelData, nWidth, nHeight, nRowSize);
}

if (nChannels == 4) {
uint32* pImage32 = (uint32*)pPixelData;
// Multiply alpha value into each AABBGGRR pixel
for (int i = 0; i < nWidth * nHeight; i++)
*pImage32++ = Helpers::AlphaBlendBackground(*pImage32, backgroundColor);
}

Image = new CJPEGImage(nWidth, nHeight, pPixelData, pEXIFData, nChannels, 0, IF_PSD, false, 0, 1, 0);
Expand Down

0 comments on commit 65e2f32

Please sign in to comment.