From 2ca0bb2df61a0b2763dfcebe63a47f80cf62f832 Mon Sep 17 00:00:00 2001 From: Brendan Bolles Date: Fri, 20 Sep 2024 07:07:00 -0700 Subject: [PATCH] Add freeBuffers() function to InputFile classes The idea here is to provide a way to get InputFile objects back to their initial state after pixels have been read, which involves the allocating of various memory buffers that usually aren't freed until the objects are destroyed. This can be useful if an application wants to keep an object around for additional reading, but doesn't want unnecessary memory overhead in the meantime. Also provided is a bufferSize() function that the application might use to determine if freeing the buffers is enough of a memory savings to be worth the trouble. Signed-off-by: Brendan Bolles --- src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp | 50 +++++++++++++- src/lib/OpenEXR/ImfDeepScanLineInputFile.h | 6 ++ src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp | 12 ++++ src/lib/OpenEXR/ImfDeepScanLineInputPart.h | 5 ++ src/lib/OpenEXR/ImfDeepTiledInputFile.cpp | 46 +++++++++++++ src/lib/OpenEXR/ImfDeepTiledInputFile.h | 6 ++ src/lib/OpenEXR/ImfDeepTiledInputPart.cpp | 12 ++++ src/lib/OpenEXR/ImfDeepTiledInputPart.h | 5 ++ src/lib/OpenEXR/ImfInputFile.cpp | 56 ++++++++++++++- src/lib/OpenEXR/ImfInputFile.h | 6 ++ src/lib/OpenEXR/ImfInputPart.cpp | 12 ++++ src/lib/OpenEXR/ImfInputPart.h | 6 ++ src/lib/OpenEXR/ImfScanLineInputFile.cpp | 50 +++++++++++++- src/lib/OpenEXR/ImfScanLineInputFile.h | 8 ++- src/lib/OpenEXR/ImfTiledInputFile.cpp | 49 +++++++++++++- src/lib/OpenEXR/ImfTiledInputFile.h | 48 +++++++------ src/lib/OpenEXR/ImfTiledInputPart.cpp | 12 ++++ src/lib/OpenEXR/ImfTiledInputPart.h | 4 ++ src/lib/OpenEXRCore/decoding.c | 71 ++++++++++++-------- src/lib/OpenEXRCore/openexr_decode.h | 15 +++++ 20 files changed, 424 insertions(+), 55 deletions(-) diff --git a/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp b/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp index 31ec5ad667..326f609bc9 100644 --- a/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp +++ b/src/lib/OpenEXR/ImfDeepScanLineInputFile.cpp @@ -80,6 +80,16 @@ struct ScanLineProcess const DeepFrameBuffer *outfb, int fbY); + size_t get_buffer_size () + { + return exr_decoding_get_buffer_size (&decoder); + } + + void free_buffers () + { + exr_decoding_free_buffers (&decoder); + } + exr_result_t last_decode_err = EXR_ERR_UNKNOWN; bool first = true; bool counts_only = false; @@ -458,6 +468,44 @@ DeepScanLineInputFile::lastScanLineInChunk (int y) const return _data->getChunkRange (y).second; } +//////////////////////////////////////// + +size_t +DeepScanLineInputFile::bufferSize () const +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + size_t retval = 0; + + std::shared_ptr sp = _data->processStack; + + while (sp) + { + retval += sp->get_buffer_size(); + + sp = sp->next; + } + + return retval; +} + +void +DeepScanLineInputFile::freeBuffers () +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + std::shared_ptr sp = _data->processStack; + + while (sp) + { + sp->free_buffers(); + + sp = sp->next; + } +} + std::pair DeepScanLineInputFile::Data::getChunkRange (int y) const { exr_attr_box2i_t dw = _ctxt->dataWindow (partNumber); @@ -612,8 +660,6 @@ DeepScanLineInputFile::Data::readData ( #endif } -//////////////////////////////////////// - void DeepScanLineInputFile::Data::readMemData ( const DeepFrameBuffer &fb, diff --git a/src/lib/OpenEXR/ImfDeepScanLineInputFile.h b/src/lib/OpenEXR/ImfDeepScanLineInputFile.h index 5bf690b89f..9fc255340c 100644 --- a/src/lib/OpenEXR/ImfDeepScanLineInputFile.h +++ b/src/lib/OpenEXR/ImfDeepScanLineInputFile.h @@ -233,6 +233,12 @@ class IMF_EXPORT_TYPE DeepScanLineInputFile int scanLine1, int scanLine2) const; + IMF_EXPORT + size_t bufferSize () const; + + IMF_EXPORT + void freeBuffers (); + private: Context _ctxt; struct IMF_HIDDEN Data; diff --git a/src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp b/src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp index da05db3653..70843889ab 100644 --- a/src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp +++ b/src/lib/OpenEXR/ImfDeepScanLineInputPart.cpp @@ -116,4 +116,16 @@ DeepScanLineInputPart::readPixelSampleCounts ( rawdata, frameBuffer, scanLine1, scanLine2); } +unsigned long long +DeepScanLineInputPart::bufferSize () const +{ + return file->bufferSize (); +} + +void +DeepScanLineInputPart::freeBuffers () +{ + file->freeBuffers (); +} + OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/src/lib/OpenEXR/ImfDeepScanLineInputPart.h b/src/lib/OpenEXR/ImfDeepScanLineInputPart.h index 3490fd2c60..d01758f167 100644 --- a/src/lib/OpenEXR/ImfDeepScanLineInputPart.h +++ b/src/lib/OpenEXR/ImfDeepScanLineInputPart.h @@ -145,6 +145,11 @@ class IMF_EXPORT_TYPE DeepScanLineInputPart int firstScanLineInChunk (int y) const; IMF_EXPORT int lastScanLineInChunk (int y) const; + + IMF_EXPORT + unsigned long long bufferSize () const; + IMF_EXPORT + void freeBuffers (); private: DeepScanLineInputFile* file; diff --git a/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp b/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp index 90de89ca75..79d769b109 100644 --- a/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp +++ b/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp @@ -65,6 +65,16 @@ struct TileProcess int fb_absX, int fb_absY, int t_absX, int t_absY); + size_t get_buffer_size () + { + return exr_decoding_get_buffer_size (&decoder); + } + + void free_buffers () + { + exr_decoding_free_buffers (&decoder); + } + exr_result_t last_decode_err = EXR_ERR_UNKNOWN; bool first = true; bool counts_only = false; @@ -914,6 +924,42 @@ DeepTiledInputFile::getTileOrder (int dx[], int dy[], int lx[], int ly[]) const } } +size_t +DeepTiledInputFile::bufferSize () const +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + size_t retval = 0; + + std::shared_ptr sp = _data->processStack; + + while (sp) + { + retval += sp->get_buffer_size(); + + sp = sp->next; + } + + return retval; +} + +void +DeepTiledInputFile::freeBuffers () +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + std::shared_ptr sp = _data->processStack; + + while (sp) + { + sp->free_buffers(); + + sp = sp->next; + } +} + void DeepTiledInputFile::Data::readTiles ( int dx1, int dx2, int dy1, int dy2, int lx, int ly, bool countsOnly) { diff --git a/src/lib/OpenEXR/ImfDeepTiledInputFile.h b/src/lib/OpenEXR/ImfDeepTiledInputFile.h index a3c3d88e4a..3a2aff7b98 100644 --- a/src/lib/OpenEXR/ImfDeepTiledInputFile.h +++ b/src/lib/OpenEXR/ImfDeepTiledInputFile.h @@ -377,6 +377,12 @@ class IMF_EXPORT_TYPE DeepTiledInputFile IMF_EXPORT void readPixelSampleCounts (int dx1, int dx2, int dy1, int dy2, int l = 0); + IMF_EXPORT + size_t bufferSize () const; + + IMF_EXPORT + void freeBuffers (); + private: Context _ctxt; struct IMF_HIDDEN Data; diff --git a/src/lib/OpenEXR/ImfDeepTiledInputPart.cpp b/src/lib/OpenEXR/ImfDeepTiledInputPart.cpp index f2b37ac637..72c263ce4d 100644 --- a/src/lib/OpenEXR/ImfDeepTiledInputPart.cpp +++ b/src/lib/OpenEXR/ImfDeepTiledInputPart.cpp @@ -207,4 +207,16 @@ DeepTiledInputPart::readPixelSampleCounts ( file->readPixelSampleCounts (dx1, dx2, dy1, dy2, l); } +unsigned long long +DeepTiledInputPart::bufferSize () const +{ + return file->bufferSize (); +} + +void +DeepTiledInputPart::freeBuffers () +{ + file->freeBuffers (); +} + OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/src/lib/OpenEXR/ImfDeepTiledInputPart.h b/src/lib/OpenEXR/ImfDeepTiledInputPart.h index 7106cfb5e8..31f616165a 100644 --- a/src/lib/OpenEXR/ImfDeepTiledInputPart.h +++ b/src/lib/OpenEXR/ImfDeepTiledInputPart.h @@ -334,6 +334,11 @@ class IMF_EXPORT_TYPE DeepTiledInputPart IMF_EXPORT void readPixelSampleCounts (int dx1, int dx2, int dy1, int dy2, int l = 0); + IMF_EXPORT + unsigned long long bufferSize () const; + IMF_EXPORT + void freeBuffers (); + private: DeepTiledInputFile* file; diff --git a/src/lib/OpenEXR/ImfInputFile.cpp b/src/lib/OpenEXR/ImfInputFile.cpp index 2f984bb4c2..858f192c66 100644 --- a/src/lib/OpenEXR/ImfInputFile.cpp +++ b/src/lib/OpenEXR/ImfInputFile.cpp @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- // -// class InputFile +// class InputFile // //----------------------------------------------------------------------------- @@ -271,6 +271,60 @@ InputFile::rawTileData ( } } +size_t +InputFile::bufferSize () const +{ + if (_data->_storage == EXR_STORAGE_DEEP_SCANLINE) + { + return _data->_dsFile->bufferSize (); + } + else if ( + _data->_storage == EXR_STORAGE_DEEP_TILED || + _data->_storage == EXR_STORAGE_TILED) + { + return _data->_tFile->bufferSize (); + } + else if (_data->_storage == EXR_STORAGE_SCANLINE) + { + return _data->_sFile->bufferSize (); + } + else + { + THROW ( + IEX_NAMESPACE::ArgExc, + "Unable to handle data storage type in file '" << fileName () + << "'"); + } +} + +void +InputFile::freeBuffers () +{ + _data->deleteCachedBuffer (); + + if (_data->_storage == EXR_STORAGE_DEEP_SCANLINE) + { + _data->_dsFile->freeBuffers (); + } + else if ( + _data->_storage == EXR_STORAGE_DEEP_TILED || + _data->_storage == EXR_STORAGE_TILED) + { + _data->_tFile->freeBuffers (); + } + else if (_data->_storage == EXR_STORAGE_SCANLINE) + { + _data->_sFile->freeBuffers (); + } + else + { + THROW ( + IEX_NAMESPACE::ArgExc, + "Unable to handle data storage type in file '" << fileName () + << "'"); + } +} + TiledInputFile& InputFile::asTiledInput (void) const { diff --git a/src/lib/OpenEXR/ImfInputFile.h b/src/lib/OpenEXR/ImfInputFile.h index 3e9da65c8d..6566b50c7a 100644 --- a/src/lib/OpenEXR/ImfInputFile.h +++ b/src/lib/OpenEXR/ImfInputFile.h @@ -245,6 +245,12 @@ class IMF_EXPORT_TYPE InputFile const char*& pixelData, int& pixelDataSize); + IMF_EXPORT + size_t bufferSize () const; + + IMF_EXPORT + void freeBuffers (); + private: IMF_HIDDEN void initialize (void); diff --git a/src/lib/OpenEXR/ImfInputPart.cpp b/src/lib/OpenEXR/ImfInputPart.cpp index acfd20db26..854113e884 100644 --- a/src/lib/OpenEXR/ImfInputPart.cpp +++ b/src/lib/OpenEXR/ImfInputPart.cpp @@ -96,4 +96,16 @@ InputPart::rawTileData ( file->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize); } +unsigned long long +InputPart::bufferSize () const +{ + return file->bufferSize (); +} + +void +InputPart::freeBuffers () +{ + file->freeBuffers (); +} + OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/src/lib/OpenEXR/ImfInputPart.h b/src/lib/OpenEXR/ImfInputPart.h index 440cc80bed..96fe332466 100644 --- a/src/lib/OpenEXR/ImfInputPart.h +++ b/src/lib/OpenEXR/ImfInputPart.h @@ -57,6 +57,12 @@ class IMF_EXPORT_TYPE InputPart const char*& pixelData, int& pixelDataSize); + IMF_EXPORT + unsigned long long bufferSize () const; + + IMF_EXPORT + void freeBuffers (); + private: InputFile* file; // for internal use - give OutputFile and TiledOutputFile access to file for copyPixels diff --git a/src/lib/OpenEXR/ImfScanLineInputFile.cpp b/src/lib/OpenEXR/ImfScanLineInputFile.cpp index f7eb144701..a22f743bac 100644 --- a/src/lib/OpenEXR/ImfScanLineInputFile.cpp +++ b/src/lib/OpenEXR/ImfScanLineInputFile.cpp @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- // -// class ScanLineInputFile +// class ScanLineInputFile // //----------------------------------------------------------------------------- @@ -61,6 +61,16 @@ struct ScanLineProcess const FrameBuffer *outfb, int fbY, const std::vector &filllist); + + size_t get_buffer_size () + { + return exr_decoding_get_buffer_size (&decoder); + } + + void free_buffers () + { + exr_decoding_free_buffers (&decoder); + } exr_result_t last_decode_err = EXR_ERR_UNKNOWN; bool first = true; @@ -408,6 +418,44 @@ ScanLineInputFile::rawPixelDataToBuffer ( //////////////////////////////////////// +size_t +ScanLineInputFile::bufferSize () const +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + size_t retval = 0; + + std::shared_ptr sp = _data->processStack; + + while (sp) + { + retval += sp->get_buffer_size(); + + sp = sp->next; + } + + return retval; +} + +void +ScanLineInputFile::freeBuffers () +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + std::shared_ptr sp = _data->processStack; + + while (sp) + { + sp->free_buffers(); + + sp = sp->next; + } +} + +//////////////////////////////////////// + void ScanLineInputFile::Data::readPixels ( const FrameBuffer &fb, int scanLine1, int scanLine2) { diff --git a/src/lib/OpenEXR/ImfScanLineInputFile.h b/src/lib/OpenEXR/ImfScanLineInputFile.h index c4e5ee5504..c5980809f4 100644 --- a/src/lib/OpenEXR/ImfScanLineInputFile.h +++ b/src/lib/OpenEXR/ImfScanLineInputFile.h @@ -8,7 +8,7 @@ //----------------------------------------------------------------------------- // -// class ScanLineInputFile +// class ScanLineInputFile // //----------------------------------------------------------------------------- @@ -169,6 +169,12 @@ class IMF_EXPORT_TYPE ScanLineInputFile IMF_EXPORT void rawPixelDataToBuffer ( int scanLine, char* pixelData, int& pixelDataSize) const; + + IMF_EXPORT + size_t bufferSize () const; + + IMF_EXPORT + void freeBuffers (); private: Context _ctxt; diff --git a/src/lib/OpenEXR/ImfTiledInputFile.cpp b/src/lib/OpenEXR/ImfTiledInputFile.cpp index d37115312d..9fe5202235 100644 --- a/src/lib/OpenEXR/ImfTiledInputFile.cpp +++ b/src/lib/OpenEXR/ImfTiledInputFile.cpp @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- // -// class TiledInputFile +// class TiledInputFile // //----------------------------------------------------------------------------- @@ -58,6 +58,16 @@ struct TileProcess int t_absX, int t_absY, const std::vector &filllist); + size_t get_buffer_size () + { + return exr_decoding_get_buffer_size (&decoder); + } + + void free_buffers () + { + exr_decoding_free_buffers (&decoder); + } + bool first = true; exr_chunk_info_t cinfo; exr_decode_pipeline_t decoder; @@ -783,6 +793,43 @@ TiledInputFile::tileOrder (int dx[], int dy[], int lx[], int ly[]) const } } +size_t +TiledInputFile::bufferSize () const +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + size_t retval = 0; + + std::shared_ptr sp = _data->processStack; + + while (sp) + { + retval += sp->get_buffer_size(); + + sp = sp->next; + } + + return retval; +} + +void +TiledInputFile::freeBuffers () +{ +#if ILMTHREAD_THREADING_ENABLED + std::lock_guard lock (_data->_mx); +#endif + std::shared_ptr sp = _data->processStack; + + while (sp) + { + sp->free_buffers(); + + sp = sp->next; + } +} + + void TiledInputFile::Data::readTiles (int dx1, int dx2, int dy1, int dy2, int lx, int ly) { int nTiles = dx2 - dx1 + 1; diff --git a/src/lib/OpenEXR/ImfTiledInputFile.h b/src/lib/OpenEXR/ImfTiledInputFile.h index 9ab1232d8a..69c21976c0 100644 --- a/src/lib/OpenEXR/ImfTiledInputFile.h +++ b/src/lib/OpenEXR/ImfTiledInputFile.h @@ -8,7 +8,7 @@ //----------------------------------------------------------------------------- // -// class TiledInputFile +// class TiledInputFile // //----------------------------------------------------------------------------- @@ -138,37 +138,37 @@ class IMF_EXPORT_TYPE TiledInputFile // // numXLevels() returns the file's number of levels in x direction. // - // if levelMode() == ONE_LEVEL: + // if levelMode() == ONE_LEVEL: // return value is: 1 // - // if levelMode() == MIPMAP_LEVELS: + // if levelMode() == MIPMAP_LEVELS: // return value is: rfunc (log (max (w, h)) / log (2)) + 1 // - // if levelMode() == RIPMAP_LEVELS: + // if levelMode() == RIPMAP_LEVELS: // return value is: rfunc (log (w) / log (2)) + 1 // - // where - // w is the width of the image's data window, max.x - min.x + 1, - // y is the height of the image's data window, max.y - min.y + 1, - // and rfunc(x) is either floor(x), or ceil(x), depending on - // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. + // where + // w is the width of the image's data window, max.x - min.x + 1, + // y is the height of the image's data window, max.y - min.y + 1, + // and rfunc(x) is either floor(x), or ceil(x), depending on + // whether levelRoundingMode() returns ROUND_DOWN or ROUND_UP. // // numYLevels() returns the file's number of levels in y direction. // - // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: // return value is the same as for numXLevels() // - // if levelMode() == RIPMAP_LEVELS: + // if levelMode() == RIPMAP_LEVELS: // return value is: rfunc (log (h) / log (2)) + 1 // // // numLevels() is a convenience function for use with // MIPMAP_LEVELS files. // - // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: + // if levelMode() == ONE_LEVEL or levelMode() == MIPMAP_LEVELS: // return value is the same as for numXLevels() // - // if levelMode() == RIPMAP_LEVELS: + // if levelMode() == RIPMAP_LEVELS: // an IEX_NAMESPACE::LogicExc exception is thrown // // isValidLevel(lx, ly) returns true if the file contains @@ -191,14 +191,14 @@ class IMF_EXPORT_TYPE TiledInputFile // levelWidth(lx) returns the width of a level with level // number (lx, *), where * is any number. // - // return value is: + // return value is: // max (1, rfunc (w / pow (2, lx))) // // // levelHeight(ly) returns the height of a level with level // number (*, ly), where * is any number. // - // return value is: + // return value is: // max (1, rfunc (h / pow (2, ly))) // //---------------------------------------------------------- @@ -215,7 +215,7 @@ class IMF_EXPORT_TYPE TiledInputFile // that cover a level with level number (lx, *), where * is // any number. // - // return value is: + // return value is: // (levelWidth(lx) + tileXSize() - 1) / tileXSize() // // @@ -223,7 +223,7 @@ class IMF_EXPORT_TYPE TiledInputFile // that cover a level with level number (*, ly), where * is // any number. // - // return value is: + // return value is: // (levelHeight(ly) + tileXSize() - 1) / tileXSize() // //-------------------------------------------------------------- @@ -239,10 +239,10 @@ class IMF_EXPORT_TYPE TiledInputFile // dataWindowForLevel(lx, ly) returns a 2-dimensional region of // valid pixel coordinates for a level with level number (lx, ly) // - // return value is a Box2i with min value: + // return value is a Box2i with min value: // (dataWindow.min.x, dataWindow.min.y) // - // and max value: + // and max value: // (dataWindow.min.x + levelWidth(lx) - 1, // dataWindow.min.y + levelHeight(ly) - 1) // @@ -264,11 +264,11 @@ class IMF_EXPORT_TYPE TiledInputFile // region of valid pixel coordinates for a tile with tile coordinates // (dx,dy) and level number (lx, ly). // - // return value is a Box2i with min value: + // return value is a Box2i with min value: // (dataWindow.min.x + dx * tileXSize(), // dataWindow.min.y + dy * tileYSize()) // - // and max value: + // and max value: // (dataWindow.min.x + (dx + 1) * tileXSize() - 1, // dataWindow.min.y + (dy + 1) * tileYSize() - 1) // @@ -344,6 +344,12 @@ class IMF_EXPORT_TYPE TiledInputFile const char*& pixelData, int& pixelDataSize); + IMF_EXPORT + size_t bufferSize () const; + + IMF_EXPORT + void freeBuffers (); + private: Context _ctxt; struct IMF_HIDDEN Data; diff --git a/src/lib/OpenEXR/ImfTiledInputPart.cpp b/src/lib/OpenEXR/ImfTiledInputPart.cpp index 71d34a088c..8cf539a5de 100644 --- a/src/lib/OpenEXR/ImfTiledInputPart.cpp +++ b/src/lib/OpenEXR/ImfTiledInputPart.cpp @@ -184,4 +184,16 @@ TiledInputPart::rawTileData ( file->rawTileData (dx, dy, lx, ly, pixelData, pixelDataSize); } +unsigned long long +TiledInputPart::bufferSize () const +{ + return file->bufferSize (); +} + +void +TiledInputPart::freeBuffers () +{ + file->freeBuffers (); +} + OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT diff --git a/src/lib/OpenEXR/ImfTiledInputPart.h b/src/lib/OpenEXR/ImfTiledInputPart.h index fafe7353fa..71dc7c7d10 100644 --- a/src/lib/OpenEXR/ImfTiledInputPart.h +++ b/src/lib/OpenEXR/ImfTiledInputPart.h @@ -86,6 +86,10 @@ class IMF_EXPORT_TYPE TiledInputPart int& ly, const char*& pixelData, int& pixelDataSize); + IMF_EXPORT + unsigned long long bufferSize () const; + IMF_EXPORT + void freeBuffers (); private: TiledInputFile* file; diff --git a/src/lib/OpenEXRCore/decoding.c b/src/lib/OpenEXRCore/decoding.c index 0ca2a9980b..2d241f16ad 100644 --- a/src/lib/OpenEXRCore/decoding.c +++ b/src/lib/OpenEXRCore/decoding.c @@ -154,9 +154,8 @@ default_read_chunk (exr_decode_pipeline_t* decode) decode->unpacked_alloc_size == 0) decode->unpacked_buffer = NULL; - if ((part->storage_mode == EXR_STORAGE_DEEP_SCANLINE || - part->storage_mode == EXR_STORAGE_DEEP_TILED) && - decode->chunk.sample_count_table_size > 0) + if (part->storage_mode == EXR_STORAGE_DEEP_SCANLINE || + part->storage_mode == EXR_STORAGE_DEEP_TILED) { rv = internal_decode_alloc_buffer ( decode, @@ -193,7 +192,7 @@ default_read_chunk (exr_decode_pipeline_t* decode) decode->packed_sample_count_table); } } - else if (decode->chunk.packed_size > 0) + else { rv = internal_decode_alloc_buffer ( decode, @@ -205,8 +204,6 @@ default_read_chunk (exr_decode_pipeline_t* decode) rv = exr_read_chunk ( ctxt, decode->part_index, &(decode->chunk), decode->packed_buffer); } - else - rv = EXR_ERR_SUCCESS; return rv; } @@ -313,13 +310,6 @@ exr_decoding_initialize ( } } - /* will have already been reported during header parse, but just - * stop the file from being read - */ - if (!part->channels || part->channels->type != EXR_ATTR_CHLIST || - part->channels->chlist->num_channels <= 0) - return EXR_ERR_INVALID_ATTR; - rv = internal_coding_fill_channel_info ( &(decode->channels), &(decode->channel_count), @@ -672,25 +662,24 @@ exr_decoding_run ( /**************************************/ -exr_result_t -exr_decoding_destroy (exr_const_context_t ctxt, exr_decode_pipeline_t* decode) +size_t +exr_decoding_get_buffer_size (exr_decode_pipeline_t* decode) { - if (!ctxt) return EXR_ERR_MISSING_CONTEXT_ARG; + return (decode->packed_alloc_size + + decode->unpacked_alloc_size + + decode->scratch_alloc_size_1 + + decode->scratch_alloc_size_2 + + decode->sample_count_alloc_size + + decode->packed_sample_count_alloc_size); +} +/**************************************/ + +exr_result_t +exr_decoding_free_buffers (exr_decode_pipeline_t* decode) +{ if (decode) { - exr_decode_pipeline_t nil = {0}; - if (decode->channels != decode->_quick_chan_store) - ctxt->free_fn (decode->channels); - - if (decode->unpacked_buffer == decode->packed_buffer && - decode->unpacked_alloc_size == 0) - decode->unpacked_buffer = NULL; - - if (decode->sample_count_table == decode->packed_sample_count_table && - decode->sample_count_alloc_size == 0) - decode->sample_count_table = NULL; - internal_decode_free_buffer ( decode, EXR_TRANSCODE_BUFFER_PACKED, @@ -722,6 +711,32 @@ 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)); + } + return EXR_ERR_SUCCESS; +} +/**************************************/ + +exr_result_t +exr_decoding_destroy (exr_const_context_t ctxt, exr_decode_pipeline_t* decode) +{ + 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); + + if (decode->unpacked_buffer == decode->packed_buffer && + decode->unpacked_alloc_size == 0) + decode->unpacked_buffer = NULL; + + if (decode->sample_count_table == decode->packed_sample_count_table && + decode->sample_count_alloc_size == 0) + decode->sample_count_table = NULL; + + exr_decoding_free_buffers(decode); + *decode = nil; } return EXR_ERR_SUCCESS; diff --git a/src/lib/OpenEXRCore/openexr_decode.h b/src/lib/OpenEXRCore/openexr_decode.h index ba53c79569..64620891c6 100644 --- a/src/lib/OpenEXRCore/openexr_decode.h +++ b/src/lib/OpenEXRCore/openexr_decode.h @@ -317,12 +317,27 @@ EXR_EXPORT exr_result_t exr_decoding_run ( exr_const_context_t ctxt, int part_index, exr_decode_pipeline_t* decode); +EXR_EXPORT +size_t +exr_decoding_get_buffer_size (exr_decode_pipeline_t* decode); + /** Free any intermediate memory in the decoding pipeline. * * This does *not* free any pointers referred to in the channel info * areas, but rather only the intermediate buffers and memory needed * for the structure itself. */ + +EXR_EXPORT +exr_result_t +exr_decoding_free_buffers (exr_decode_pipeline_t* decode); + + /** Destroy the decoder. + * + * decode struct will be zeroed out. + */ + + EXR_EXPORT exr_result_t exr_decoding_destroy (exr_const_context_t ctxt, exr_decode_pipeline_t* decode);