diff options
author | mio <[email protected]> | 2025-03-11 13:54:49 +1000 |
---|---|---|
committer | mio <[email protected]> | 2025-03-15 09:58:50 +1000 |
commit | e9ff844859434097d79e6d1b6393ce5eb81c2726 (patch) | |
tree | cac536a6d457818d2c9b7e682ca026bbb7803c39 | |
parent | 18fbfb1e17eadd5f73cd7f1f510922b189d5d33f (diff) | |
download | digikam-e9ff844859434097d79e6d1b6393ce5eb81c2726.tar.gz digikam-e9ff844859434097d79e6d1b6393ce5eb81c2726.zip |
Use JasPer 3 init/cleanup functionsr14.1.x
The jas_init() and jas_cleanup() where deprecated in JasPer 3.0. There
was also a functionality change in jas_init() which has stopped
registering jas_cleanup() with 'atexit(3)', meaning that, when compiled
with JasPer 3 or newer, there have been memory leaks in certain
instances.
This commit also introduces a memory limit for JasPer, without which,
JasPer will log warnings to the standard error stream. We set a
maximum of 512 MB, but will use whatever JasPer was configured with if
it is lower.
Signed-off-by: mio <[email protected]>
(cherry picked from commit 0b5e696d79ab1a160293d520b7526e031238989a)
-rw-r--r-- | src/libs/dimg/loaders/jp2kloader.cpp | 103 |
1 files changed, 89 insertions, 14 deletions
diff --git a/src/libs/dimg/loaders/jp2kloader.cpp b/src/libs/dimg/loaders/jp2kloader.cpp index 66351c25..016a7196 100644 --- a/src/libs/dimg/loaders/jp2kloader.cpp +++ b/src/libs/dimg/loaders/jp2kloader.cpp @@ -58,6 +58,16 @@ extern "C" #include "dimgloaderobserver.h" #include "jp2kloader.h" +static void cleanup_jasper() +{ +#if defined(JAS_VERSION_MAJOR) && (JAS_VERSION_MAJOR >= 3) + jas_cleanup_thread(); + jas_cleanup_library(); +#else + jas_cleanup(); +#endif +} + namespace Digikam { @@ -69,7 +79,7 @@ JP2KLoader::JP2KLoader(DImg* image) } bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) -{ +{ readMetadata(filePath, DImg::JPEG); FILE *file = fopen(TQFile::encodeName(filePath), "rb"); @@ -109,17 +119,45 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) jas_stream_t *jp2_stream = 0; jas_matrix_t *pixels[4]; - int init = jas_init(); - if (init != 0) + +#if defined(JAS_VERSION_MAJOR) && (JAS_VERSION_MAJOR >= 3) + jas_conf_clear(); + + // Limit JasPer memory usage to 512 MB + size_t memoryLimit = (512 * 1024) * 1024; + size_t jasperTotalMemSize = jas_get_total_mem_size(); + if (!jasperTotalMemSize) + { + jasperTotalMemSize = JAS_DEFAULT_MAX_MEM_USAGE; + } + memoryLimit = (memoryLimit < jasperTotalMemSize) ? memoryLimit : jasperTotalMemSize; + jas_conf_set_max_mem_usage(memoryLimit); + + if (jas_init_library()) + { + DDebug() << "Unable to init JPEG2000 decoder" << endl; + return false; + } + + if (jas_init_thread()) + { + DDebug() << "Unable to init JPEG2000 decoder" << endl; + jas_cleanup_library(); + return false; + } +#else + if (jas_init()) { DDebug() << "Unable to init JPEG2000 decoder" << endl; return false; } +#endif jp2_stream = jas_stream_fopen(TQFile::encodeName(filePath), "rb"); if (jp2_stream == 0) { DDebug() << "Unable to open JPEG2000 stream" << endl; + cleanup_jasper(); return false; } @@ -127,6 +165,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) if (jp2_image == 0) { jas_stream_close(jp2_stream); + cleanup_jasper(); DDebug() << "Unable to decode JPEG2000 image" << endl; return false; } @@ -150,6 +189,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0)) { jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error parsing JPEG2000 image : Missing Image Channel" << endl; return false; } @@ -169,6 +209,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) if (components[0] < 0) { jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error parsing JP2000 image : Missing Image Channel" << endl; return false; } @@ -183,6 +224,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) if ((components[0] < 0) || (components[1] < 0) || (components[2] < 0)) { jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error parsing JP2000 image : Missing Image Channel" << endl; return false; } @@ -199,6 +241,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) default: { jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error parsing JP2000 image : Colorspace Model Is Not Supported" << endl; return false; } @@ -221,6 +264,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) (jas_image_cmptsgnd(jp2_image, components[i]) != false)) { jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error parsing JPEG2000 image : Irregular Channel Geometry Not Supported" << endl; return false; } @@ -242,6 +286,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) if (!pixels[i]) { jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error decoding JPEG2000 image data : Memory Allocation Failed" << endl; return false; } @@ -271,7 +316,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return false; } @@ -295,7 +340,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return false; } } @@ -402,7 +447,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return false; } @@ -452,7 +497,7 @@ bool JP2KLoader::load(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return true; } @@ -476,20 +521,48 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) jas_matrix_t *pixels[4]; jas_image_cmptparm_t component_info[4]; - int init = jas_init(); - if (init != 0) + +#if defined(JAS_VERSION_MAJOR) && (JAS_VERSION_MAJOR >= 3) + jas_conf_clear(); + + // Limit JasPer memory usage to 512 MB + size_t memoryLimit = (512 * 1024) * 1024; + size_t jasperTotalMemSize = jas_get_total_mem_size(); + if (!jasperTotalMemSize) + { + jasperTotalMemSize = JAS_DEFAULT_MAX_MEM_USAGE; + } + memoryLimit = (memoryLimit < jasperTotalMemSize) ? memoryLimit : jasperTotalMemSize; + jas_conf_set_max_mem_usage(memoryLimit); + + if (jas_init_library()) + { + DDebug() << "Unable to init JPEG2000 decoder" << endl; + return false; + } + + if (jas_init_thread()) + { + DDebug() << "Unable to init JPEG2000 decoder" << endl; + jas_cleanup_library(); + return false; + } +#else + if (jas_init()) { DDebug() << "Unable to init JPEG2000 decoder" << endl; return false; } +#endif jp2_stream = jas_stream_fopen(TQFile::encodeName(filePath), "wb"); if (jp2_stream == 0) { DDebug() << "Unable to open JPEG2000 stream" << endl; + cleanup_jasper(); return false; } - + number_components = imageHasAlpha() ? 4 : 3; for (i = 0 ; i < (long)number_components ; i++) @@ -508,6 +581,7 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) if (jp2_image == 0) { jas_stream_close(jp2_stream); + cleanup_jasper(); DDebug() << "Unable to create JPEG2000 image" << endl; return false; } @@ -562,6 +636,7 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) jas_matrix_destroy(pixels[x]); jas_image_destroy(jp2_image); + cleanup_jasper(); DDebug() << "Error encoding JPEG2000 image data : Memory Allocation Failed" << endl; return false; } @@ -583,7 +658,7 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return false; } @@ -633,7 +708,7 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return false; } } @@ -680,7 +755,7 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return false; } @@ -697,7 +772,7 @@ bool JP2KLoader::save(const TQString& filePath, DImgLoaderObserver *observer) for (i = 0 ; i < (long)number_components ; i++) jas_matrix_destroy(pixels[i]); - jas_cleanup(); + cleanup_jasper(); return true; } |