Skip to content

Commit

Permalink
fix(psd): CMYK PSD files should copy alpha (#3918)
Browse files Browse the repository at this point in the history
During the CMYK to RGB conversion in PSDInput, the alpha channel was
never copied to the RGBA output. Converting a PSD to JPEG worked because
it ignored all the 0 alpha values, but converting to WebP would result
in a fully transparent image.

I added a cmyk-with-alpha.psd test to the psd-colormodes test to check
this

Signed-off-by: Jason Baumeister <jason@jasonbaumeister.com>
  • Loading branch information
jasonbaumeister authored Jul 22, 2023
1 parent e297a3b commit 88d354e
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 12 deletions.
31 changes: 20 additions & 11 deletions src/psd.imageio/psdinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ class PSDInput final : public ImageInput {
rgb[0] = convert_type<float, T>(R);
rgb[1] = convert_type<float, T>(G);
rgb[2] = convert_type<float, T>(B);

if (cmyk_stride == 5 && rgb_stride == 4) {
rgb[3] = convert_type<float, T>(cmyk[4]);
}
}
}

Expand Down Expand Up @@ -780,25 +784,30 @@ PSDInput::read_native_scanline(int subimage, int miplevel, int y, int /*z*/,
} else if (m_header.color_mode == ColorMode_CMYK) {
switch (bps) {
case 4: {
std::unique_ptr<float[]> cmyk(new float[4 * spec.width]);
interleave_row(cmyk.get(), channel_buffers, spec.width, 4);
cmyk_to_rgb(spec.width, cmyk.get(), 4, (float*)dst, spec.nchannels);
std::unique_ptr<float[]> cmyk(
new float[channel_count * spec.width]);
interleave_row(cmyk.get(), channel_buffers, spec.width,
channel_count);
cmyk_to_rgb(spec.width, cmyk.get(), channel_count, (float*)dst,
spec.nchannels);
break;
}
case 2: {
std::unique_ptr<unsigned short[]> cmyk(
new unsigned short[4 * spec.width]);
interleave_row(cmyk.get(), channel_buffers, spec.width, 4);
cmyk_to_rgb(spec.width, cmyk.get(), 4, (unsigned short*)dst,
spec.nchannels);
new unsigned short[channel_count * spec.width]);
interleave_row(cmyk.get(), channel_buffers, spec.width,
channel_count);
cmyk_to_rgb(spec.width, cmyk.get(), channel_count,
(unsigned short*)dst, spec.nchannels);
break;
}
default: {
std::unique_ptr<unsigned char[]> cmyk(
new unsigned char[4 * spec.width]);
interleave_row(cmyk.get(), channel_buffers, spec.width, 4);
cmyk_to_rgb(spec.width, cmyk.get(), 4, (unsigned char*)dst,
spec.nchannels);
new unsigned char[channel_count * spec.width]);
interleave_row(cmyk.get(), channel_buffers, spec.width,
channel_count);
cmyk_to_rgb(spec.width, cmyk.get(), channel_count,
(unsigned char*)dst, spec.nchannels);
break;
}
}
Expand Down
Binary file added testsuite/psd-colormodes/ref/cmyk-with-alpha.tif
Binary file not shown.
4 changes: 4 additions & 0 deletions testsuite/psd-colormodes/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Comparing "src/pattern2-16-grayscale.psd" and "pattern2-16-grayscale.psd.tif"
PASS
Comparing "src/pattern2-8-indexed.psd" and "pattern2-8-indexed.psd.tif"
PASS
Comparing "src/cmyk-with-alpha.psd" and "cmyk-with-alpha.psd.tif"
PASS
Comparing "pattern2-8-rgb.psd.tif" and "ref/pattern2.tif"
PASS
Comparing "pattern2-16-rgb.psd.tif" and "ref/pattern2.tif"
Expand All @@ -34,3 +36,5 @@ Comparing "pattern2-16-grayscale.psd.tif" and "ref/pattern2-gray.tif"
PASS
Comparing "pattern2-8-indexed.psd.tif" and "ref/pattern2-alpha.tif"
PASS
Comparing "cmyk-with-alpha.psd.tif" and "ref/cmyk-with-alpha.tif"
PASS
2 changes: 1 addition & 1 deletion testsuite/psd-colormodes/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"pattern2-8-multichannel.psd", "pattern2-16-multichannel.psd",
"pattern2-8-grayscale.psd", "pattern2-16-grayscale.psd",
#"pattern2-32-grayscale.psd",
"pattern2-8-indexed.psd",
"pattern2-8-indexed.psd", "cmyk-with-alpha.psd",
]
for f in files:
outfile = f+".tif"
Expand Down
Binary file added testsuite/psd-colormodes/src/cmyk-with-alpha.psd
Binary file not shown.

0 comments on commit 88d354e

Please sign in to comment.