From fdebab0b9d2334278663ee7368665eaf33a3669d Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Sat, 12 Nov 2022 16:17:16 -0800 Subject: [PATCH] PSD: Fix thumbnail extraction for PSD files 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. --- src/jpeg.imageio/jpeg_pvt.h | 2 - src/psd.imageio/CMakeLists.txt | 4 +- src/psd.imageio/jpeg_memory_src.cpp | 91 ----------------------------- src/psd.imageio/jpeg_memory_src.h | 29 --------- src/psd.imageio/psdinput.cpp | 54 ++--------------- 5 files changed, 5 insertions(+), 175 deletions(-) delete mode 100644 src/psd.imageio/jpeg_memory_src.cpp delete mode 100644 src/psd.imageio/jpeg_memory_src.h diff --git a/src/jpeg.imageio/jpeg_pvt.h b/src/jpeg.imageio/jpeg_pvt.h index f247be0fe9..91dae1bd2a 100644 --- a/src/jpeg.imageio/jpeg_pvt.h +++ b/src/jpeg.imageio/jpeg_pvt.h @@ -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 @@ -101,7 +100,6 @@ class JpgInput final : public ImageInput { void init() { - m_fd = NULL; m_raw = false; m_cmyk = false; m_fatalerr = false; diff --git a/src/psd.imageio/CMakeLists.txt b/src/psd.imageio/CMakeLists.txt index 61f30ac111..6fc000a6df 100644 --- a/src/psd.imageio/CMakeLists.txt +++ b/src/psd.imageio/CMakeLists.txt @@ -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) diff --git a/src/psd.imageio/jpeg_memory_src.cpp b/src/psd.imageio/jpeg_memory_src.cpp deleted file mode 100644 index 631d91faef..0000000000 --- a/src/psd.imageio/jpeg_memory_src.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2008-present Contributors to the OpenImageIO project. -// SPDX-License-Identifier: BSD-3-Clause -// https://github.com/OpenImageIO/oiio - -#include - -#include - -#include "jerror.h" -#include "jpeg_memory_src.h" - -namespace { - -void init_memory_source(j_decompress_ptr /*cinfo*/) {} - - - -void term_memory_source(j_decompress_ptr /*cinfo*/) {} - - - -void -skip_input(j_decompress_ptr cinfo, long num_bytes) -{ - struct jpeg_source_mgr* src = cinfo->src; - - if (!num_bytes) - return; - - while (num_bytes > (long)src->bytes_in_buffer) { - num_bytes -= (long)src->bytes_in_buffer; - (*src->fill_input_buffer)(cinfo); - } - src->next_input_byte += (size_t)num_bytes; - src->bytes_in_buffer -= (size_t)num_bytes; -} - - - -boolean -fill_input(j_decompress_ptr cinfo) -{ - static JOCTET mybuffer[4]; - - WARNMS(cinfo, JWRN_JPEG_EOF); - /* Insert a fake EOI marker */ - mybuffer[0] = (JOCTET)0xFF; - mybuffer[1] = (JOCTET)JPEG_EOI; - - cinfo->src->next_input_byte = mybuffer; - cinfo->src->bytes_in_buffer = 2; - - return TRUE; -} - -} // namespace - - - -OIIO_PLUGIN_NAMESPACE_BEGIN -namespace psd_pvt { - - -void -jpeg_memory_src(j_decompress_ptr cinfo, unsigned char* inbuffer, - unsigned long insize) -{ - struct jpeg_source_mgr* src; - - if (inbuffer == NULL || insize == 0) - ERREXIT(cinfo, JERR_INPUT_EMPTY); - - if (cinfo->src == NULL) { - cinfo->src = (struct jpeg_source_mgr*)(*cinfo->mem->alloc_small)( - (j_common_ptr)cinfo, JPOOL_PERMANENT, - (size_t)sizeof(struct jpeg_source_mgr)); - } - - src = cinfo->src; - src->init_source = init_memory_source; - src->fill_input_buffer = fill_input; - src->skip_input_data = skip_input; - src->resync_to_restart = jpeg_resync_to_restart; - src->term_source = term_memory_source; - src->bytes_in_buffer = (size_t)insize; - src->next_input_byte = (JOCTET*)inbuffer; -} - - -} // namespace psd_pvt -OIIO_PLUGIN_NAMESPACE_END diff --git a/src/psd.imageio/jpeg_memory_src.h b/src/psd.imageio/jpeg_memory_src.h deleted file mode 100644 index 85ac6d3081..0000000000 --- a/src/psd.imageio/jpeg_memory_src.h +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2008-present Contributors to the OpenImageIO project. -// SPDX-License-Identifier: BSD-3-Clause -// https://github.com/OpenImageIO/oiio - -#pragma once - -#ifdef _WIN32 -//#undef FAR -# define XMD_H -#endif - -extern "C" { -#include "jpeglib.h" -} - -OIIO_PLUGIN_NAMESPACE_BEGIN -namespace psd_pvt { - -// This function allows you to read a JPEG from memory using libjpeg. -// Newer versions of libjpeg have jpeg_mem_src which has the same functionality. -// inbuffer is the buffer that holds the JPEG data -// insize is the size of the buffer -void -jpeg_memory_src(j_decompress_ptr cinfo, unsigned char* inbuffer, - unsigned long insize); - -} // end namespace psd_pvt - -OIIO_PLUGIN_NAMESPACE_END diff --git a/src/psd.imageio/psdinput.cpp b/src/psd.imageio/psdinput.cpp index e61796a99d..caae9d0023 100644 --- a/src/psd.imageio/psdinput.cpp +++ b/src/psd.imageio/psdinput.cpp @@ -20,7 +20,7 @@ #include #include -#include "jpeg_memory_src.h" +// #include "jpeg_memory_src.h" #include "psd_pvt.h" OIIO_PLUGIN_NAMESPACE_BEGIN @@ -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(); @@ -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(format) && read_bige(width) @@ -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); @@ -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() {