tinyexr: Update to current upstream master branch
This commit is contained in:
parent
c2b8856f2d
commit
0036019e67
|
@ -390,7 +390,7 @@ Files extracted from upstream source:
|
|||
## tinyexr
|
||||
|
||||
- Upstream: https://github.com/syoyo/tinyexr
|
||||
- Version: 0.9.5+ (git a145d69)
|
||||
- Version: 0.9.5+ (git 9f784ca - 24 October 2017)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
|
@ -259,7 +259,8 @@ typedef struct _DeepImage {
|
|||
} DeepImage;
|
||||
|
||||
// @deprecated { to be removed. }
|
||||
// Loads single-frame OpenEXR image. Assume EXR image contains RGB(A) channels.
|
||||
// Loads single-frame OpenEXR image. Assume EXR image contains A(single channel
|
||||
// alpha) or RGB(A) channels.
|
||||
// Application must free image data as returned by `out_rgba`
|
||||
// Result image format is: float x RGBA x width x hight
|
||||
// Returns negative value and may set error string in `err` when there's an
|
||||
|
@ -269,9 +270,14 @@ extern int LoadEXR(float **out_rgba, int *width, int *height,
|
|||
|
||||
// @deprecated { to be removed. }
|
||||
// Saves single-frame OpenEXR image. Assume EXR image contains RGB(A) channels.
|
||||
// components must be 3(RGB) or 4(RGBA).
|
||||
// Result image format is: float x RGB(A) x width x hight
|
||||
extern int SaveEXR(const float *data, int width, int height, int components,
|
||||
// components must be 1(Grayscale), 3(RGB) or 4(RGBA).
|
||||
// Input image format is: `float x width x height`, or `float x RGB(A) x width x
|
||||
// hight`
|
||||
// Save image as fp16(HALF) format when `save_as_fp16` is positive non-zero
|
||||
// value.
|
||||
// Save image as fp32(FLOAT) format when `save_as_fp16` is 0.
|
||||
extern int SaveEXR(const float *data, const int width, const int height,
|
||||
const int components, const int save_as_fp16,
|
||||
const char *filename);
|
||||
|
||||
// Initialize EXRHeader struct
|
||||
|
@ -401,12 +407,11 @@ extern int LoadDeepEXR(DeepImage *out_image, const char *filename,
|
|||
// For emscripten.
|
||||
// Loads single-frame OpenEXR image from memory. Assume EXR image contains
|
||||
// RGB(A) channels.
|
||||
// `out_rgba` must have enough memory(at least sizeof(float) x 4(RGBA) x width x
|
||||
// hight)
|
||||
// Returns negative value and may set error string in `err` when there's an
|
||||
// error
|
||||
extern int LoadEXRFromMemory(float *out_rgba, const unsigned char *memory,
|
||||
size_t size, const char **err);
|
||||
extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
|
||||
const unsigned char *memory, size_t size,
|
||||
const char **err);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -439,7 +444,8 @@ extern int LoadEXRFromMemory(float *out_rgba, const unsigned char *memory,
|
|||
|
||||
#if TINYEXR_USE_MINIZ
|
||||
#else
|
||||
#include "zlib.h"
|
||||
// Issue #46. Please include your own zlib-compatible API header before including `tinyexr.h`
|
||||
//#include "zlib.h"
|
||||
#endif
|
||||
|
||||
#if TINYEXR_USE_ZFP
|
||||
|
@ -478,13 +484,11 @@ namespace miniz {
|
|||
#pragma clang diagnostic ignored "-Wsign-conversion"
|
||||
#pragma clang diagnostic ignored "-Wc++11-extensions"
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#ifdef __APPLE__
|
||||
#if __clang_major__ >= 8 && __clang__minor__ > 1
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#if __has_warning("-Wcomma")
|
||||
#pragma clang diagnostic ignored "-Wcomma"
|
||||
#endif
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
/* miniz.c v1.15 - public domain deflate/inflate, zlib-subset, ZIP
|
||||
reading/writing/appending, PNG writing
|
||||
|
@ -1913,11 +1917,11 @@ static void def_free_func(void *opaque, void *address) {
|
|||
(void)opaque, (void)address;
|
||||
MZ_FREE(address);
|
||||
}
|
||||
static void *def_realloc_func(void *opaque, void *address, size_t items,
|
||||
size_t size) {
|
||||
(void)opaque, (void)address, (void)items, (void)size;
|
||||
return MZ_REALLOC(address, items * size);
|
||||
}
|
||||
// static void *def_realloc_func(void *opaque, void *address, size_t items,
|
||||
// size_t size) {
|
||||
// (void)opaque, (void)address, (void)items, (void)size;
|
||||
// return MZ_REALLOC(address, items * size);
|
||||
//}
|
||||
|
||||
const char *mz_version(void) { return MZ_VERSION; }
|
||||
|
||||
|
@ -2889,8 +2893,9 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len,
|
|||
tinfl_status status = tinfl_decompress(
|
||||
&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size,
|
||||
(mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL,
|
||||
&dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
|
||||
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
|
||||
&dst_buf_size,
|
||||
(flags & ~TINFL_FLAG_HAS_MORE_INPUT) |
|
||||
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
|
||||
if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) {
|
||||
MZ_FREE(pBuf);
|
||||
*pOut_len = 0;
|
||||
|
@ -3537,9 +3542,10 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) {
|
|||
mz_uint saved_bit_buf, saved_bits_in;
|
||||
mz_uint8 *pSaved_output_buf;
|
||||
mz_bool comp_block_succeeded = MZ_FALSE;
|
||||
int n, use_raw_block =
|
||||
((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
|
||||
(d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
|
||||
int n,
|
||||
use_raw_block =
|
||||
((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) &&
|
||||
(d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
|
||||
mz_uint8 *pOutput_buf_start =
|
||||
((d->m_pPut_buf_func == NULL) &&
|
||||
((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE))
|
||||
|
@ -3569,8 +3575,9 @@ static int tdefl_flush_block(tdefl_compressor *d, int flush) {
|
|||
|
||||
if (!use_raw_block)
|
||||
comp_block_succeeded =
|
||||
tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
|
||||
(d->m_total_lz_bytes < 48));
|
||||
tdefl_compress_block(d,
|
||||
(d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) ||
|
||||
(d->m_total_lz_bytes < 48));
|
||||
|
||||
// If the block gets expanded, forget the current contents of the output
|
||||
// buffer and send a raw block instead.
|
||||
|
@ -5215,9 +5222,10 @@ 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_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
|
||||
pStat->m_comment_size = n;
|
||||
memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
|
||||
MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
|
||||
MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
|
||||
memcpy(pStat->m_comment,
|
||||
p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE +
|
||||
MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) +
|
||||
MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS),
|
||||
n);
|
||||
pStat->m_comment[n] = '\0';
|
||||
|
||||
|
@ -6875,6 +6883,12 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename,
|
|||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
#else
|
||||
|
||||
|
@ -7338,11 +7352,23 @@ static void CompressZip(unsigned char *dst,
|
|||
|
||||
compressedSize = outSize;
|
||||
#endif
|
||||
|
||||
// Use uncompressed data when compressed data is larger than uncompressed.
|
||||
// (Issue 40)
|
||||
if (compressedSize >= src_size) {
|
||||
compressedSize = src_size;
|
||||
memcpy(dst, src, src_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void DecompressZip(unsigned char *dst,
|
||||
unsigned long *uncompressed_size /* inout */,
|
||||
const unsigned char *src, unsigned long src_size) {
|
||||
if ((*uncompressed_size) == src_size) {
|
||||
// Data is not compressed(Issue 40).
|
||||
memcpy(dst, src, src_size);
|
||||
return;
|
||||
}
|
||||
std::vector<unsigned char> tmpBuf(*uncompressed_size);
|
||||
|
||||
#if TINYEXR_USE_MINIZ
|
||||
|
@ -7402,6 +7428,22 @@ static void DecompressZip(unsigned char *dst,
|
|||
#pragma clang diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4204) // nonstandard extension used : non-constant
|
||||
// aggregate initializer (also supported by GNU
|
||||
// C and C99, so no big deal)
|
||||
#pragma warning(disable : 4244) // 'initializing': conversion from '__int64' to
|
||||
// 'int', possible loss of data
|
||||
#pragma warning( \
|
||||
disable : 4267) // 'argument': conversion from '__int64' to 'int',
|
||||
// possible loss of data
|
||||
#pragma warning(disable : 4996) // 'strdup': The POSIX name for this item is
|
||||
// deprecated. Instead, use the ISO C and C++
|
||||
// conformant name: _strdup.
|
||||
#endif
|
||||
|
||||
|
||||
const int MIN_RUN_LENGTH = 3;
|
||||
const int MAX_RUN_LENGTH = 127;
|
||||
|
||||
|
@ -7494,6 +7536,7 @@ static int rleUncompress(int inLength, int maxLength, const signed char in[],
|
|||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
// End of RLE code from OpenEXR -----------------------------------
|
||||
|
||||
static void CompressRle(unsigned char *dst,
|
||||
|
@ -7554,11 +7597,24 @@ static void CompressRle(unsigned char *dst,
|
|||
assert(outSize > 0);
|
||||
|
||||
compressedSize = static_cast<tinyexr::tinyexr_uint64>(outSize);
|
||||
|
||||
// Use uncompressed data when compressed data is larger than uncompressed.
|
||||
// (Issue 40)
|
||||
if (compressedSize >= src_size) {
|
||||
compressedSize = src_size;
|
||||
memcpy(dst, src, src_size);
|
||||
}
|
||||
}
|
||||
|
||||
static void DecompressRle(unsigned char *dst,
|
||||
const unsigned long uncompressed_size,
|
||||
const unsigned char *src, unsigned long src_size) {
|
||||
if (uncompressed_size == src_size) {
|
||||
// Data is not compressed(Issue 40).
|
||||
memcpy(dst, src, src_size);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<unsigned char> tmpBuf(uncompressed_size);
|
||||
|
||||
int ret = rleUncompress(static_cast<int>(src_size),
|
||||
|
@ -8874,7 +8930,12 @@ static void applyLut(const unsigned short lut[USHORT_RANGE],
|
|||
#pragma clang diagnostic pop
|
||||
#endif // __clang__
|
||||
|
||||
static bool CompressPiz(unsigned char *outPtr, unsigned int &outSize,
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
static bool CompressPiz(unsigned char *outPtr, unsigned int *outSize,
|
||||
const unsigned char *inPtr, size_t inSize,
|
||||
const std::vector<ChannelInfo> &channelInfo,
|
||||
int data_width, int num_lines) {
|
||||
|
@ -8981,16 +9042,29 @@ static bool CompressPiz(unsigned char *outPtr, unsigned int &outSize,
|
|||
hufCompress(&tmpBuffer.at(0), static_cast<int>(tmpBuffer.size()), buf);
|
||||
memcpy(lengthPtr, &length, sizeof(int));
|
||||
|
||||
outSize = static_cast<unsigned int>(
|
||||
(*outSize) = static_cast<unsigned int>(
|
||||
(reinterpret_cast<unsigned char *>(buf) - outPtr) +
|
||||
static_cast<unsigned int>(length));
|
||||
|
||||
// Use uncompressed data when compressed data is larger than uncompressed.
|
||||
// (Issue 40)
|
||||
if ((*outSize) >= inSize) {
|
||||
(*outSize) = static_cast<unsigned int>(inSize);
|
||||
memcpy(outPtr, inPtr, inSize);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool DecompressPiz(unsigned char *outPtr, const unsigned char *inPtr,
|
||||
size_t tmpBufSize, int num_channels,
|
||||
size_t tmpBufSize, size_t inLen, int num_channels,
|
||||
const EXRChannelInfo *channels, int data_width,
|
||||
int num_lines) {
|
||||
if (inLen == tmpBufSize) {
|
||||
// Data is not compressed(Issue 40).
|
||||
memcpy(outPtr, inPtr, inLen);
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned char bitmap[BITMAP_SIZE];
|
||||
unsigned short minNonZero;
|
||||
unsigned short maxNonZero;
|
||||
|
@ -9165,6 +9239,11 @@ static bool DecompressZfp(float *dst, int dst_width, int dst_num_lines,
|
|||
const ZFPCompressionParam ¶m) {
|
||||
size_t uncompressed_size = dst_width * dst_num_lines * num_channels;
|
||||
|
||||
if (uncompressed_size == src_size) {
|
||||
// Data is not compressed(Issue 40).
|
||||
memcpy(dst, src, src_size);
|
||||
}
|
||||
|
||||
zfp_stream *zfp = NULL;
|
||||
zfp_field *field = NULL;
|
||||
|
||||
|
@ -9309,12 +9388,11 @@ static void DecodePixelData(/* out */ unsigned char **out_images,
|
|||
// Allocate original data size.
|
||||
std::vector<unsigned char> outBuf(static_cast<size_t>(
|
||||
static_cast<size_t>(width * num_lines) * pixel_data_size));
|
||||
size_t tmpBufLen = static_cast<size_t>(
|
||||
static_cast<size_t>(width * num_lines) * pixel_data_size);
|
||||
size_t tmpBufLen = outBuf.size();
|
||||
|
||||
bool ret = tinyexr::DecompressPiz(
|
||||
reinterpret_cast<unsigned char *>(&outBuf.at(0)), data_ptr, tmpBufLen,
|
||||
static_cast<int>(num_channels), channels, width, num_lines);
|
||||
data_len, static_cast<int>(num_channels), channels, width, num_lines);
|
||||
|
||||
assert(ret);
|
||||
(void)ret;
|
||||
|
@ -10039,8 +10117,7 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
|
|||
|
||||
} else if (attr_name.compare("compression") == 0) {
|
||||
bool ok = false;
|
||||
if ((data[0] >= TINYEXR_COMPRESSIONTYPE_NONE) &&
|
||||
(data[0] < TINYEXR_COMPRESSIONTYPE_PIZ)) {
|
||||
if (data[0] < TINYEXR_COMPRESSIONTYPE_PIZ) {
|
||||
ok = true;
|
||||
}
|
||||
|
||||
|
@ -10150,9 +10227,14 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header,
|
|||
// Custom attribute(up to TINYEXR_MAX_ATTRIBUTES)
|
||||
if (info->attributes.size() < TINYEXR_MAX_ATTRIBUTES) {
|
||||
EXRAttribute attrib;
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(attrib.name, attr_name.c_str(), 255);
|
||||
strncpy_s(attrib.type, attr_type.c_str(), 255);
|
||||
#else
|
||||
strncpy(attrib.name, attr_name.c_str(), 255);
|
||||
attrib.name[255] = '\0';
|
||||
strncpy(attrib.type, attr_type.c_str(), 255);
|
||||
#endif
|
||||
attrib.name[255] = '\0';
|
||||
attrib.type[255] = '\0';
|
||||
attrib.size = static_cast<int>(data.size());
|
||||
attrib.value = static_cast<unsigned char *>(malloc(data.size()));
|
||||
|
@ -10246,8 +10328,12 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
|
|||
exr_header->channels = static_cast<EXRChannelInfo *>(malloc(
|
||||
sizeof(EXRChannelInfo) * static_cast<size_t>(exr_header->num_channels)));
|
||||
for (size_t c = 0; c < static_cast<size_t>(exr_header->num_channels); c++) {
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
|
||||
#else
|
||||
strncpy(exr_header->channels[c].name, info.channels[c].name.c_str(), 255);
|
||||
// manually add '\0' for safety.
|
||||
#endif
|
||||
// manually add '\0' for safety.
|
||||
exr_header->channels[c].name[255] = '\0';
|
||||
|
||||
exr_header->channels[c].pixel_type = info.channels[c].pixel_type;
|
||||
|
@ -10309,6 +10395,8 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
|
|||
&channel_offset, num_channels,
|
||||
exr_header->channels);
|
||||
|
||||
bool invalid_data = false;
|
||||
|
||||
if (exr_header->tiled) {
|
||||
size_t num_tiles = offsets.size(); // = # of blocks
|
||||
|
||||
|
@ -10403,18 +10491,26 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
|
|||
// Adjust line_no with data_window.bmin.y
|
||||
line_no -= exr_header->data_window[1];
|
||||
|
||||
tinyexr::DecodePixelData(
|
||||
exr_image->images, exr_header->requested_pixel_types, data_ptr,
|
||||
static_cast<size_t>(data_len), exr_header->compression_type,
|
||||
exr_header->line_order, data_width, data_height, data_width, y,
|
||||
line_no, num_lines, static_cast<size_t>(pixel_data_size),
|
||||
static_cast<size_t>(exr_header->num_custom_attributes),
|
||||
exr_header->custom_attributes,
|
||||
static_cast<size_t>(exr_header->num_channels), exr_header->channels,
|
||||
channel_offset_list);
|
||||
if (line_no < 0) {
|
||||
invalid_data = true;
|
||||
} else {
|
||||
tinyexr::DecodePixelData(
|
||||
exr_image->images, exr_header->requested_pixel_types, data_ptr,
|
||||
static_cast<size_t>(data_len), exr_header->compression_type,
|
||||
exr_header->line_order, data_width, data_height, data_width, y,
|
||||
line_no, num_lines, static_cast<size_t>(pixel_data_size),
|
||||
static_cast<size_t>(exr_header->num_custom_attributes),
|
||||
exr_header->custom_attributes,
|
||||
static_cast<size_t>(exr_header->num_channels), exr_header->channels,
|
||||
channel_offset_list);
|
||||
}
|
||||
} // omp parallel
|
||||
}
|
||||
|
||||
if (invalid_data) {
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
// Overwrite `pixel_type` with `requested_pixel_type`.
|
||||
{
|
||||
for (int c = 0; c < exr_header->num_channels; c++) {
|
||||
|
@ -10633,46 +10729,63 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename,
|
|||
}
|
||||
}
|
||||
|
||||
if (idxR == -1) {
|
||||
if (err) {
|
||||
(*err) = "R channel not found\n";
|
||||
if ((idxA == 0) && (idxR == -1) && (idxG == -1) && (idxB == -1)) {
|
||||
// Alpha channel only.
|
||||
|
||||
(*out_rgba) = reinterpret_cast<float *>(
|
||||
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
|
||||
static_cast<size_t>(exr_image.height)));
|
||||
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
|
||||
const float val = reinterpret_cast<float **>(exr_image.images)[0][i];
|
||||
(*out_rgba)[4 * i + 0] = val;
|
||||
(*out_rgba)[4 * i + 1] = val;
|
||||
(*out_rgba)[4 * i + 2] = val;
|
||||
(*out_rgba)[4 * i + 3] = val;
|
||||
}
|
||||
} else {
|
||||
// Assume RGB(A)
|
||||
|
||||
if (idxR == -1) {
|
||||
if (err) {
|
||||
(*err) = "R channel not found\n";
|
||||
}
|
||||
|
||||
// @todo { free exr_image }
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
// @todo { free exr_image }
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (idxG == -1) {
|
||||
if (err) {
|
||||
(*err) = "G channel not found\n";
|
||||
if (idxG == -1) {
|
||||
if (err) {
|
||||
(*err) = "G channel not found\n";
|
||||
}
|
||||
// @todo { free exr_image }
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
// @todo { free exr_image }
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (idxB == -1) {
|
||||
if (err) {
|
||||
(*err) = "B channel not found\n";
|
||||
if (idxB == -1) {
|
||||
if (err) {
|
||||
(*err) = "B channel not found\n";
|
||||
}
|
||||
// @todo { free exr_image }
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
// @todo { free exr_image }
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
(*out_rgba) = reinterpret_cast<float *>(
|
||||
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
|
||||
static_cast<size_t>(exr_image.height)));
|
||||
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
|
||||
(*out_rgba)[4 * i + 0] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxR][i];
|
||||
(*out_rgba)[4 * i + 1] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxG][i];
|
||||
(*out_rgba)[4 * i + 2] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxB][i];
|
||||
if (idxA != -1) {
|
||||
(*out_rgba)[4 * i + 3] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxA][i];
|
||||
} else {
|
||||
(*out_rgba)[4 * i + 3] = 1.0;
|
||||
(*out_rgba) = reinterpret_cast<float *>(
|
||||
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
|
||||
static_cast<size_t>(exr_image.height)));
|
||||
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
|
||||
(*out_rgba)[4 * i + 0] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxR][i];
|
||||
(*out_rgba)[4 * i + 1] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxG][i];
|
||||
(*out_rgba)[4 * i + 2] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxB][i];
|
||||
if (idxA != -1) {
|
||||
(*out_rgba)[4 * i + 3] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxA][i];
|
||||
} else {
|
||||
(*out_rgba)[4 * i + 3] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10712,7 +10825,11 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
|
|||
|
||||
if (ret != TINYEXR_SUCCESS) {
|
||||
if (err && !err_str.empty()) {
|
||||
#ifdef _WIN32
|
||||
(*err) = _strdup(err_str.c_str()); // May leak
|
||||
#else
|
||||
(*err) = strdup(err_str.c_str()); // May leak
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10724,8 +10841,9 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int LoadEXRFromMemory(float *out_rgba, const unsigned char *memory, size_t size,
|
||||
const char **err) {
|
||||
int LoadEXRFromMemory(float **out_rgba, int *width, int *height,
|
||||
const unsigned char *memory, size_t size,
|
||||
const char **err) {
|
||||
if (out_rgba == NULL || memory == NULL) {
|
||||
if (err) {
|
||||
(*err) = "Invalid argument.\n";
|
||||
|
@ -10748,6 +10866,13 @@ int LoadEXRFromMemory(float *out_rgba, const unsigned char *memory, size_t size,
|
|||
if (ret != TINYEXR_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Read HALF channel as FLOAT.
|
||||
for (int i = 0; i < exr_header.num_channels; i++) {
|
||||
if (exr_header.pixel_types[i] == TINYEXR_PIXELTYPE_HALF) {
|
||||
exr_header.requested_pixel_types[i] = TINYEXR_PIXELTYPE_FLOAT;
|
||||
}
|
||||
}
|
||||
|
||||
InitEXRImage(&exr_image);
|
||||
ret = LoadEXRImageFromMemory(&exr_image, &exr_header, memory, size, err);
|
||||
|
@ -10797,19 +10922,32 @@ int LoadEXRFromMemory(float *out_rgba, const unsigned char *memory, size_t size,
|
|||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
// Assume `out_rgba` have enough memory allocated.
|
||||
(*out_rgba) = reinterpret_cast<float *>(
|
||||
malloc(4 * sizeof(float) * static_cast<size_t>(exr_image.width) *
|
||||
static_cast<size_t>(exr_image.height)));
|
||||
|
||||
for (int i = 0; i < exr_image.width * exr_image.height; i++) {
|
||||
out_rgba[4 * i + 0] = reinterpret_cast<float **>(exr_image.images)[idxR][i];
|
||||
out_rgba[4 * i + 1] = reinterpret_cast<float **>(exr_image.images)[idxG][i];
|
||||
out_rgba[4 * i + 2] = reinterpret_cast<float **>(exr_image.images)[idxB][i];
|
||||
if (idxA > 0) {
|
||||
out_rgba[4 * i + 3] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxA][i];
|
||||
} else {
|
||||
out_rgba[4 * i + 3] = 1.0;
|
||||
}
|
||||
(*out_rgba)[4 * i + 0] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxR][i];
|
||||
(*out_rgba)[4 * i + 1] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxG][i];
|
||||
(*out_rgba)[4 * i + 2] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxB][i];
|
||||
if (idxA != -1) {
|
||||
(*out_rgba)[4 * i + 3] =
|
||||
reinterpret_cast<float **>(exr_image.images)[idxA][i];
|
||||
}
|
||||
else {
|
||||
(*out_rgba)[4 * i + 3] = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
(*width) = exr_image.width;
|
||||
(*height) = exr_image.height;
|
||||
|
||||
FreeEXRHeader(&exr_header);
|
||||
FreeEXRImage(&exr_image);
|
||||
|
||||
return TINYEXR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -11304,7 +11442,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image,
|
|||
std::vector<unsigned char> block(bufLen);
|
||||
unsigned int outSize = static_cast<unsigned int>(block.size());
|
||||
|
||||
CompressPiz(&block.at(0), outSize,
|
||||
CompressPiz(&block.at(0), &outSize,
|
||||
reinterpret_cast<const unsigned char *>(&buf.at(0)),
|
||||
buf.size(), channels, exr_image->width, h);
|
||||
|
||||
|
@ -11445,6 +11583,16 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
return TINYEXR_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
FILE *fp = NULL;
|
||||
errno_t errcode = fopen_s(&fp, filename, "rb");
|
||||
if ((!errcode) || (!fp)) {
|
||||
if (err) {
|
||||
(*err) = "Cannot read file.";
|
||||
}
|
||||
return TINYEXR_ERROR_CANT_OPEN_FILE;
|
||||
}
|
||||
#else
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
if (err) {
|
||||
|
@ -11452,6 +11600,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
}
|
||||
return TINYEXR_ERROR_CANT_OPEN_FILE;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t filesize;
|
||||
// Compute size
|
||||
|
@ -11521,6 +11670,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
if (0 == size) {
|
||||
return TINYEXR_ERROR_INVALID_DATA;
|
||||
} else if (marker[0] == '\0') {
|
||||
marker++;
|
||||
size--;
|
||||
break;
|
||||
}
|
||||
|
@ -11710,11 +11860,13 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
// decode sample data.
|
||||
{
|
||||
unsigned long dstLen = static_cast<unsigned long>(unpackedSampleDataSize);
|
||||
tinyexr::DecompressZip(
|
||||
reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
|
||||
data_ptr + 28 + packedOffsetTableSize,
|
||||
static_cast<unsigned long>(packedSampleDataSize));
|
||||
assert(dstLen == static_cast<unsigned long>(unpackedSampleDataSize));
|
||||
if (dstLen) {
|
||||
tinyexr::DecompressZip(
|
||||
reinterpret_cast<unsigned char *>(&sample_data.at(0)), &dstLen,
|
||||
data_ptr + 28 + packedOffsetTableSize,
|
||||
static_cast<unsigned long>(packedSampleDataSize));
|
||||
assert(dstLen == static_cast<unsigned long>(unpackedSampleDataSize));
|
||||
}
|
||||
}
|
||||
|
||||
// decode sample
|
||||
|
@ -11760,7 +11912,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
if (channels[c].pixel_type == 0) { // UINT
|
||||
for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
|
||||
unsigned int ui = *reinterpret_cast<unsigned int *>(
|
||||
&sample_data.at(data_offset + x * sizeof(int)));
|
||||
&sample_data.at(size_t(data_offset) + x * sizeof(int)));
|
||||
deep_image->image[c][y][x] = static_cast<float>(ui); // @fixme
|
||||
}
|
||||
data_offset +=
|
||||
|
@ -11769,7 +11921,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
|
||||
tinyexr::FP16 f16;
|
||||
f16.u = *reinterpret_cast<unsigned short *>(
|
||||
&sample_data.at(data_offset + x * sizeof(short)));
|
||||
&sample_data.at(size_t(data_offset) + x * sizeof(short)));
|
||||
tinyexr::FP32 f32 = half_to_float(f16);
|
||||
deep_image->image[c][y][x] = f32.f;
|
||||
}
|
||||
|
@ -11777,7 +11929,7 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) {
|
|||
} else { // float
|
||||
for (size_t x = 0; x < static_cast<size_t>(samples_per_line); x++) {
|
||||
float f = *reinterpret_cast<float *>(
|
||||
&sample_data.at(data_offset + x * sizeof(float)));
|
||||
&sample_data.at(size_t(data_offset) + x * sizeof(float)));
|
||||
deep_image->image[c][y][x] = f;
|
||||
}
|
||||
data_offset += sizeof(float) * static_cast<size_t>(samples_per_line);
|
||||
|
@ -11961,7 +12113,11 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers,
|
|||
|
||||
if (ret != TINYEXR_SUCCESS) {
|
||||
if (err) {
|
||||
#ifdef _WIN32
|
||||
(*err) = _strdup(err_str.c_str()); // may leak
|
||||
#else
|
||||
(*err) = strdup(err_str.c_str()); // may leak
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -12287,8 +12443,8 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images,
|
|||
}
|
||||
|
||||
int SaveEXR(const float *data, int width, int height, int components,
|
||||
const char *outfilename) {
|
||||
if (components == 3 || components == 4) {
|
||||
const int save_as_fp16, const char *outfilename) {
|
||||
if ((components == 1) || components == 3 || components == 4) {
|
||||
// OK
|
||||
} else {
|
||||
return TINYEXR_ERROR_INVALID_ARGUMENT;
|
||||
|
@ -12307,18 +12463,24 @@ int SaveEXR(const float *data, int width, int height, int components,
|
|||
image.num_channels = components;
|
||||
|
||||
std::vector<float> images[4];
|
||||
images[0].resize(static_cast<size_t>(width * height));
|
||||
images[1].resize(static_cast<size_t>(width * height));
|
||||
images[2].resize(static_cast<size_t>(width * height));
|
||||
images[3].resize(static_cast<size_t>(width * height));
|
||||
|
||||
// Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers
|
||||
for (size_t i = 0; i < static_cast<size_t>(width * height); i++) {
|
||||
images[0][i] = data[static_cast<size_t>(components) * i + 0];
|
||||
images[1][i] = data[static_cast<size_t>(components) * i + 1];
|
||||
images[2][i] = data[static_cast<size_t>(components) * i + 2];
|
||||
if (components == 4) {
|
||||
images[3][i] = data[static_cast<size_t>(components) * i + 3];
|
||||
if (components == 1) {
|
||||
images[0].resize(static_cast<size_t>(width * height));
|
||||
memcpy(images[0].data(), data, sizeof(float) * size_t(width * height));
|
||||
} else {
|
||||
images[0].resize(static_cast<size_t>(width * height));
|
||||
images[1].resize(static_cast<size_t>(width * height));
|
||||
images[2].resize(static_cast<size_t>(width * height));
|
||||
images[3].resize(static_cast<size_t>(width * height));
|
||||
|
||||
// Split RGB(A)RGB(A)RGB(A)... into R, G and B(and A) layers
|
||||
for (size_t i = 0; i < static_cast<size_t>(width * height); i++) {
|
||||
images[0][i] = data[static_cast<size_t>(components) * i + 0];
|
||||
images[1][i] = data[static_cast<size_t>(components) * i + 1];
|
||||
images[2][i] = data[static_cast<size_t>(components) * i + 2];
|
||||
if (components == 4) {
|
||||
images[3][i] = data[static_cast<size_t>(components) * i + 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12328,10 +12490,12 @@ int SaveEXR(const float *data, int width, int height, int components,
|
|||
image_ptr[1] = &(images[2].at(0)); // B
|
||||
image_ptr[2] = &(images[1].at(0)); // G
|
||||
image_ptr[3] = &(images[0].at(0)); // R
|
||||
} else {
|
||||
} else if (components == 3) {
|
||||
image_ptr[0] = &(images[2].at(0)); // B
|
||||
image_ptr[1] = &(images[1].at(0)); // G
|
||||
image_ptr[2] = &(images[0].at(0)); // R
|
||||
} else if (components == 1) {
|
||||
image_ptr[0] = &(images[0].at(0)); // A
|
||||
}
|
||||
|
||||
image.images = reinterpret_cast<unsigned char **>(image_ptr);
|
||||
|
@ -12343,21 +12507,41 @@ int SaveEXR(const float *data, int width, int height, int components,
|
|||
sizeof(EXRChannelInfo) * static_cast<size_t>(header.num_channels)));
|
||||
// Must be (A)BGR order, since most of EXR viewers expect this channel order.
|
||||
if (components == 4) {
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(header.channels[0].name, "A", 255);
|
||||
strncpy_s(header.channels[1].name, "B", 255);
|
||||
strncpy_s(header.channels[2].name, "G", 255);
|
||||
strncpy_s(header.channels[3].name, "R", 255);
|
||||
#else
|
||||
strncpy(header.channels[0].name, "A", 255);
|
||||
header.channels[0].name[strlen("A")] = '\0';
|
||||
strncpy(header.channels[1].name, "B", 255);
|
||||
header.channels[1].name[strlen("B")] = '\0';
|
||||
strncpy(header.channels[2].name, "G", 255);
|
||||
header.channels[2].name[strlen("G")] = '\0';
|
||||
strncpy(header.channels[3].name, "R", 255);
|
||||
#endif
|
||||
header.channels[0].name[strlen("A")] = '\0';
|
||||
header.channels[1].name[strlen("B")] = '\0';
|
||||
header.channels[2].name[strlen("G")] = '\0';
|
||||
header.channels[3].name[strlen("R")] = '\0';
|
||||
} else {
|
||||
} else if (components == 3) {
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(header.channels[0].name, "B", 255);
|
||||
strncpy_s(header.channels[1].name, "G", 255);
|
||||
strncpy_s(header.channels[2].name, "R", 255);
|
||||
#else
|
||||
strncpy(header.channels[0].name, "B", 255);
|
||||
header.channels[0].name[strlen("B")] = '\0';
|
||||
strncpy(header.channels[1].name, "G", 255);
|
||||
header.channels[1].name[strlen("G")] = '\0';
|
||||
strncpy(header.channels[2].name, "R", 255);
|
||||
#endif
|
||||
header.channels[0].name[strlen("B")] = '\0';
|
||||
header.channels[1].name[strlen("G")] = '\0';
|
||||
header.channels[2].name[strlen("R")] = '\0';
|
||||
} else {
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(header.channels[0].name, "A", 255);
|
||||
#else
|
||||
strncpy(header.channels[0].name, "A", 255);
|
||||
#endif
|
||||
header.channels[0].name[strlen("A")] = '\0';
|
||||
}
|
||||
|
||||
header.pixel_types = static_cast<int *>(
|
||||
|
@ -12367,9 +12551,15 @@ int SaveEXR(const float *data, int width, int height, int components,
|
|||
for (int i = 0; i < header.num_channels; i++) {
|
||||
header.pixel_types[i] =
|
||||
TINYEXR_PIXELTYPE_FLOAT; // pixel type of input image
|
||||
header.requested_pixel_types[i] =
|
||||
TINYEXR_PIXELTYPE_HALF; // pixel type of output image to be stored in
|
||||
// .EXR
|
||||
|
||||
if (save_as_fp16 > 0) {
|
||||
header.requested_pixel_types[i] =
|
||||
TINYEXR_PIXELTYPE_HALF; // save with half(fp16) pixel format
|
||||
} else {
|
||||
header.requested_pixel_types[i] =
|
||||
TINYEXR_PIXELTYPE_FLOAT; // save with float(fp32) pixel format(i.e.
|
||||
// no precision reduction)
|
||||
}
|
||||
}
|
||||
|
||||
const char *err;
|
||||
|
@ -12385,9 +12575,5 @@ int SaveEXR(const float *data, int width, int height, int components,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // TINYEXR_IMPLEMENTATION_DEIFNED
|
||||
#endif // TINYEXR_IMPLEMENTATION
|
||||
|
|
Loading…
Reference in New Issue