Skip to content

Commit c232aed

Browse files
jessey-gitlgritz
authored andcommitted
fix(psd): various PSD files fail to load correctly (#4302)
The primary issue seemed to be that the ChannelInfo width and height were not filled in for some of the layers, notably the merged image data layer in most(all?) cases. A second issue was that there was incorrect nesting of the switch statement in `read_channel_row`. The last 3 case statements were all nested under the `if (!bigendian()) {` conditional from the 1st case. Fixes #4298 ## Tests Use `iconvert` on all PSD files contained in the attached .zip. Converting to both .exr and .png is a good test to ensure the data is flowing out to those formats correctly. [psd.zip](https://github.com/user-attachments/files/15905814/psd.zip) --------- Signed-off-by: Jesse Yurkovich <[email protected]>
1 parent eeb1cfd commit c232aed

File tree

8 files changed

+41
-39
lines changed

8 files changed

+41
-39
lines changed

src/doc/builtinplugins.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1876,7 +1876,7 @@ Lab or duotone modes.
18761876

18771877
**Custom I/O Overrides**
18781878

1879-
PSD output supports the "custom I/O" feature via the special ``"oiio:ioproxy"``
1879+
PSD input supports the "custom I/O" feature via the special ``"oiio:ioproxy"``
18801880
attributes (see Sections :ref:`sec-imageoutput-ioproxy` and
18811881
:ref:`sec-imageinput-ioproxy`) as well as the `set_ioproxy()` methods.
18821882

src/psd.imageio/psdinput.cpp

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,8 @@ PSDInput::load_image_data()
18921892
// setup some generic properties and read any RLE lengths
18931893
// Image Data Section has RLE lengths for all channels stored first
18941894
for (ChannelInfo& channel_info : m_image_data.channel_info) {
1895+
channel_info.width = m_header.width;
1896+
channel_info.height = m_header.height;
18951897
channel_info.compression = compression;
18961898
channel_info.channel_id = id++;
18971899
channel_info.data_length = row_length * m_header.height;
@@ -2047,39 +2049,39 @@ PSDInput::read_channel_row(ChannelInfo& channel_info, uint32_t row, char* data)
20472049
case 16: swap_endian((uint16_t*)data, channel_info.width); break;
20482050
case 32: swap_endian((uint32_t*)data, channel_info.width); break;
20492051
}
2050-
break;
2051-
case Compression_RLE: {
2052-
if (!ioseek(channel_info.row_pos[row]))
2053-
return false;
2054-
uint32_t rle_length = channel_info.rle_lengths[row];
2055-
char* rle_buffer;
2056-
OIIO_ALLOCATE_STACK_OR_HEAP(rle_buffer, char, rle_length);
2057-
if (!ioread(rle_buffer, rle_length)
2058-
|| !decompress_packbits(rle_buffer, data, rle_length,
2059-
channel_info.row_length))
2060-
return false;
2061-
} break;
2062-
case Compression_ZIP: {
2063-
OIIO_ASSERT(channel_info.decompressed_data.size()
2064-
== static_cast<uint64_t>(channel_info.width)
2065-
* channel_info.height * (m_header.depth / 8));
2066-
// We simply copy over the row into destination
2067-
uint64_t row_index = static_cast<uint64_t>(row) * channel_info.width
2068-
* (m_header.depth / 8);
2069-
std::memcpy(data, channel_info.decompressed_data.data() + row_index,
2070-
channel_info.row_length);
2071-
} break;
2072-
case Compression_ZIP_Predict: {
2073-
OIIO_ASSERT(channel_info.decompressed_data.size()
2074-
== static_cast<uint64_t>(channel_info.width)
2075-
* channel_info.height * (m_header.depth / 8));
2076-
// We simply copy over the row into destination
2077-
uint64_t row_index = static_cast<uint64_t>(row) * channel_info.width
2078-
* (m_header.depth / 8);
2079-
std::memcpy(data, channel_info.decompressed_data.data() + row_index,
2080-
channel_info.row_length);
2081-
} break;
20822052
}
2053+
break;
2054+
case Compression_RLE: {
2055+
if (!ioseek(channel_info.row_pos[row]))
2056+
return false;
2057+
uint32_t rle_length = channel_info.rle_lengths[row];
2058+
char* rle_buffer;
2059+
OIIO_ALLOCATE_STACK_OR_HEAP(rle_buffer, char, rle_length);
2060+
if (!ioread(rle_buffer, rle_length)
2061+
|| !decompress_packbits(rle_buffer, data, rle_length,
2062+
channel_info.row_length))
2063+
return false;
2064+
} break;
2065+
case Compression_ZIP: {
2066+
OIIO_ASSERT(channel_info.decompressed_data.size()
2067+
== static_cast<uint64_t>(channel_info.width)
2068+
* channel_info.height * (m_header.depth / 8));
2069+
// We simply copy over the row into destination
2070+
uint64_t row_index = static_cast<uint64_t>(row) * channel_info.width
2071+
* (m_header.depth / 8);
2072+
std::memcpy(data, channel_info.decompressed_data.data() + row_index,
2073+
channel_info.row_length);
2074+
} break;
2075+
case Compression_ZIP_Predict: {
2076+
OIIO_ASSERT(channel_info.decompressed_data.size()
2077+
== static_cast<uint64_t>(channel_info.width)
2078+
* channel_info.height * (m_header.depth / 8));
2079+
// We simply copy over the row into destination
2080+
uint64_t row_index = static_cast<uint64_t>(row) * channel_info.width
2081+
* (m_header.depth / 8);
2082+
std::memcpy(data, channel_info.decompressed_data.data() + row_index,
2083+
channel_info.row_length);
2084+
} break;
20832085
}
20842086

20852087
return true;

testsuite/psd-colormodes/ref/out.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ Comparing "pattern2-8-rgb.psd.tif" and "ref/pattern2.tif"
2222
PASS
2323
Comparing "pattern2-16-rgb.psd.tif" and "ref/pattern2.tif"
2424
PASS
25-
Comparing "pattern2-8-cmyk.psd.tif" and "ref/pattern2-cmyk.tif"
25+
Comparing "pattern2-8-cmyk.psd.tif" and "ref/pattern2-8-cmyk.psd.tif"
2626
PASS
2727
Comparing "pattern2-16-cmyk.psd.tif" and "ref/pattern2-16-cmyk.psd.tif"
2828
PASS
2929
Comparing "pattern2-8-multichannel.psd.tif" and "ref/pattern2.tif"
3030
PASS
3131
Comparing "pattern2-16-multichannel.psd.tif" and "ref/pattern2.tif"
3232
PASS
33-
Comparing "pattern2-8-grayscale.psd.tif" and "ref/pattern2-gray.tif"
33+
Comparing "pattern2-8-grayscale.psd.tif" and "ref/pattern2-8-grayscale.psd.tif"
3434
PASS
3535
Comparing "pattern2-16-grayscale.psd.tif" and "ref/pattern2-16-grayscale.psd.tif"
3636
PASS
13 Bytes
Binary file not shown.
1 Byte
Binary file not shown.
File renamed without changes.
File renamed without changes.

testsuite/psd/ref/out.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ Reading ../oiio-images/psd_rgb_8.psd
584584
stRef:originalDocumentID: "E146B3E37A92795EE3EA6577040DE6D5"
585585
Reading ../oiio-images/psd_rgb_16.psd
586586
../oiio-images/psd_rgb_16.psd : 320 x 240, 3 channel, uint16 psd
587-
SHA-1: 591F6850EB0B548DF2CE7177661440CB812E5C31
587+
SHA-1: E42334B0F0684E3C3BF9125F2920B07C44C17B11
588588
channel list: R, G, B
589589
Artist: "Daniel Wyatt"
590590
DateTime: "2007-01-18T15:49:21"
@@ -655,7 +655,7 @@ Reading ../oiio-images/psd_rgb_16.psd
655655
stRef:originalDocumentID: "E146B3E37A92795EE3EA6577040DE6D5"
656656
Reading ../oiio-images/psd_rgb_32.psd
657657
../oiio-images/psd_rgb_32.psd : 320 x 240, 3 channel, float psd
658-
SHA-1: B7F8CE4B4259A92AA13333EA8112C3E37C6BAB39
658+
SHA-1: 63CF8F7B010D24EFD3C41F51C16D8D285FE07313
659659
channel list: R, G, B
660660
Artist: "Daniel Wyatt"
661661
DateTime: "2007-01-18T15:49:21"
@@ -1459,7 +1459,7 @@ Reading src/Layers_16bit_RGB.psd
14591459
src/Layers_16bit_RGB.psd : 48 x 27, 3 channel, uint16 psd
14601460
4 subimages: 48x27 [u16,u16,u16], 48x27 [u16,u16,u16,u16], 48x27 [u16,u16,u16,u16], 48x27 [u16,u16,u16,u16]
14611461
subimage 0: 48 x 27, 3 channel, uint16 psd
1462-
SHA-1: 22EAC1FF517BCCEA8EBA31AB240C11518EE42424
1462+
SHA-1: 0228B2F3AA493695E9653E1C32D303022DDEFAE4
14631463
channel list: R, G, B
14641464
DateTime: "2024-03-06T15:22:40+01:00"
14651465
ICCProfile: 0, 0, 12, 72, 76, 105, 110, 111, 2, 16, 0, 0, 109, 110, 116, 114, ... [3144 x uint8]
@@ -1653,7 +1653,7 @@ Reading src/Layers_32bit_RGB.psd
16531653
src/Layers_32bit_RGB.psd : 48 x 27, 3 channel, float psd
16541654
4 subimages: 48x27 [f,f,f], 48x27 [f,f,f,f], 48x27 [f,f,f,f], 48x27 [f,f,f,f]
16551655
subimage 0: 48 x 27, 3 channel, float psd
1656-
SHA-1: 90D05324071E32026D22E44FA9EF027C80D97308
1656+
SHA-1: C9C84C45C64884BD4D6F1B1E91CCA6744EA3C06C
16571657
channel list: R, G, B
16581658
DateTime: "2024-03-06T15:22:40+01:00"
16591659
ICCProfile: 0, 0, 2, 56, 108, 99, 109, 115, 4, 48, 0, 0, 109, 110, 116, 114, ... [568 x uint8]

0 commit comments

Comments
 (0)