diff --git a/BUILD.bazel b/BUILD.bazel index 1f4e0280d..2c193fbe5 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -203,6 +203,7 @@ cc_library( "src/lib/OpenEXRCore/internal_ht_common.h", "src/lib/OpenEXRCore/internal_huf.c", "src/lib/OpenEXRCore/internal_huf.h", + "src/lib/OpenEXRCore/internal_legacy_structs.h", "src/lib/OpenEXRCore/internal_memory.h", "src/lib/OpenEXRCore/internal_opaque.h", "src/lib/OpenEXRCore/internal_piz.c", diff --git a/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp b/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp index 5c3ae0532..dc3fff2ff 100644 --- a/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp +++ b/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp @@ -84,7 +84,7 @@ struct ScanLineProcess bool first = true; bool counts_only = false; exr_chunk_info_t cinfo; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; ScanLineProcess* next; }; diff --git a/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp b/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp index dca48426d..26c3f7bc4 100644 --- a/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp +++ b/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp @@ -69,7 +69,7 @@ struct TileProcess bool first = true; bool counts_only = false; exr_chunk_info_t cinfo; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; TileProcess* next; }; diff --git a/src/lib/OpenEXR/ImfScanLineInputFile.cpp b/src/lib/OpenEXR/ImfScanLineInputFile.cpp index d09f76b3a..179659e05 100644 --- a/src/lib/OpenEXR/ImfScanLineInputFile.cpp +++ b/src/lib/OpenEXR/ImfScanLineInputFile.cpp @@ -65,7 +65,7 @@ struct ScanLineProcess exr_result_t last_decode_err = EXR_ERR_UNKNOWN; bool first = true; exr_chunk_info_t cinfo; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; // requirement to use process group ScanLineProcess* next; diff --git a/src/lib/OpenEXR/ImfTiledInputFile.cpp b/src/lib/OpenEXR/ImfTiledInputFile.cpp index 7bf4c5ebe..f21563ec5 100644 --- a/src/lib/OpenEXR/ImfTiledInputFile.cpp +++ b/src/lib/OpenEXR/ImfTiledInputFile.cpp @@ -60,7 +60,7 @@ struct TileProcess bool first = true; exr_chunk_info_t cinfo; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; TileProcess* next; }; diff --git a/src/lib/OpenEXRCore/compression.c b/src/lib/OpenEXRCore/compression.c index d64d071e8..02738a2ef 100644 --- a/src/lib/OpenEXRCore/compression.c +++ b/src/lib/OpenEXRCore/compression.c @@ -13,6 +13,7 @@ #include "internal_coding.h" #include "internal_file.h" #include "internal_huf.h" +#include "internal_legacy_structs.h" #include "OpenEXRConfigInternal.h" @@ -141,18 +142,9 @@ exr_compress_buffer ( /**************************************/ -exr_result_t -exr_uncompress_buffer ( - exr_const_context_t ctxt, - const void* in, - size_t in_bytes, - void* out, - size_t out_bytes_avail, - size_t* actual_out) +static struct libdeflate_decompressor* +create_deflate_context (exr_const_context_t ctxt) { - struct libdeflate_decompressor* decomp; - enum libdeflate_result res; - size_t actual_in_bytes; #ifdef EXR_USE_CONFIG_DEFLATE_STRUCT struct libdeflate_options opt = { .sizeof_options = sizeof (struct libdeflate_options), @@ -160,23 +152,105 @@ exr_uncompress_buffer ( .free_func = ctxt ? ctxt->free_fn : internal_exr_free}; #endif -// if (in_bytes == out_bytes_avail) -// { -// if (actual_out) *actual_out = in_bytes; -// if (in != out) -// memcpy(out, in, in_bytes); -// -// return EXR_ERR_SUCCESS; -// } - #ifdef EXR_USE_CONFIG_DEFLATE_STRUCT - decomp = libdeflate_alloc_decompressor_ex (&opt); + return libdeflate_alloc_decompressor_ex (&opt); #else libdeflate_set_memory_allocator ( ctxt ? ctxt->alloc_fn : internal_exr_alloc, ctxt ? ctxt->free_fn : internal_exr_free); - decomp = libdeflate_alloc_decompressor (); + return libdeflate_alloc_decompressor (); #endif +} + +static inline exr_result_t +translate_deflate_result ( + enum libdeflate_result res, + size_t actual_in_bytes, + size_t in_bytes) +{ + if (res == LIBDEFLATE_SUCCESS) + { + if (in_bytes == actual_in_bytes) return EXR_ERR_SUCCESS; + /* it's an error to not consume the full buffer, right? */ + } + else if (res == LIBDEFLATE_INSUFFICIENT_SPACE) + { + return EXR_ERR_OUT_OF_MEMORY; + } + else if (res == LIBDEFLATE_SHORT_OUTPUT) + { + /* Decompression succeeded; *actual_out is the byte count. This is + * not an error when out_bytes_avail exceeds the true uncompressed + * size (e.g. PXR24/ZIP use padded scratch buffers). Callers that + * need an exact payload size must compare *actual_out (see e.g. + * undo_pxr24_impl). */ + return EXR_ERR_SUCCESS; + } + return EXR_ERR_CORRUPT_CHUNK; +} + +/**************************************/ + +static void internal_free_zip_context (exr_decode_pipeline_t* decode) +{ + struct libdeflate_decompressor* decomp = decode->compression_context; + if (decomp) + libdeflate_free_decompressor (decomp); +} + +exr_result_t internal_exr_decode_uncompress_buffer ( + exr_decode_pipeline_t* decode, + const void* in, + size_t in_bytes, + void* out, + size_t out_bytes_avail, + size_t* actual_out) +{ + if (decode->pipe_size >= sizeof (exr_decode_pipeline_v2_t)) + { + struct libdeflate_decompressor* decomp; + enum libdeflate_result res; + size_t actual_in_bytes; + + /* we can cache the context... */ + if (decode->compression_context == NULL) + { + decode->compression_context = create_deflate_context (decode->context); + decode->free_compression_context = &internal_free_zip_context; + } + decomp = decode->compression_context; + + res = libdeflate_zlib_decompress_ex ( + decomp, + in, + in_bytes, + out, + out_bytes_avail, + &actual_in_bytes, + actual_out); + + return translate_deflate_result (res, actual_in_bytes, in_bytes); + } + return exr_uncompress_buffer (decode->context, in, in_bytes, + out, out_bytes_avail, actual_out); +} + +/**************************************/ + +exr_result_t +exr_uncompress_buffer ( + exr_const_context_t ctxt, + const void* in, + size_t in_bytes, + void* out, + size_t out_bytes_avail, + size_t* actual_out) +{ + struct libdeflate_decompressor* decomp; + enum libdeflate_result res; + size_t actual_in_bytes; + + decomp = create_deflate_context (ctxt); if (decomp) { res = libdeflate_zlib_decompress_ex ( @@ -190,25 +264,7 @@ exr_uncompress_buffer ( libdeflate_free_decompressor (decomp); - if (res == LIBDEFLATE_SUCCESS) - { - if (in_bytes == actual_in_bytes) return EXR_ERR_SUCCESS; - /* it's an error to not consume the full buffer, right? */ - } - else if (res == LIBDEFLATE_INSUFFICIENT_SPACE) - { - return EXR_ERR_OUT_OF_MEMORY; - } - else if (res == LIBDEFLATE_SHORT_OUTPUT) - { - /* Decompression succeeded; *actual_out is the byte count. This is - * not an error when out_bytes_avail exceeds the true uncompressed - * size (e.g. PXR24/ZIP use padded scratch buffers). Callers that - * need an exact payload size must compare *actual_out (see e.g. - * undo_pxr24_impl). */ - return EXR_ERR_SUCCESS; - } - return EXR_ERR_CORRUPT_CHUNK; + return translate_deflate_result (res, actual_in_bytes, in_bytes); } return EXR_ERR_OUT_OF_MEMORY; } diff --git a/src/lib/OpenEXRCore/decoding.c b/src/lib/OpenEXRCore/decoding.c index 0ca2a9980..fd0b1fcde 100644 --- a/src/lib/OpenEXRCore/decoding.c +++ b/src/lib/OpenEXRCore/decoding.c @@ -11,6 +11,8 @@ #include "internal_decompress.h" #include "internal_structs.h" #include "internal_xdr.h" +#include "internal_xdr.h" +#include "internal_legacy_structs.h" #include #include @@ -284,8 +286,8 @@ exr_decoding_initialize ( const exr_chunk_info_t* cinfo, exr_decode_pipeline_t* decode) { + size_t pipe_ver; exr_result_t rv; - exr_decode_pipeline_t nil = {0}; exr_const_priv_part_t part; if (!ctxt) return EXR_ERR_MISSING_CONTEXT_ARG; @@ -296,9 +298,23 @@ exr_decoding_initialize ( if (part_index < 0 || part_index >= ctxt->num_parts) return EXR_ERR_ARGUMENT_OUT_OF_RANGE; - part = ctxt->parts[part_index]; + if (decode->pipe_size != sizeof (exr_decode_pipeline_v2_t)) + { + /* There was no check for the pipe_size during the v1 struct + * versions of the library. If we add more versions of the + * struct later, update this condition to check for the new + * versions but just let the old assumption that the + * size is correct keep running + */ + decode->pipe_size = sizeof (exr_decode_pipeline_v1_t); + } + + pipe_ver = decode->pipe_size; + part = ctxt->parts[part_index]; - *decode = nil; + // ensure everything is 0 / null... + memset (decode, 0, pipe_ver); + decode->pipe_size = pipe_ver; if (part->storage_mode == EXR_STORAGE_DEEP_SCANLINE || part->storage_mode == EXR_STORAGE_DEEP_TILED) @@ -675,11 +691,12 @@ exr_decoding_run ( exr_result_t exr_decoding_destroy (exr_const_context_t ctxt, exr_decode_pipeline_t* decode) { + size_t pipe_ver; + if (!ctxt) return EXR_ERR_MISSING_CONTEXT_ARG; if (decode) { - exr_decode_pipeline_t nil = {0}; if (decode->channels != decode->_quick_chan_store) ctxt->free_fn (decode->channels); @@ -722,7 +739,21 @@ exr_decoding_destroy (exr_const_context_t ctxt, exr_decode_pipeline_t* decode) EXR_TRANSCODE_BUFFER_PACKED_SAMPLES, &(decode->packed_sample_count_table), &(decode->packed_sample_count_alloc_size)); - *decode = nil; + + if (decode->pipe_size > sizeof (exr_decode_pipeline_v1_t)) + { + /* safe to check the compression context member and free routine */ + if (decode->compression_context && decode->free_compression_context) + { + decode->free_compression_context (decode); + } + } + + /* zilch out everything except the version field */ + pipe_ver = decode->pipe_size; + + memset (decode, 0, pipe_ver); + decode->pipe_size = pipe_ver; } return EXR_ERR_SUCCESS; } diff --git a/src/lib/OpenEXRCore/internal_decompress.h b/src/lib/OpenEXRCore/internal_decompress.h index 6251c2d9c..706fab25d 100644 --- a/src/lib/OpenEXRCore/internal_decompress.h +++ b/src/lib/OpenEXRCore/internal_decompress.h @@ -24,6 +24,18 @@ exr_result_t internal_exr_undo_rle ( void* uncompressed_data, uint64_t uncompressed_size); +/* + * rather than just straight using uncompress buffer + * uses a cached zip context in the decode struct... + */ +exr_result_t internal_exr_decode_uncompress_buffer ( + exr_decode_pipeline_t* decode, + const void* in, + size_t in_bytes, + void* out, + size_t out_bytes_avail, + size_t* actual_out); + exr_result_t internal_exr_undo_zip ( exr_decode_pipeline_t* decode, const void* compressed_data, diff --git a/src/lib/OpenEXRCore/internal_ht.cpp b/src/lib/OpenEXRCore/internal_ht.cpp index c4b2ce504..9da59a944 100644 --- a/src/lib/OpenEXRCore/internal_ht.cpp +++ b/src/lib/OpenEXRCore/internal_ht.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ #include "openexr_decode.h" #include "openexr_encode.h" #include "internal_ht_common.h" +#include "internal_legacy_structs.h" /** * OpenJPH output file that is backed by a fixed-size memory buffer @@ -157,6 +159,20 @@ class staticmem_outfile : public ojph::outfile_base ojph::ui8 *cur_ptr; }; +struct ht_context_cache +{ + std::vector cs_to_file_ch; + ojph::codestream cs; +}; + +static void destroy_ht_decompress_context (exr_decode_pipeline_t* decode) +{ + ht_context_cache* ctxt = static_cast (decode->compression_context); + delete ctxt; + decode->compression_context = NULL; + decode->free_compression_context = NULL; +} + static exr_result_t ht_undo_impl ( exr_decode_pipeline_t* decode, @@ -167,10 +183,29 @@ ht_undo_impl ( { exr_result_t rv = EXR_ERR_SUCCESS; - std::vector cs_to_file_ch (decode->channel_count); + std::unique_ptr legacy_support; - /* read the channel map */ + ht_context_cache* ctxt; + if (decode->pipe_size >= sizeof (exr_decode_pipeline_v2_t)) + { + ctxt = static_cast (decode->compression_context); + if ( ! ctxt ) + { + ctxt = new ht_context_cache; + decode->compression_context = ctxt; + decode->free_compression_context = &destroy_ht_decompress_context; + } + } + else + { + legacy_support = std::make_unique(); + ctxt = legacy_support.get(); + } + + std::vector &cs_to_file_ch = ctxt->cs_to_file_ch; + cs_to_file_ch.resize(decode->channel_count); + /* read the channel map */ size_t header_sz; try { @@ -214,7 +249,8 @@ ht_undo_impl ( reinterpret_cast (compressed_data) + header_sz, codestream_sz); - ojph::codestream cs; + ojph::codestream &cs = ctxt->cs; + cs.restart (); cs.read_headers (&infile); ojph::param_siz siz = cs.access_siz (); diff --git a/src/lib/OpenEXRCore/internal_legacy_structs.h b/src/lib/OpenEXRCore/internal_legacy_structs.h new file mode 100644 index 000000000..6e827dac3 --- /dev/null +++ b/src/lib/OpenEXRCore/internal_legacy_structs.h @@ -0,0 +1,60 @@ +/* +** SPDX-License-Identifier: BSD-3-Clause +** Copyright Contributors to the OpenEXR Project. +*/ + +#ifndef OPENEXR_CORE_LEGACY_STRUCTS_H +#define OPENEXR_CORE_LEGACY_STRUCTS_H + +#include "openexr_decode.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _exr_decode_pipeline_v1 +{ + size_t pipe_size; + + exr_coding_channel_info_t* channels; + int16_t channel_count; + uint16_t decode_flags; + int part_index; + exr_const_context_t context; + exr_chunk_info_t chunk; + int32_t user_line_begin_skip; + int32_t user_line_end_ignore; + uint64_t bytes_decompressed; + void* decoding_user_data; + void* packed_buffer; + size_t packed_alloc_size; + void* unpacked_buffer; + size_t unpacked_alloc_size; + void* packed_sample_count_table; + size_t packed_sample_count_alloc_size; + int32_t* sample_count_table; + size_t sample_count_alloc_size; + void* scratch_buffer_1; + size_t scratch_alloc_size_1; + void* scratch_buffer_2; + size_t scratch_alloc_size_2; + + void* (*alloc_fn) (exr_transcoding_pipeline_buffer_id_t, size_t); + void (*free_fn) (exr_transcoding_pipeline_buffer_id_t, void*); + exr_result_t (*read_fn) (struct _exr_decode_pipeline* pipeline); + exr_result_t (*decompress_fn) (struct _exr_decode_pipeline* pipeline); + exr_result_t (*realloc_nonimage_data_fn) ( + struct _exr_decode_pipeline* pipeline); + exr_result_t (*unpack_and_convert_fn) ( + struct _exr_decode_pipeline* pipeline); + exr_coding_channel_info_t _quick_chan_store[5]; +} exr_decode_pipeline_v1_t; + +/* change this if we add additional members in the future */ +typedef struct _exr_decode_pipeline exr_decode_pipeline_v2_t; + +#ifdef __cplusplus +} +#endif + +#endif /* OPENEXR_CORE_DECOMPRESS_H */ diff --git a/src/lib/OpenEXRCore/internal_zip.c b/src/lib/OpenEXRCore/internal_zip.c index f7aa6433f..b5a2a621d 100644 --- a/src/lib/OpenEXRCore/internal_zip.c +++ b/src/lib/OpenEXRCore/internal_zip.c @@ -302,8 +302,8 @@ undo_zip_impl ( if (scratch_size < uncompressed_size) return EXR_ERR_INVALID_ARGUMENT; - res = exr_uncompress_buffer ( - decode->context, + res = internal_exr_decode_uncompress_buffer ( + decode, compressed_data, comp_buf_size, scratch_data, diff --git a/src/lib/OpenEXRCore/openexr_decode.h b/src/lib/OpenEXRCore/openexr_decode.h index ba53c7956..e9b9742ae 100644 --- a/src/lib/OpenEXRCore/openexr_decode.h +++ b/src/lib/OpenEXRCore/openexr_decode.h @@ -63,7 +63,7 @@ extern "C" { */ typedef struct _exr_decode_pipeline { - /** Used for versioning the decode pipeline in the future. + /** Used for detecting the version of the decode pipeline. * * \ref EXR_DECODE_PIPELINE_INITIALIZER */ @@ -264,6 +264,28 @@ typedef struct _exr_decode_pipeline * this being used. */ exr_coding_channel_info_t _quick_chan_store[5]; + + /** Some compression methods (using external libraries) require additional + * contexts to be constructed. Rather than re-initialize those every chunk, + * allow the context to be re-used across chunks. + * + * NB: Do not store thread-specific data or contexts which use + * thread-specific data using this mechanism, as the decode pipeline is + * free to be used by multiple threads from invocation to invocation + * (just not concurrently). + * + * If the context is not NULL upon destruction, or if somehow the + * compression changes during an update, the \ref free_compression_context + * function will be invoked. If that free routine is not provided, + * memory may leak. + */ + void* compression_context; + + /** Cleanup routine for the \ref compression_context member. + * If a compression context is set, but this routine is NULL, + * no attempt to free will be made, so your program might leak. + */ + void (*free_compression_context) (struct _exr_decode_pipeline* pipeline); } exr_decode_pipeline_t; /** @brief Simple macro to initialize an empty decode pipeline. */ diff --git a/src/test/OpenEXRCoreTest/compression.cpp b/src/test/OpenEXRCoreTest/compression.cpp index 427433234..e1879f748 100644 --- a/src/test/OpenEXRCoreTest/compression.cpp +++ b/src/test/OpenEXRCoreTest/compression.cpp @@ -909,7 +909,7 @@ static void doDecodeScan (exr_context_t f, pixels& p, int xs, int ys) { exr_chunk_info_t cinfo; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; int32_t scansperchunk; exr_attr_box2i_t dw; bool first = true; @@ -990,7 +990,7 @@ doDecodeTile (exr_context_t f, pixels& p, int xs, int ys) int y, endy; int x, endx; exr_chunk_info_t cinfo; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; bool first = true; EXRCORE_TEST (xs == 1 && ys == 1); diff --git a/src/test/OpenEXRCoreTest/performance.cpp b/src/test/OpenEXRCoreTest/performance.cpp index 200d61bfa..6854a8e2b 100644 --- a/src/test/OpenEXRCoreTest/performance.cpp +++ b/src/test/OpenEXRCoreTest/performance.cpp @@ -45,7 +45,7 @@ class CoreReadTask : public Task void execute () override { exr_chunk_info_t cinfo = {0}; - exr_decode_pipeline_t chunk; + exr_decode_pipeline_t chunk = EXR_DECODE_PIPELINE_INITIALIZER; exr_result_t rv = exr_read_scanline_chunk_info (_f, 0, _y, &cinfo); if (rv == EXR_ERR_SUCCESS) rv = exr_decoding_initialize (_f, 0, &cinfo, &chunk); @@ -144,7 +144,7 @@ read_pixels_raw (exr_context_t f) } #else exr_chunk_info_t cinfo = {0}; - exr_decode_pipeline_t chunk = {0}; + exr_decode_pipeline_t chunk = EXR_DECODE_PIPELINE_INITIALIZER; for (int y = dw.min.y; y <= dw.max.y;) { exr_result_t rv = exr_read_scanline_chunk_info (f, 0, y, &cinfo); diff --git a/src/test/OpenEXRCoreTest/read.cpp b/src/test/OpenEXRCoreTest/read.cpp index 2451f55f4..3834835f5 100644 --- a/src/test/OpenEXRCoreTest/read.cpp +++ b/src/test/OpenEXRCoreTest/read.cpp @@ -324,7 +324,7 @@ testReadScans (const std::string& tempdir) EXRCORE_TEST (cinfo.sample_count_data_offset == 0); EXRCORE_TEST (cinfo.sample_count_table_size == 0); - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; EXRCORE_TEST_RVAL (exr_decoding_initialize (f, 0, &cinfo, &decoder)); EXRCORE_TEST (decoder.channel_count == 2); @@ -513,7 +513,7 @@ testReadTiles (const std::string& tempdir) EXRCORE_TEST (cinfo.sample_count_data_offset == 0); EXRCORE_TEST (cinfo.sample_count_table_size == 0); - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; EXRCORE_TEST_RVAL (exr_decoding_initialize (f, 0, &cinfo, &decoder)); EXRCORE_TEST (decoder.channel_count == 2); @@ -586,7 +586,7 @@ testReadUnpack (const std::string& tempdir) EXRCORE_TEST_RVAL (exr_read_tile_chunk_info (f, 0, 4, 2, 0, 0, &cinfo)); { - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; EXRCORE_TEST_RVAL (exr_decoding_initialize (f, 0, &cinfo, &decoder)); std::unique_ptr gptr{new float[24 * 12]}; @@ -619,43 +619,6 @@ testReadUnpack (const std::string& tempdir) #include "../../lib/OpenEXRCore/internal_util.h" -static inline int -compute_sampled_height_p (int height, int y_sampling, int start_y) -{ - int nlines; - - if (y_sampling <= 1) return height; - - if (height == 1) - nlines = (start_y % y_sampling) == 0 ? 1 : 0; - else - { - int off, tmph; - - /* computed the number of times y % ysampling == 0, by - * computing interval based on first and last time that occurs - * on the given range - */ - if (start_y < 0) - { - off = -start_y % y_sampling; - } - else - { - off = start_y % y_sampling; - if (off != 0) - off = (y_sampling - off); - } - - tmph = height - off; - if (tmph == 0) return 0; - --tmph; - nlines = tmph / y_sampling + 1; - } - - return nlines; -} - static inline int hardway_height (int height, int y_sampling, int start_y) { int nlines = 0; @@ -674,29 +637,6 @@ static inline int hardway_height (int height, int y_sampling, int start_y) return nlines; } -static inline int hardway_height_p (int height, int y_sampling, int start_y) -{ - int nlines = 0; - int end = start_y + height; - int off = 0; - - if (y_sampling <= 1) return height; - - if (height == 1) - return (start_y % y_sampling) == 0 ? 1 : 0; - - for ( int y = start_y; y < end; ++y ) - { - if (y % y_sampling != 0) - { - if (nlines == 0) ++off; - continue; - } - ++nlines; - } - return nlines; -} - static void test_lpc( int samp, int h, int lpc ) { for ( int y = -100; y < 100; ++y ) @@ -714,8 +654,6 @@ static void test_lpc( int samp, int h, int lpc ) int hnl = hardway_height(th, samp, ty); if (nl != hnl) { - compute_sampled_height_p(th, samp, ty); - hardway_height_p(th, samp, ty); printf( "ty %d h %d (%d) samp %d lpc %d => nl %d hnl %d\n", ty, th, h, samp, lpc, nl, hnl ); EXRCORE_TEST(nl == hnl); diff --git a/src/test/oss-fuzz/openexr_htj2k_fuzzer.cc b/src/test/oss-fuzz/openexr_htj2k_fuzzer.cc index 3ac8f720c..0fc8f8c4d 100644 --- a/src/test/oss-fuzz/openexr_htj2k_fuzzer.cc +++ b/src/test/oss-fuzz/openexr_htj2k_fuzzer.cc @@ -140,7 +140,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { exr_chunk_info_t cinfo; if (exr_read_scanline_chunk_info(rf, part_idx, y, &cinfo) != EXR_ERR_SUCCESS) break; - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; if (exr_decoding_initialize(rf, part_idx, &cinfo, &decoder) != EXR_ERR_SUCCESS) break; std::vector> out_data(decoder.channel_count); diff --git a/src/test/oss-fuzz/openexr_roundtrip_fuzzer.cc b/src/test/oss-fuzz/openexr_roundtrip_fuzzer.cc index 989d9ad23..c45ddab6f 100644 --- a/src/test/oss-fuzz/openexr_roundtrip_fuzzer.cc +++ b/src/test/oss-fuzz/openexr_roundtrip_fuzzer.cc @@ -175,7 +175,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { for (int y = 0; y < h; y += lines) { exr_chunk_info_t cinfo; if (exr_read_scanline_chunk_info(rf, p, y + dw.min.y, &cinfo) == EXR_ERR_SUCCESS) { - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; if (exr_decoding_initialize(rf, p, &cinfo, &decoder) == EXR_ERR_SUCCESS) { std::vector> out_data(decoder.channel_count); for (int c = 0; c < decoder.channel_count; ++c) { @@ -198,7 +198,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { for (int x = 0; x < tx; ++x) { exr_chunk_info_t cinfo; if (exr_read_tile_chunk_info(rf, p, x, y, 0, 0, &cinfo) == EXR_ERR_SUCCESS) { - exr_decode_pipeline_t decoder; + exr_decode_pipeline_t decoder = EXR_DECODE_PIPELINE_INITIALIZER; if (exr_decoding_initialize(rf, p, &cinfo, &decoder) == EXR_ERR_SUCCESS) { std::vector> out_data(decoder.channel_count); for (int c = 0; c < decoder.channel_count; ++c) {