Evas: heif module is dlopen'ed

The reason is that for newer versions, libheif should be initialized
with heif_init(). This way, we call this function if the symbol exists.
This commit is contained in:
Vincent Torri 2023-05-01 18:12:28 +02:00 committed by Carsten Haitzler (Rasterman)
parent 8c30cb2ef8
commit 201a32279f
2 changed files with 151 additions and 23 deletions

View File

@ -21,7 +21,7 @@ evas_image_loaders_file = [
['eet', 'static', [eet]],
['generic', 'shared', [rt]],
['gif', 'shared', [giflib]],
['heif', 'shared', [heif]],
['heif', 'shared', []],
['ico', 'shared', []],
['jpeg', 'static', [jpeg]],
['jp2k', 'shared', [libopenjp2]],

View File

@ -16,6 +16,86 @@ struct _Evas_Loader_Internal
};
static int _evas_loader_heif_log_dom = -1;
static Eina_Module *_evas_loader_heif_mod = NULL;
#define LOAD(x) \
if (!_evas_loader_heif_mod) { \
if ((_evas_loader_heif_mod = eina_module_new(x))) { \
if (!eina_module_load(_evas_loader_heif_mod)) { \
eina_module_free(_evas_loader_heif_mod); \
_evas_loader_heif_mod = NULL; \
} \
} \
}
#define SYM(x) \
if (!(x ## _f = eina_module_symbol_get(_evas_loader_heif_mod, #x))) { \
ERR("Cannot find symbol '%s' in '%s'", \
#x, eina_module_file_get(_evas_loader_heif_mod)); \
goto error; \
}
// heif_check_filetype
typedef enum heif_filetype_result (*heif_check_filetype_t)(const uint8_t* data,
int len);
static heif_check_filetype_t heif_check_filetype_f = NULL;
// heif_context_alloc
typedef struct heif_context* (*heif_context_alloc_t)(void);
static heif_context_alloc_t heif_context_alloc_f = NULL;
// heif_context_free
typedef void (*heif_context_free_t)(struct heif_context*);
static heif_context_free_t heif_context_free_f = NULL;
// heif_context_get_primary_image_handle
typedef struct heif_error (*heif_context_get_primary_image_handle_t)(struct heif_context* ctx,
struct heif_image_handle**);
static heif_context_get_primary_image_handle_t heif_context_get_primary_image_handle_f = NULL;
// heif_context_read_from_memory_without_copy
typedef struct heif_error (*heif_context_read_from_memory_without_copy_t)(struct heif_context*,
const void* mem, size_t size,
const struct heif_reading_options*);
static heif_context_read_from_memory_without_copy_t heif_context_read_from_memory_without_copy_f = NULL;
// heif_decode_image
typedef struct heif_error (*heif_decode_image_t)(const struct heif_image_handle* in_handle,
struct heif_image** out_img,
enum heif_colorspace colorspace,
enum heif_chroma chroma,
const struct heif_decoding_options* options);
static heif_decode_image_t heif_decode_image_f = NULL;
// heif_deinit
typedef void (*heif_deinit_t)();
static heif_deinit_t heif_deinit_f = NULL;
// heif_image_get_plane_readonly
typedef const uint8_t* (*heif_image_get_plane_readonly_t)(const struct heif_image*,
enum heif_channel channel,
int* out_stride);
static heif_image_get_plane_readonly_t heif_image_get_plane_readonly_f = NULL;
// heif_image_handle_get_height
typedef int (*heif_image_handle_get_height_t)(const struct heif_image_handle* handle);
static heif_image_handle_get_height_t heif_image_handle_get_height_f = NULL;
// heif_image_handle_get_width
typedef int (*heif_image_handle_get_width_t)(const struct heif_image_handle* handle);
static heif_image_handle_get_width_t heif_image_handle_get_width_f = NULL;
// heif_image_handle_has_alpha_channel
typedef int (*heif_image_handle_has_alpha_channel_t)(const struct heif_image_handle*);
static heif_image_handle_has_alpha_channel_t heif_image_handle_has_alpha_channel_f = NULL;
// heif_init
typedef struct heif_error (*heif_init_t)(struct heif_init_params*);
static heif_init_t heif_init_f = NULL;
// heif_image_handle_release
typedef void (*heif_image_handle_release_t)(const struct heif_image_handle*);
static heif_image_handle_release_t heif_image_handle_release_f = NULL;
#ifdef ERR
# undef ERR
@ -45,14 +125,14 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
/* heif file must have a 12 bytes long header */
if ((length < 12) ||
(heif_check_filetype(map, length) == heif_filetype_no))
(heif_check_filetype_f(map, length) == heif_filetype_no))
{
INF("HEIF header invalid");
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
return ret;
}
ctx = heif_context_alloc();
ctx = heif_context_alloc_f();
if (!ctx)
{
INF("cannot allocate heif_context");
@ -60,7 +140,7 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
return ret;
}
err = heif_context_read_from_memory_without_copy(ctx, map, length, NULL);
err = heif_context_read_from_memory_without_copy_f(ctx, map, length, NULL);
if (err.code != heif_error_Ok)
{
INF("%s", err.message);
@ -68,7 +148,7 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
goto free_ctx;
}
err = heif_context_get_primary_image_handle(ctx, &handle);
err = heif_context_get_primary_image_handle_f(ctx, &handle);
if (err.code != heif_error_Ok)
{
INF("%s", err.message);
@ -76,8 +156,8 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
goto free_ctx;
}
prop->w = heif_image_handle_get_width(handle);
prop->h = heif_image_handle_get_height(handle);
prop->w = heif_image_handle_get_width_f(handle);
prop->h = heif_image_handle_get_height_f(handle);
/* if size is invalid, we exit */
if ((prop->w < 1) || (prop->h < 1) ||
@ -91,15 +171,15 @@ evas_image_load_file_head_heif_internal(Evas_Loader_Internal *loader EINA_UNUSED
goto release_handle;
}
prop->alpha = !!heif_image_handle_has_alpha_channel(handle);
prop->alpha = !!heif_image_handle_has_alpha_channel_f(handle);
*error = EVAS_LOAD_ERROR_NONE;
ret = EINA_TRUE;
release_handle:
heif_image_handle_release(handle);
heif_image_handle_release_f(handle);
free_ctx:
heif_context_free(ctx);
heif_context_free_f(ctx);
return ret;
}
@ -128,7 +208,7 @@ evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
ctx = loader->ctx;
if (!ctx)
{
ctx = heif_context_alloc();
ctx = heif_context_alloc_f();
if (!ctx)
{
INF("cannot allocate heif_context");
@ -136,33 +216,33 @@ evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
return ret;
}
err = heif_context_read_from_memory_without_copy(ctx,
map, length, NULL);
err = heif_context_read_from_memory_without_copy_f(ctx,
map, length, NULL);
if (err.code != heif_error_Ok)
{
INF("%s", err.message);
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
heif_context_free(ctx);
heif_context_free_f(ctx);
return ret;
}
err = heif_context_get_primary_image_handle(ctx, &handle);
err = heif_context_get_primary_image_handle_f(ctx, &handle);
if (err.code != heif_error_Ok)
{
INF("%s", err.message);
*error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
heif_image_handle_release(handle);
heif_context_free(ctx);
heif_image_handle_release_f(handle);
heif_context_free_f(ctx);
return ret;
}
loader->ctx = ctx;
}
err = heif_decode_image(handle, &img, heif_colorspace_RGB,
prop->alpha ? heif_chroma_interleaved_RGBA
: heif_chroma_interleaved_RGB,
NULL);
err = heif_decode_image_f(handle, &img, heif_colorspace_RGB,
prop->alpha ? heif_chroma_interleaved_RGBA
: heif_chroma_interleaved_RGB,
NULL);
if (err.code != heif_error_Ok)
{
@ -171,7 +251,7 @@ evas_image_load_file_data_heif_internal(Evas_Loader_Internal *loader,
goto on_error;
}
data = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
data = heif_image_get_plane_readonly_f(img, heif_channel_interleaved, &stride);
dd = (unsigned char *)pixels;
ds = (unsigned char *)data;
@ -248,7 +328,7 @@ evas_image_load_file_close_heif(void *loader_data)
* loader is not filled and loader->ctx is NULL
*/
if (loader->ctx)
heif_context_free(loader->ctx);
heif_context_free_f(loader->ctx);
free(loader_data);
}
@ -340,12 +420,60 @@ module_open(Evas_Module *em)
em->functions = (void *)(&evas_image_load_heif_func);
#if defined (_WIN32)
LOAD("libheif-1.dll");
LOAD("libheif.dll");
#elif defined (_CYGWIN__)
LOAD("cygheif-1.dll");
#elif defined(__APPLE__) && defined(__MACH__)
LOAD("libheif.1.dylib");
#else
LOAD("libheif.so.1");
#endif
if (!_evas_loader_heif_mod)
{
EINA_LOG_ERR("Can not open libheif shared library.");
goto error;
}
SYM(heif_check_filetype);
SYM(heif_context_alloc);
SYM(heif_context_free);
SYM(heif_context_get_primary_image_handle);
SYM(heif_context_read_from_memory_without_copy);
SYM(heif_decode_image);
SYM(heif_image_get_plane_readonly);
SYM(heif_image_handle_get_height);
SYM(heif_image_handle_get_width);
SYM(heif_image_handle_has_alpha_channel);
SYM(heif_image_handle_release);
heif_init_f = eina_module_symbol_get(_evas_loader_heif_mod, "heif_init");
heif_deinit_f = eina_module_symbol_get(_evas_loader_heif_mod, "heif_deinit");
if (heif_init_f)
{
heif_init_f(NULL);
}
return 1;
error:
eina_log_domain_unregister(_evas_loader_heif_log_dom);
_evas_loader_heif_log_dom = -1;
return 0;
}
static void
module_close(Evas_Module *em EINA_UNUSED)
{
if (heif_deinit_f)
heif_deinit_f();
if (_evas_loader_heif_mod)
eina_module_free(_evas_loader_heif_mod);
if (_evas_loader_heif_log_dom >= 0)
{
eina_log_domain_unregister(_evas_loader_heif_log_dom);