summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormio <[email protected]>2025-03-11 13:54:49 +1000
committermio <[email protected]>2025-03-15 09:58:50 +1000
commite9ff844859434097d79e6d1b6393ce5eb81c2726 (patch)
treecac536a6d457818d2c9b7e682ca026bbb7803c39
parent18fbfb1e17eadd5f73cd7f1f510922b189d5d33f (diff)
downloaddigikam-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.cpp103
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;
}