Skip to content

Commit

Permalink
PSD: Fix thumbnail extraction for PSD files
Browse files Browse the repository at this point in the history
Fixes 3660

In investigating this issue, I also noticed that now that IOProxy
support can be relied on, the old code that in the psd reader that
directly fumbles with libjpeg is not needed and can be replaced by
just a couple of lines to make an ImageBuf read from an IOProxy.

And it fixes the bug, too. So I'm not even going to try to figure
out what was going wrong with the old code.
  • Loading branch information
lgritz committed Nov 13, 2022
1 parent 6da2b6e commit 3758cf4
Show file tree
Hide file tree
Showing 6 changed files with 6 additions and 176 deletions.
2 changes: 1 addition & 1 deletion src/include/OpenImageIO/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ class OIIO_UTIL_API IOVecOutput : public IOProxy {
/// IOProxy subclass for reading that wraps an cspan<char>.
class OIIO_UTIL_API IOMemReader : public IOProxy {
public:
IOMemReader(void* buf, size_t size)
IOMemReader(const void* buf, size_t size)
: IOProxy("", Read)
, m_buf((const unsigned char*)buf, size)
{
Expand Down
2 changes: 0 additions & 2 deletions src/jpeg.imageio/jpeg_pvt.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ class JpgInput final : public ImageInput {
void jpegerror(my_error_ptr myerr, bool fatal = false);

private:
FILE* m_fd;
std::string m_filename;
int m_next_scanline; // Which scanline is the next to read?
bool m_raw; // Read raw coefficients, not scanlines
Expand All @@ -101,7 +100,6 @@ class JpgInput final : public ImageInput {

void init()
{
m_fd = NULL;
m_raw = false;
m_cmyk = false;
m_fatalerr = false;
Expand Down
4 changes: 1 addition & 3 deletions src/psd.imageio/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@
# SPDX-License-Identifier: BSD-3-Clause
# https://github.com/OpenImageIO/oiio

add_oiio_plugin (psdinput.cpp jpeg_memory_src.cpp
INCLUDE_DIRS ${JPEG_INCLUDE_DIR}
LINK_LIBRARIES JPEG::JPEG)
add_oiio_plugin (psdinput.cpp)

91 changes: 0 additions & 91 deletions src/psd.imageio/jpeg_memory_src.cpp

This file was deleted.

29 changes: 0 additions & 29 deletions src/psd.imageio/jpeg_memory_src.h

This file was deleted.

54 changes: 4 additions & 50 deletions src/psd.imageio/psdinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include <OpenImageIO/imagebufalgo.h>
#include <OpenImageIO/tiffutils.h>

#include "jpeg_memory_src.h"
// #include "jpeg_memory_src.h"
#include "psd_pvt.h"

OIIO_PLUGIN_NAMESPACE_BEGIN
Expand Down Expand Up @@ -265,13 +265,6 @@ class PSDInput final : public ImageInput {

//Load thumbnail resource, used for resources 1033 and 1036
bool load_resource_thumbnail(uint32_t length, bool isBGR);
//For thumbnail loading
struct thumbnail_error_mgr {
jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
METHODDEF(void)
thumbnail_error_exit(j_common_ptr cinfo);

//Layers
bool load_layers();
Expand Down Expand Up @@ -1270,9 +1263,6 @@ PSDInput::load_resource_thumbnail(uint32_t length, bool isBGR)
uint32_t compressed_size;
uint16_t bpp;
uint16_t planes;
int stride;
jpeg_decompress_struct cinfo;
thumbnail_error_mgr jerr;
uint32_t jpeg_length = length - 28;

bool ok = read_bige<uint32_t>(format) && read_bige<uint32_t>(width)
Expand Down Expand Up @@ -1312,40 +1302,13 @@ PSDInput::load_resource_thumbnail(uint32_t length, bool isBGR)
return false;
}

cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = thumbnail_error_exit;
if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo);
errorfmt("[Image Resource] [JPEG Thumbnail] libjpeg error");
return false;
}
std::string jpeg_data(jpeg_length, '\0');
if (!ioread(&jpeg_data[0], jpeg_length))
return false;

jpeg_create_decompress(&cinfo);
jpeg_memory_src(&cinfo, (unsigned char*)&jpeg_data[0], jpeg_length);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
stride = cinfo.output_width * cinfo.output_components;
ImageSpec thumbspec(cinfo.output_width, cinfo.output_height, 3, TypeUInt8);
m_thumbnail.reset(thumbspec);
// jpeg_destroy_decompress will deallocate this
JSAMPLE** buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo,
JPOOL_IMAGE, stride, 1);
while (cinfo.output_scanline < cinfo.output_height) {
if (jpeg_read_scanlines(&cinfo, buffer, 1) != 1) {
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
errorfmt("[Image Resource] [JPEG Thumbnail] libjpeg error");
return false;
}
m_thumbnail.get_pixels(ROI(0, width, cinfo.output_scanline,
cinfo.output_scanline + 1, 0, 1, 0, 3),
TypeUInt8, buffer[0]);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
Filesystem::IOMemReader thumbblob(jpeg_data.data(), jpeg_length);
m_thumbnail = ImageBuf("thumbnail.jpg", 0, 0, nullptr, nullptr, &thumbblob);
m_thumbnail.read(0, 0, true);

// Set these attributes for the merged composite only (subimage 0)
composite_attribute("thumbnail_width", (int)width);
Expand All @@ -1358,15 +1321,6 @@ PSDInput::load_resource_thumbnail(uint32_t length, bool isBGR)



void
PSDInput::thumbnail_error_exit(j_common_ptr cinfo)
{
thumbnail_error_mgr* mgr = (thumbnail_error_mgr*)cinfo->err;
longjmp(mgr->setjmp_buffer, 1);
}



bool
PSDInput::load_layers()
{
Expand Down

0 comments on commit 3758cf4

Please sign in to comment.