tinyexr: Sync with upstream 1.0.7

(cherry picked from commit b70e2af3b7)
This commit is contained in:
Rémi Verschelde 2023-08-07 18:25:37 +02:00 committed by Yuri Sizov
parent 894d4ca769
commit 023e154cb4
1 changed files with 87 additions and 9 deletions

View File

@ -114,6 +114,11 @@ extern "C" {
#define TINYEXR_USE_STB_ZLIB (0) #define TINYEXR_USE_STB_ZLIB (0)
#endif #endif
// Use nanozlib.
#ifndef TINYEXR_USE_NANOZLIB
#define TINYEXR_USE_NANOZLIB (0)
#endif
// Disable PIZ compression when applying cpplint. // Disable PIZ compression when applying cpplint.
#ifndef TINYEXR_USE_PIZ #ifndef TINYEXR_USE_PIZ
#define TINYEXR_USE_PIZ (1) #define TINYEXR_USE_PIZ (1)
@ -608,7 +613,10 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
#define NOMINMAX #define NOMINMAX
#endif #endif
#include <windows.h> // for UTF-8 and memory-mapping #include <windows.h> // for UTF-8 and memory-mapping
#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)
#define TINYEXR_USE_WIN32_MMAP (1) #define TINYEXR_USE_WIN32_MMAP (1)
#endif
#elif defined(__linux__) || defined(__unix__) #elif defined(__linux__) || defined(__unix__)
#include <fcntl.h> // for open() #include <fcntl.h> // for open()
@ -650,7 +658,7 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
#include <omp.h> #include <omp.h>
#endif #endif
#if TINYEXR_USE_MINIZ #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
#include <miniz.h> #include <miniz.h>
#else #else
// Issue #46. Please include your own zlib-compatible API header before // Issue #46. Please include your own zlib-compatible API header before
@ -658,6 +666,11 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
//#include "zlib.h" //#include "zlib.h"
#endif #endif
#if defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1)
#define NANOZLIB_IMPLEMENTATION
#include "nanozlib.h"
#endif
#if TINYEXR_USE_STB_ZLIB #if TINYEXR_USE_STB_ZLIB
// Since we don't know where a project has stb_image.h and stb_image_write.h // Since we don't know where a project has stb_image.h and stb_image_write.h
// and whether they are in the include path, we don't include them here, and // and whether they are in the include path, we don't include them here, and
@ -668,6 +681,7 @@ extern "C" int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuf
extern "C" unsigned char *stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality); extern "C" unsigned char *stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality);
#endif #endif
#if TINYEXR_USE_ZFP #if TINYEXR_USE_ZFP
#ifdef __clang__ #ifdef __clang__
@ -1343,7 +1357,7 @@ static bool CompressZip(unsigned char *dst,
} }
} }
#if TINYEXR_USE_MINIZ #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
// //
// Compress the data using miniz // Compress the data using miniz
// //
@ -1357,7 +1371,7 @@ static bool CompressZip(unsigned char *dst,
} }
compressedSize = outSize; compressedSize = outSize;
#elif TINYEXR_USE_STB_ZLIB #elif defined(TINYEXR_USE_STB_ZLIB) && (TINYEXR_USE_STB_ZLIB==1)
int outSize; int outSize;
unsigned char* ret = stbi_zlib_compress(const_cast<unsigned char*>(&tmpBuf.at(0)), src_size, &outSize, 8); unsigned char* ret = stbi_zlib_compress(const_cast<unsigned char*>(&tmpBuf.at(0)), src_size, &outSize, 8);
if (!ret) { if (!ret) {
@ -1366,6 +1380,18 @@ static bool CompressZip(unsigned char *dst,
memcpy(dst, ret, outSize); memcpy(dst, ret, outSize);
free(ret); free(ret);
compressedSize = outSize;
#elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1)
uint64_t dstSize = nanoz_compressBound(static_cast<uint64_t>(src_size));
int outSize{0};
unsigned char *ret = nanoz_compress(&tmpBuf.at(0), src_size, &outSize, /* quality */8);
if (!ret) {
return false;
}
memcpy(dst, ret, outSize);
free(ret);
compressedSize = outSize; compressedSize = outSize;
#else #else
uLong outSize = compressBound(static_cast<uLong>(src_size)); uLong outSize = compressBound(static_cast<uLong>(src_size));
@ -1398,7 +1424,7 @@ static bool DecompressZip(unsigned char *dst,
} }
std::vector<unsigned char> tmpBuf(*uncompressed_size); std::vector<unsigned char> tmpBuf(*uncompressed_size);
#if TINYEXR_USE_MINIZ #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
int ret = int ret =
mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
if (MZ_OK != ret) { if (MZ_OK != ret) {
@ -1410,6 +1436,17 @@ static bool DecompressZip(unsigned char *dst,
if (ret < 0) { if (ret < 0) {
return false; return false;
} }
#elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1)
uint64_t dest_size = (*uncompressed_size);
uint64_t uncomp_size{0};
nanoz_status_t ret =
nanoz_uncompress(src, src_size, dest_size, &tmpBuf.at(0), &uncomp_size);
if (NANOZ_SUCCESS != ret) {
return false;
}
if ((*uncompressed_size) != uncomp_size) {
return false;
}
#else #else
int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size);
if (Z_OK != ret) { if (Z_OK != ret) {
@ -5715,7 +5752,7 @@ static bool isValidTile(const EXRHeader* exr_header,
static bool ReconstructTileOffsets(OffsetData& offset_data, static bool ReconstructTileOffsets(OffsetData& offset_data,
const EXRHeader* exr_header, const EXRHeader* exr_header,
const unsigned char* head, const unsigned char* marker, const size_t /*size*/, const unsigned char* head, const unsigned char* marker, const size_t size,
bool isMultiPartFile, bool isMultiPartFile,
bool isDeep) { bool isDeep) {
int numXLevels = offset_data.num_x_levels; int numXLevels = offset_data.num_x_levels;
@ -5724,11 +5761,20 @@ static bool ReconstructTileOffsets(OffsetData& offset_data,
for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) { for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) {
tinyexr::tinyexr_uint64 tileOffset = tinyexr::tinyexr_uint64(marker - head); tinyexr::tinyexr_uint64 tileOffset = tinyexr::tinyexr_uint64(marker - head);
if (isMultiPartFile) { if (isMultiPartFile) {
if ((marker + sizeof(int)) >= (head + size)) {
return false;
}
//int partNumber; //int partNumber;
marker += sizeof(int); marker += sizeof(int);
} }
if ((marker + 4 * sizeof(int)) >= (head + size)) {
return false;
}
int tileX; int tileX;
memcpy(&tileX, marker, sizeof(int)); memcpy(&tileX, marker, sizeof(int));
tinyexr::swap4(&tileX); tinyexr::swap4(&tileX);
@ -5750,6 +5796,9 @@ static bool ReconstructTileOffsets(OffsetData& offset_data,
marker += sizeof(int); marker += sizeof(int);
if (isDeep) { if (isDeep) {
if ((marker + 2 * sizeof(tinyexr::tinyexr_int64)) >= (head + size)) {
return false;
}
tinyexr::tinyexr_int64 packed_offset_table_size; tinyexr::tinyexr_int64 packed_offset_table_size;
memcpy(&packed_offset_table_size, marker, sizeof(tinyexr::tinyexr_int64)); memcpy(&packed_offset_table_size, marker, sizeof(tinyexr::tinyexr_int64));
tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64*>(&packed_offset_table_size)); tinyexr::swap8(reinterpret_cast<tinyexr::tinyexr_uint64*>(&packed_offset_table_size));
@ -5763,13 +5812,26 @@ static bool ReconstructTileOffsets(OffsetData& offset_data,
// next Int64 is unpacked sample size - skip that too // next Int64 is unpacked sample size - skip that too
marker += packed_offset_table_size + packed_sample_size + 8; marker += packed_offset_table_size + packed_sample_size + 8;
if (marker >= (head + size)) {
return false;
}
} else { } else {
int dataSize; if ((marker + sizeof(uint32_t)) >= (head + size)) {
memcpy(&dataSize, marker, sizeof(int)); return false;
}
uint32_t dataSize;
memcpy(&dataSize, marker, sizeof(uint32_t));
tinyexr::swap4(&dataSize); tinyexr::swap4(&dataSize);
marker += sizeof(int); marker += sizeof(uint32_t);
marker += dataSize; marker += dataSize;
if (marker >= (head + size)) {
return false;
}
} }
if (!isValidTile(exr_header, offset_data, if (!isValidTile(exr_header, offset_data,
@ -5781,6 +5843,19 @@ static bool ReconstructTileOffsets(OffsetData& offset_data,
if (level_idx < 0) { if (level_idx < 0) {
return false; return false;
} }
if (size_t(level_idx) >= offset_data.offsets.size()) {
return false;
}
if (size_t(tileY) >= offset_data.offsets[size_t(level_idx)].size()) {
return false;
}
if (size_t(tileX) >= offset_data.offsets[size_t(level_idx)][size_t(tileY)].size()) {
return false;
}
offset_data.offsets[size_t(level_idx)][size_t(tileY)][size_t(tileX)] = tileOffset; offset_data.offsets[size_t(level_idx)][size_t(tileY)][size_t(tileX)] = tileOffset;
} }
} }
@ -7043,13 +7118,16 @@ static bool EncodePixelData(/* out */ std::vector<unsigned char>& out_data,
} else if ((compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) || } else if ((compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) ||
(compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) { (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) {
#if TINYEXR_USE_MINIZ #if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1)
std::vector<unsigned char> block(mz_compressBound( std::vector<unsigned char> block(mz_compressBound(
static_cast<unsigned long>(buf.size()))); static_cast<unsigned long>(buf.size())));
#elif TINYEXR_USE_STB_ZLIB #elif TINYEXR_USE_STB_ZLIB
// there is no compressBound() function, so we use a value that // there is no compressBound() function, so we use a value that
// is grossly overestimated, but should always work // is grossly overestimated, but should always work
std::vector<unsigned char> block(256 + 2 * buf.size()); std::vector<unsigned char> block(256 + 2 * buf.size());
#elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB == 1)
std::vector<unsigned char> block(nanoz_compressBound(
static_cast<unsigned long>(buf.size())));
#else #else
std::vector<unsigned char> block( std::vector<unsigned char> block(
compressBound(static_cast<uLong>(buf.size()))); compressBound(static_cast<uLong>(buf.size())));