Updated tinyexr.

This commit is contained in:
Branimir Karadžić
2018-07-19 20:52:39 -07:00
parent dc121dbc27
commit 3d3d9d3273

View File

@@ -306,12 +306,14 @@ extern int ParseEXRVersionFromMemory(EXRVersion *version,
const unsigned char *memory, size_t size); const unsigned char *memory, size_t size);
// Parse single-part OpenEXR header from a file and initialize `EXRHeader`. // Parse single-part OpenEXR header from a file and initialize `EXRHeader`.
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version, extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version,
const char *filename, const char **err); const char *filename, const char **err);
// Parse single-part OpenEXR header from a memory and initialize `EXRHeader`. // Parse single-part OpenEXR header from a memory and initialize `EXRHeader`.
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int ParseEXRHeaderFromMemory(EXRHeader *header, extern int ParseEXRHeaderFromMemory(EXRHeader *header,
const EXRVersion *version, const EXRVersion *version,
const unsigned char *memory, size_t size, const unsigned char *memory, size_t size,
@@ -319,7 +321,8 @@ extern int ParseEXRHeaderFromMemory(EXRHeader *header,
// Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*` // Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*`
// array. // array.
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers, extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers,
int *num_headers, int *num_headers,
const EXRVersion *version, const EXRVersion *version,
@@ -328,7 +331,8 @@ extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers,
// Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*` // Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*`
// array // array
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers, extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers,
int *num_headers, int *num_headers,
const EXRVersion *version, const EXRVersion *version,
@@ -340,7 +344,8 @@ extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers,
// Application can free EXRImage using `FreeEXRImage` // Application can free EXRImage using `FreeEXRImage`
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header, extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header,
const char *filename, const char **err); const char *filename, const char **err);
@@ -350,7 +355,8 @@ extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header,
// Application can free EXRImage using `FreeEXRImage` // Application can free EXRImage using `FreeEXRImage`
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header, extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header,
const unsigned char *memory, const unsigned char *memory,
const size_t size, const char **err); const size_t size, const char **err);
@@ -361,7 +367,8 @@ extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header,
// Application can free EXRImage using `FreeEXRImage` // Application can free EXRImage using `FreeEXRImage`
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int LoadEXRMultipartImageFromFile(EXRImage *images, extern int LoadEXRMultipartImageFromFile(EXRImage *images,
const EXRHeader **headers, const EXRHeader **headers,
unsigned int num_parts, unsigned int num_parts,
@@ -374,7 +381,8 @@ extern int LoadEXRMultipartImageFromFile(EXRImage *images,
// Application can free EXRImage using `FreeEXRImage` // Application can free EXRImage using `FreeEXRImage`
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int LoadEXRMultipartImageFromMemory(EXRImage *images, extern int LoadEXRMultipartImageFromMemory(EXRImage *images,
const EXRHeader **headers, const EXRHeader **headers,
unsigned int num_parts, unsigned int num_parts,
@@ -384,7 +392,8 @@ extern int LoadEXRMultipartImageFromMemory(EXRImage *images,
// Saves multi-channel, single-frame OpenEXR image to a file. // Saves multi-channel, single-frame OpenEXR image to a file.
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int SaveEXRImageToFile(const EXRImage *image, extern int SaveEXRImageToFile(const EXRImage *image,
const EXRHeader *exr_header, const char *filename, const EXRHeader *exr_header, const char *filename,
const char **err); const char **err);
@@ -394,7 +403,8 @@ extern int SaveEXRImageToFile(const EXRImage *image,
// Return the number of bytes if succes. // Return the number of bytes if succes.
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern size_t SaveEXRImageToMemory(const EXRImage *image, extern size_t SaveEXRImageToMemory(const EXRImage *image,
const EXRHeader *exr_header, const EXRHeader *exr_header,
unsigned char **memory, const char **err); unsigned char **memory, const char **err);
@@ -403,7 +413,8 @@ extern size_t SaveEXRImageToMemory(const EXRImage *image,
// Application must free memory of variables in DeepImage(image, offset_table) // Application must free memory of variables in DeepImage(image, offset_table)
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int LoadDeepEXR(DeepImage *out_image, const char *filename, extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
const char **err); const char **err);
@@ -426,7 +437,8 @@ extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
// RGB(A) channels. // RGB(A) channels.
// Returns negative value and may set error string in `err` when there's an // Returns negative value and may set error string in `err` when there's an
// error // error
// When there was an error message, Application must free `err` with FreeEXRErrorMessage() // When there was an error message, Application must free `err` with
// FreeEXRErrorMessage()
extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
const unsigned char *memory, size_t size, const unsigned char *memory, size_t size,
const char **err); const char **err);
@@ -2520,10 +2532,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r,
tinfl_status status = TINFL_STATUS_FAILED; tinfl_status status = TINFL_STATUS_FAILED;
mz_uint32 num_bits, dist, counter, num_extra; mz_uint32 num_bits, dist, counter, num_extra;
tinfl_bit_buf_t bit_buf; tinfl_bit_buf_t bit_buf;
const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = const mz_uint8 *pIn_buf_cur = pIn_buf_next,
pIn_buf_next + *pIn_buf_size; *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = mz_uint8 *pOut_buf_cur = pOut_buf_next,
pOut_buf_next + *pOut_buf_size; *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
size_t out_buf_size_mask = size_t out_buf_size_mask =
(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)
? (size_t)-1 ? (size_t)-1
@@ -2940,9 +2952,8 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
tinfl_status status = tinfl_decompress( tinfl_status status = tinfl_decompress(
&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
(mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
&dst_buf_size, &dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
(flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
MZ_FREE(pBuf); MZ_FREE(pBuf);
*pOut_len = 0; *pOut_len = 0;
@@ -2995,8 +3006,9 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size,
tinfl_status status = tinfl_status status =
tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs,
&in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
(flags & ~(TINFL_FLAG_HAS_MORE_INPUT | (flags &
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); ~(TINFL_FLAG_HAS_MORE_INPUT |
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
in_buf_ofs += in_buf_size; in_buf_ofs += in_buf_size;
if ((dst_buf_size) && if ((dst_buf_size) &&
(!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
@@ -3121,9 +3133,7 @@ static const mz_uint8 s_tdefl_large_dist_extra[128] = {
// Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted
// values. // values.
typedef struct { typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq;
mz_uint16 m_key, m_sym_index;
} tdefl_sym_freq;
static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms,
tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms0,
tdefl_sym_freq *pSyms1) { tdefl_sym_freq *pSyms1) {
@@ -5267,10 +5277,9 @@ mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index,
n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
pStat->m_comment_size = n; pStat->m_comment_size = n;
memcpy(pStat->m_comment, memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
n); n);
pStat->m_comment[n] = '\0'; pStat->m_comment[n] = '\0';
@@ -6957,13 +6966,12 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
// return bint.c[0] == 1; // return bint.c[0] == 1;
//} //}
static void SetErrorMessage(const std::string &msg, const char **err) static void SetErrorMessage(const std::string &msg, const char **err) {
{
if (err) { if (err) {
#ifdef _WIN32 #ifdef _WIN32
(*err) = _strdup(msg.c_str()); (*err) = _strdup(msg.c_str());
#else #else
(*err) = strdup(msg.c_str()); (*err) = strdup(msg.c_str());
#endif #endif
} }
} }
@@ -10095,6 +10103,12 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
outLine += (height - 1 - y) * x_stride; outLine += (height - 1 - y) * x_stride;
} }
if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
(data_ptr + data_len)) {
// Insufficient data size
return false;
}
for (int u = 0; u < width; u++) { for (int u = 0; u < width; u++) {
tinyexr::FP16 hf; tinyexr::FP16 hf;
@@ -10123,6 +10137,12 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
outLine += (height - 1 - y) * x_stride; outLine += (height - 1 - y) * x_stride;
} }
if (reinterpret_cast<const unsigned char *>(line_ptr + width) >
(data_ptr + data_len)) {
// Insufficient data size
return false;
}
for (int u = 0; u < width; u++) { for (int u = 0; u < width; u++) {
float val; float val;
tinyexr::cpy4(&val, line_ptr + u); tinyexr::cpy4(&val, line_ptr + u);
@@ -10143,6 +10163,12 @@ static bool DecodePixelData(/* out */ unsigned char **out_images,
} }
for (int u = 0; u < width; u++) { for (int u = 0; u < width; u++) {
if (reinterpret_cast<const unsigned char *>(line_ptr + u) >=
(data_ptr + data_len)) {
// Corrupsed data?
return false;
}
unsigned int val; unsigned int val;
tinyexr::cpy4(&val, line_ptr + u); tinyexr::cpy4(&val, line_ptr + u);
@@ -10325,6 +10351,9 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
size_t orig_size = size; size_t orig_size = size;
for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) { for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) {
if (0 == size) { if (0 == size) {
if (err) {
(*err) += "Insufficient data size for attributes.\n";
}
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} else if (marker[0] == '\0') { } else if (marker[0] == '\0') {
size--; size--;
@@ -10337,6 +10366,9 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
size_t marker_size; size_t marker_size;
if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size, if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size,
marker, size)) { marker, size)) {
if (err) {
(*err) += "Failed to read attribute.\n";
}
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
marker += marker_size; marker += marker_size;
@@ -10407,14 +10439,14 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
if (!ReadChannelInfo(info->channels, data)) { if (!ReadChannelInfo(info->channels, data)) {
if (err) { if (err) {
(*err) = "Failed to parse channel info."; (*err) += "Failed to parse channel info.\n";
} }
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
if (info->channels.size() < 1) { if (info->channels.size() < 1) {
if (err) { if (err) {
(*err) = "# of channels is zero."; (*err) += "# of channels is zero.\n";
} }
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -10648,7 +10680,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
const std::vector<tinyexr::tinyexr_uint64> &offsets, const std::vector<tinyexr::tinyexr_uint64> &offsets,
const unsigned char *head, const size_t size) { const unsigned char *head, const size_t size, std::string *err) {
int num_channels = exr_header->num_channels; int num_channels = exr_header->num_channels;
int num_scanline_blocks = 1; int num_scanline_blocks = 1;
@@ -10669,8 +10701,11 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
int pixel_data_size = 0; int pixel_data_size = 0;
size_t channel_offset = 0; size_t channel_offset = 0;
if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size, if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size,
&channel_offset, num_channels, &channel_offset, num_channels,
exr_header->channels)) { exr_header->channels)) {
if (err) {
(*err) += "Failed to compute channel layout.\n";
}
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -10692,6 +10727,9 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
// 4 byte : data size // 4 byte : data size
// ~ : data(uncompressed or compressed) // ~ : data(uncompressed or compressed)
if (offsets[tile_idx] + sizeof(int) * 5 > size) { if (offsets[tile_idx] + sizeof(int) * 5 > size) {
if (err) {
(*err) += "Insufficient data size.\n";
}
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -10720,6 +10758,9 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len)); tinyexr::swap4(reinterpret_cast<unsigned int *>(&data_len));
if (data_len < 4 || size_t(data_len) > data_size) { if (data_len < 4 || size_t(data_len) > data_size) {
if (err) {
(*err) += "Insufficient data length.\n";
}
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -10977,13 +11018,38 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
// OK // OK
break; break;
} else { } else {
tinyexr::SetErrorMessage("Cannot reconstruct lineOffset table in DecodeEXRImage.", err); tinyexr::SetErrorMessage(
"Cannot reconstruct lineOffset table in DecodeEXRImage.", err);
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
} }
} }
return DecodeChunk(exr_image, exr_header, offsets, head, size); {
std::string e;
int ret = DecodeChunk(exr_image, exr_header, offsets, head, size, &e);
if (ret != TINYEXR_SUCCESS) {
if (!e.empty()) {
tinyexr::SetErrorMessage(e, err);
}
// release memory(if exists)
if ((exr_header->num_channels > 0) && exr_image && exr_image->images) {
for (size_t c = 0; c < size_t(exr_header->num_channels); c++) {
if (exr_image->images[c]) {
free(exr_image->images[c]);
exr_image->images[c] = NULL;
}
}
free(exr_image->images);
exr_image->images = NULL;
}
}
return ret;
}
} }
} // namespace tinyexr } // namespace tinyexr
@@ -11004,11 +11070,14 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
{ {
int ret = ParseEXRVersionFromFile(&exr_version, filename); int ret = ParseEXRVersionFromFile(&exr_version, filename);
if (ret != TINYEXR_SUCCESS) { if (ret != TINYEXR_SUCCESS) {
tinyexr::SetErrorMessage("Invalid EXR header.", err);
return ret; return ret;
} }
if (exr_version.multipart || exr_version.non_image) { if (exr_version.multipart || exr_version.non_image) {
tinyexr::SetErrorMessage("Loading multipart or DeepImage is not supported in LoadEXR() API", err); tinyexr::SetErrorMessage(
"Loading multipart or DeepImage is not supported in LoadEXR() API",
err);
return TINYEXR_ERROR_INVALID_DATA; // @fixme. return TINYEXR_ERROR_INVALID_DATA; // @fixme.
} }
} }
@@ -11161,13 +11230,19 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
const unsigned char *memory, size_t size, const unsigned char *memory, size_t size,
const char **err) { const char **err) {
if (memory == NULL || exr_header == NULL) { if (memory == NULL || exr_header == NULL) {
tinyexr::SetErrorMessage("Invalid argument. `memory` or `exr_header` argument is null in ParseEXRHeaderFromMemory()", err); tinyexr::SetErrorMessage(
"Invalid argument. `memory` or `exr_header` argument is null in "
"ParseEXRHeaderFromMemory()",
err);
// Invalid argument // Invalid argument
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }
if (size < tinyexr::kEXRVersionSize) { if (size < tinyexr::kEXRVersionSize) {
tinyexr::SetErrorMessage(
"Insufficient header/data size.\n",
err);
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -11321,6 +11396,7 @@ int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header,
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
if (filesize < 16) { if (filesize < 16) {
tinyexr::SetErrorMessage("File size too short " + std::string(filename), err);
return TINYEXR_ERROR_INVALID_FILE; return TINYEXR_ERROR_INVALID_FILE;
} }
@@ -11342,7 +11418,8 @@ int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header,
const char **err) { const char **err) {
if (exr_image == NULL || memory == NULL || if (exr_image == NULL || memory == NULL ||
(size < tinyexr::kEXRVersionSize)) { (size < tinyexr::kEXRVersionSize)) {
tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory", err); tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory",
err);
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }
@@ -11370,14 +11447,16 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
#if !TINYEXR_USE_PIZ #if !TINYEXR_USE_PIZ
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
tinyexr::SetErrorMessage("PIZ compression is not supported in this build", err); tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
err);
return 0; return 0;
} }
#endif #endif
#if !TINYEXR_USE_ZFP #if !TINYEXR_USE_ZFP
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
tinyexr::SetErrorMessage("ZFP compression is not supported in this build", err); tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
err);
return 0; return 0;
} }
#endif #endif
@@ -11385,7 +11464,8 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
#if TINYEXR_USE_ZFP #if TINYEXR_USE_ZFP
for (size_t i = 0; i < static_cast<size_t>(exr_header->num_channels); i++) { for (size_t i = 0; i < static_cast<size_t>(exr_header->num_channels); i++) {
if (exr_header->requested_pixel_types[i] != TINYEXR_PIXELTYPE_FLOAT) { if (exr_header->requested_pixel_types[i] != TINYEXR_PIXELTYPE_FLOAT) {
tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression", err); tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression",
err);
return 0; return 0;
} }
} }
@@ -11595,7 +11675,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_HALF) {
if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) {
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
// Assume increasing Y // Assume increasing Y
float *line_ptr = reinterpret_cast<float *>(&buf.at( float *line_ptr = reinterpret_cast<float *>(&buf.at(
static_cast<size_t>(pixel_data_size * y * exr_image->width) + static_cast<size_t>(pixel_data_size * y * exr_image->width) +
channel_offset_list[c] * channel_offset_list[c] *
@@ -11616,7 +11696,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
} else if (exr_header->requested_pixel_types[c] == } else if (exr_header->requested_pixel_types[c] ==
TINYEXR_PIXELTYPE_HALF) { TINYEXR_PIXELTYPE_HALF) {
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
// Assume increasing Y // Assume increasing Y
unsigned short *line_ptr = reinterpret_cast<unsigned short *>( unsigned short *line_ptr = reinterpret_cast<unsigned short *>(
&buf.at(static_cast<size_t>(pixel_data_size * y * &buf.at(static_cast<size_t>(pixel_data_size * y *
exr_image->width) + exr_image->width) +
@@ -11685,8 +11765,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
// Assume increasing Y // Assume increasing Y
unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at( unsigned int *line_ptr = reinterpret_cast<unsigned int *>(&buf.at(
static_cast<size_t>(pixel_data_size * y * exr_image->width) + static_cast<size_t>(pixel_data_size * y * exr_image->width) +
channel_offset_list[c] * channel_offset_list[c] * static_cast<size_t>(exr_image->width)));
static_cast<size_t>(exr_image->width)));
for (int x = 0; x < exr_image->width; x++) { for (int x = 0; x < exr_image->width; x++) {
unsigned int val = reinterpret_cast<unsigned int **>( unsigned int val = reinterpret_cast<unsigned int **>(
exr_image->images)[c][(y + start_y) * exr_image->width + x]; exr_image->images)[c][(y + start_y) * exr_image->width + x];
@@ -11869,14 +11948,16 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header,
#if !TINYEXR_USE_PIZ #if !TINYEXR_USE_PIZ
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) {
tinyexr::SetErrorMessage("PIZ compression is not supported in this build", err); tinyexr::SetErrorMessage("PIZ compression is not supported in this build",
err);
return 0; return 0;
} }
#endif #endif
#if !TINYEXR_USE_ZFP #if !TINYEXR_USE_ZFP
if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) {
tinyexr::SetErrorMessage("ZFP compression is not supported in this build", err); tinyexr::SetErrorMessage("ZFP compression is not supported in this build",
err);
return 0; return 0;
} }
#endif #endif
@@ -11915,13 +11996,15 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
FILE *fp = NULL; FILE *fp = NULL;
errno_t errcode = fopen_s(&fp, filename, "rb"); errno_t errcode = fopen_s(&fp, filename, "rb");
if ((0 != errcode) || (!fp)) { if ((0 != errcode) || (!fp)) {
tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), err); tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename),
err);
return TINYEXR_ERROR_CANT_OPEN_FILE; return TINYEXR_ERROR_CANT_OPEN_FILE;
} }
#else #else
FILE *fp = fopen(filename, "rb"); FILE *fp = fopen(filename, "rb");
if (!fp) { if (!fp) {
tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), err); tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename),
err);
return TINYEXR_ERROR_CANT_OPEN_FILE; return TINYEXR_ERROR_CANT_OPEN_FILE;
} }
#endif #endif
@@ -11934,7 +12017,8 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
if (filesize == 0) { if (filesize == 0) {
fclose(fp); fclose(fp);
tinyexr::SetErrorMessage("File size is zero : " + std::string(filename), err); tinyexr::SetErrorMessage("File size is zero : " + std::string(filename),
err);
return TINYEXR_ERROR_INVALID_FILE; return TINYEXR_ERROR_INVALID_FILE;
} }
@@ -12377,7 +12461,8 @@ int FreeEXRImage(EXRImage *exr_image) {
int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version,
const char *filename, const char **err) { const char *filename, const char **err) {
if (exr_header == NULL || exr_version == NULL || filename == NULL) { if (exr_header == NULL || exr_version == NULL || filename == NULL) {
tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile", err); tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile",
err);
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }
@@ -12406,7 +12491,8 @@ int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version,
fclose(fp); fclose(fp);
if (ret != filesize) { if (ret != filesize) {
tinyexr::SetErrorMessage("fread() error on " + std::string(filename), err); tinyexr::SetErrorMessage("fread() error on " + std::string(filename),
err);
return TINYEXR_ERROR_INVALID_FILE; return TINYEXR_ERROR_INVALID_FILE;
} }
} }
@@ -12423,11 +12509,14 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers,
if (memory == NULL || exr_headers == NULL || num_headers == NULL || if (memory == NULL || exr_headers == NULL || num_headers == NULL ||
exr_version == NULL) { exr_version == NULL) {
// Invalid argument // Invalid argument
tinyexr::SetErrorMessage("Invalid argument for ParseEXRMultipartHeaderFromMemory", err); tinyexr::SetErrorMessage(
"Invalid argument for ParseEXRMultipartHeaderFromMemory", err);
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }
if (size < tinyexr::kEXRVersionSize) { if (size < tinyexr::kEXRVersionSize) {
tinyexr::SetErrorMessage(
"Data size too short", err);
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -12457,7 +12546,8 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers,
// `chunkCount` must exist in the header. // `chunkCount` must exist in the header.
if (info.chunk_count == 0) { if (info.chunk_count == 0) {
tinyexr::SetErrorMessage("`chunkCount' attribute is not found in the header.", err); tinyexr::SetErrorMessage(
"`chunkCount' attribute is not found in the header.", err);
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -12492,7 +12582,8 @@ int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers,
const char *filename, const char **err) { const char *filename, const char **err) {
if (exr_headers == NULL || num_headers == NULL || exr_version == NULL || if (exr_headers == NULL || num_headers == NULL || exr_version == NULL ||
filename == NULL) { filename == NULL) {
tinyexr::SetErrorMessage("Invalid argument for ParseEXRMultipartHeaderFromFile()", err); tinyexr::SetErrorMessage(
"Invalid argument for ParseEXRMultipartHeaderFromFile()", err);
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }
@@ -12630,7 +12721,8 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
const size_t size, const char **err) { const size_t size, const char **err) {
if (exr_images == NULL || exr_headers == NULL || num_parts == 0 || if (exr_images == NULL || exr_headers == NULL || num_parts == 0 ||
memory == NULL || (size <= tinyexr::kEXRVersionSize)) { memory == NULL || (size <= tinyexr::kEXRVersionSize)) {
tinyexr::SetErrorMessage("Invalid argument for LoadEXRMultipartImageFromMemory()", err); tinyexr::SetErrorMessage(
"Invalid argument for LoadEXRMultipartImageFromMemory()", err);
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }
@@ -12673,7 +12765,8 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
tinyexr::swap8(&offset); tinyexr::swap8(&offset);
if (offset >= size) { if (offset >= size) {
tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.", err); tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.",
err);
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
@@ -12698,15 +12791,19 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
tinyexr::swap4(&part_no); tinyexr::swap4(&part_no);
if (part_no != i) { if (part_no != i) {
tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.", err); tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.",
err);
return TINYEXR_ERROR_INVALID_DATA; return TINYEXR_ERROR_INVALID_DATA;
} }
} }
std::string e;
int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table, int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table,
memory, size); memory, size, &e);
if (ret != TINYEXR_SUCCESS) { if (ret != TINYEXR_SUCCESS) {
tinyexr::SetErrorMessage("Error in DecodeChunk()", err); if (!e.empty()) {
tinyexr::SetErrorMessage(e, err);
}
return ret; return ret;
} }
} }
@@ -12719,7 +12816,8 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
unsigned int num_parts, const char *filename, unsigned int num_parts, const char *filename,
const char **err) { const char **err) {
if (exr_images == NULL || exr_headers == NULL || num_parts == 0) { if (exr_images == NULL || exr_headers == NULL || num_parts == 0) {
tinyexr::SetErrorMessage("Invalid argument for LoadEXRMultipartImageFromFile", err); tinyexr::SetErrorMessage(
"Invalid argument for LoadEXRMultipartImageFromFile", err);
return TINYEXR_ERROR_INVALID_ARGUMENT; return TINYEXR_ERROR_INVALID_ARGUMENT;
} }