From 5cc8fea7e99144f0e25076edb29309385bcf013b Mon Sep 17 00:00:00 2001 From: Jesse Yurkovich Date: Sat, 6 May 2023 00:16:19 +0200 Subject: [PATCH] Fix #107212: Fix file browser thumbnails for images Fix several issues found while investigating missing browser thumbnails. TIFF, PSD, and PNG now use their old file check code. This is due to OIIO not having an early-out check within `.open`. Calling `.open` required a large portion of the file to be available (more than 8192 bytes). The code here can be removed in the future if/when a new API is available which alleviates this problem. PSD files often carry along a large blob of ICCProfile metadata. Attempting to roundtrip this metadata when we cache the thumbnail to .png was leading to problems. We suppress this metadata now as ICC profiles are not supported in general and are quite large. Lastly, even after the mentioned new API is available, OIIO will want to validate the full header of some file formats. DPX is the largest at a full 2048 bytes so we must have this as our minimum now too. OS's should be servicing this read call just as efficiently as when using 64. I could spot no performance difference here at least. This was missed during development because Blender will cache thumbnails into a special .thumbnails directory and the images I was using to test had already been cached there. Pull Request: https://projects.blender.org/blender/blender/pulls/107515 --- source/blender/imbuf/intern/format_png.cc | 6 +++++- source/blender/imbuf/intern/format_psd.cc | 6 +++++- source/blender/imbuf/intern/format_tiff.cc | 10 +++++++++- .../blender/imbuf/intern/oiio/openimageio_support.cc | 3 +++ source/blender/imbuf/intern/util.cc | 4 ++-- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/source/blender/imbuf/intern/format_png.cc b/source/blender/imbuf/intern/format_png.cc index 87b866dffd7..aac42ec6be0 100644 --- a/source/blender/imbuf/intern/format_png.cc +++ b/source/blender/imbuf/intern/format_png.cc @@ -13,7 +13,11 @@ extern "C" { bool imb_is_a_png(const uchar *mem, size_t size) { - return imb_oiio_check(mem, size, "png"); + const char signature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; + if (size < sizeof(signature)) { + return false; + } + return memcmp(signature, mem, sizeof(signature)) == 0; } ImBuf *imb_load_png(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) diff --git a/source/blender/imbuf/intern/format_psd.cc b/source/blender/imbuf/intern/format_psd.cc index 21c97108d75..0ebfebb43ce 100644 --- a/source/blender/imbuf/intern/format_psd.cc +++ b/source/blender/imbuf/intern/format_psd.cc @@ -13,7 +13,11 @@ extern "C" { bool imb_is_a_psd(const uchar *mem, size_t size) { - return imb_oiio_check(mem, size, "psd"); + const uchar magic[4] = {'8', 'B', 'P', 'S'}; + if (size < sizeof(magic)) { + return false; + } + return memcmp(magic, mem, sizeof(magic)) == 0; } ImBuf *imb_load_psd(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) diff --git a/source/blender/imbuf/intern/format_tiff.cc b/source/blender/imbuf/intern/format_tiff.cc index b779e3973de..e46e4db5bf2 100644 --- a/source/blender/imbuf/intern/format_tiff.cc +++ b/source/blender/imbuf/intern/format_tiff.cc @@ -13,7 +13,15 @@ extern "C" { bool imb_is_a_tiff(const uchar *mem, size_t size) { - return imb_oiio_check(mem, size, "tif"); + constexpr int MAGIC_SIZE = 4; + if (size < MAGIC_SIZE) { + return false; + } + + const char big_endian[MAGIC_SIZE] = {0x4d, 0x4d, 0x00, 0x2a}; + const char lil_endian[MAGIC_SIZE] = {0x49, 0x49, 0x2a, 0x00}; + return ((memcmp(big_endian, mem, MAGIC_SIZE) == 0) || + (memcmp(lil_endian, mem, MAGIC_SIZE) == 0)); } ImBuf *imb_load_tiff(const uchar *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE]) diff --git a/source/blender/imbuf/intern/oiio/openimageio_support.cc b/source/blender/imbuf/intern/oiio/openimageio_support.cc index 34bd9225182..ba8e5cc5de3 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_support.cc +++ b/source/blender/imbuf/intern/oiio/openimageio_support.cc @@ -225,6 +225,9 @@ static ImBuf *get_oiio_ibuf(ImageInput *in, const ReadContext &ctx, char colorsp ibuf->flags |= spec.extra_attribs.empty() ? 0 : IB_metadata; for (const auto &attrib : spec.extra_attribs) { + if (attrib.name().find("ICCProfile") != string::npos) { + continue; + } IMB_metadata_set_field(ibuf->metadata, attrib.name().c_str(), attrib.get_string().c_str()); } } diff --git a/source/blender/imbuf/intern/util.cc b/source/blender/imbuf/intern/util.cc index 286d8dfde83..ed8a5358ef1 100644 --- a/source/blender/imbuf/intern/util.cc +++ b/source/blender/imbuf/intern/util.cc @@ -88,8 +88,8 @@ const char *imb_ext_audio[] = { nullptr, }; -/* Increased from 32 to 64 because of the bitmaps header size. */ -#define HEADER_SIZE 64 +/* OIIO will validate the entire header of some files and DPX requires 2048 */ +#define HEADER_SIZE 2048 static ssize_t imb_ispic_read_header_from_filepath(const char *filepath, uchar buf[HEADER_SIZE]) {