From 590a5c2fb02f8933b3c9f263b30a089b5c2e6324 Mon Sep 17 00:00:00 2001 From: Arkadiy Illarionov Date: Sat, 25 Jan 2025 21:44:10 +0300 Subject: [PATCH] Use libheif C++ API Simplify heif_color_profile() and related a bit. --- src/color-man.cc | 101 ++++++++++++++--------------------------- src/color-man.h | 3 +- src/image-load-heif.cc | 75 ++++++++++-------------------- src/image.cc | 2 +- src/thumb-standard.cc | 2 +- 5 files changed, 61 insertions(+), 122 deletions(-) diff --git a/src/color-man.cc b/src/color-man.cc index 6ae4684fc..5e55f3977 100644 --- a/src/color-man.cc +++ b/src/color-man.cc @@ -38,7 +38,6 @@ # include #endif -#include "filedata.h" #include "image.h" #include "intl.h" #include "options.h" @@ -440,7 +439,9 @@ void color_man_update() #if HAVE_HEIF #include -#include +#include + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(heif_color_profile_nclx, heif_nclx_color_profile_free) static cmsToneCurve* colorspaces_create_transfer(int32_t size, double (*fct)(double)) { @@ -514,7 +515,7 @@ static double PQ_fct(double x) * * Copied from: gimp/libgimpcolor/gimpcolorprofile.c */ -static guchar *nclx_to_lcms_profile(const struct heif_color_profile_nclx *nclx, guint *profile_len) +static guchar *nclx_to_lcms_profile(const heif_color_profile_nclx *nclx, guint &profile_len) { const gchar *primaries_name = ""; const gchar *trc_name = ""; @@ -657,98 +658,62 @@ static guchar *nclx_to_lcms_profile(const struct heif_color_profile_nclx *nclx, data = static_cast(g_malloc(size)); if (cmsSaveProfileToMem(profile, data, &size)) { - *profile_len = size; + profile_len = size; } cmsCloseProfile(profile); return static_cast(data); } cmsCloseProfile(profile); - return nullptr; } return nullptr; } -guchar *heif_color_profile(FileData *fd, guint *profile_len) +guchar *heif_color_profile(const gchar *path, guint &profile_len) { - struct heif_context* ctx; - struct heif_error error_code; - struct heif_image_handle* handle; - struct heif_color_profile_nclx *nclxcp; - gint profile_type; - guchar *profile; - cmsUInt32Number size; - guint8 *data = nullptr; - - ctx = heif_context_alloc(); - error_code = heif_context_read_from_file(ctx, fd->path, nullptr); - - if (error_code.code) - { - log_printf("warning: heif reader error: %s\n", error_code.message); - heif_context_free(ctx); - return nullptr; - } + heif::Context ctx{}; - error_code = heif_context_get_primary_image_handle(ctx, &handle); - if (error_code.code) + try { - log_printf("warning: heif reader error: %s\n", error_code.message); - heif_image_handle_release(handle); - heif_context_free(ctx); - return nullptr; - } + ctx.read_from_file(path); - nclxcp = heif_nclx_color_profile_alloc(); - profile_type = heif_image_handle_get_color_profile_type(handle); + heif::ImageHandle image_handle = ctx.get_primary_image_handle(); + heif_image_handle *handle = image_handle.get_raw_image_handle(); - if (profile_type == heif_color_profile_type_prof) - { - size = heif_image_handle_get_raw_color_profile_size(handle); - *profile_len = size; - data = static_cast(g_malloc0(size)); - error_code = heif_image_handle_get_raw_color_profile(handle, data); - if (error_code.code) + if (heif_image_handle_get_color_profile_type(handle) == heif_color_profile_type_prof) { - log_printf("warning: heif reader error: %s\n", error_code.message); - heif_image_handle_release(handle); - heif_context_free(ctx); - heif_nclx_color_profile_free(nclxcp); - return nullptr; + profile_len = heif_image_handle_get_raw_color_profile_size(handle); + auto *data = static_cast(g_malloc0(profile_len)); + + heif_error error = heif_image_handle_get_raw_color_profile(handle, data); + if (error.code) throw heif::Error(error); + + DEBUG_1("heif color profile type: prof"); + + return static_cast(data); } - DEBUG_1("heif color profile type: prof"); - heif_image_handle_release(handle); - heif_context_free(ctx); - heif_nclx_color_profile_free(nclxcp); + g_autoptr(heif_color_profile_nclx) nclx_cp = heif_nclx_color_profile_alloc(); - return static_cast(data); - } + heif_error error = heif_image_handle_get_nclx_color_profile(handle, &nclx_cp); + if (error.code) throw heif::Error(error); - error_code = heif_image_handle_get_nclx_color_profile(handle, &nclxcp); - if (error_code.code) + return nclx_to_lcms_profile(nclx_cp, profile_len); + } + catch (const heif::Error &error) { - if (error_code.code != heif_error_Color_profile_does_not_exist) + if (error.get_code() != heif_error_Color_profile_does_not_exist) { - log_printf("warning: heif reader error: %d (%s)\n", error_code.code, error_code.message); + log_printf("warning: heif reader error: %d (%s)\n", + error.get_code(), error.get_message().c_str()); } - heif_image_handle_release(handle); - heif_context_free(ctx); - heif_nclx_color_profile_free(nclxcp); - return nullptr; } - profile = nclx_to_lcms_profile(nclxcp, profile_len); - - heif_image_handle_release(handle); - heif_context_free(ctx); - heif_nclx_color_profile_free(nclxcp); - - return profile; + return nullptr; } #else -guchar *heif_color_profile(FileData *, guint *) +guchar *heif_color_profile(const gchar *, guint &) { return NULL; } @@ -796,7 +761,7 @@ gboolean color_man_get_status(ColorMan *, gchar **, gchar **) return FALSE; } -guchar *heif_color_profile(FileData *, guint *) +guchar *heif_color_profile(const gchar *, guint &) { return nullptr; } diff --git a/src/color-man.h b/src/color-man.h index c1fdaf8ee..1f2f0bb51 100644 --- a/src/color-man.h +++ b/src/color-man.h @@ -25,7 +25,6 @@ #include #include -class FileData; struct ImageWindow; enum ColorManProfileType { @@ -75,6 +74,6 @@ void color_man_correct_region(ColorMan *cm, GdkPixbuf *pixbuf, gint x, gint y, g gboolean color_man_get_status(ColorMan *cm, gchar **image_profile, gchar **screen_profile); -guchar *heif_color_profile(FileData *fd, guint *profile_len); +guchar *heif_color_profile(const gchar *path, guint &profile_len); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image-load-heif.cc b/src/image-load-heif.cc index f85d1217a..af4549e31 100644 --- a/src/image-load-heif.cc +++ b/src/image-load-heif.cc @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include "image-load.h" @@ -61,65 +61,40 @@ void free_buffer(guchar *, gpointer data) gboolean ImageLoaderHEIF::write(const guchar *buf, gsize &chunk_size, gsize count, GError **) { - struct heif_context* ctx; - struct heif_image* img; - struct heif_error error_code; - struct heif_image_handle* handle; - guint8* pixels; - gint width; - gint height; - gint stride; - gboolean alpha; - - ctx = heif_context_alloc(); - - error_code = heif_context_read_from_memory_without_copy(ctx, buf, count, nullptr); - if (error_code.code) + heif::Context ctx{}; + + try { - log_printf("warning: heif reader error: %s\n", error_code.message); - heif_context_free(ctx); - return FALSE; - } + ctx.read_from_memory_without_copy(buf, count); - page_total = heif_context_get_number_of_top_level_images(ctx); + page_total = ctx.get_number_of_top_level_images(); - std::vector IDs(page_total); + /* get list of all (top level) image IDs */ + std::vector IDs = ctx.get_list_of_top_level_image_IDs(); - /* get list of all (top level) image IDs */ - heif_context_get_list_of_top_level_image_IDs(ctx, IDs.data(), page_total); + heif::ImageHandle handle = ctx.get_image_handle(IDs[page_num]); - error_code = heif_context_get_image_handle(ctx, IDs[page_num], &handle); - if (error_code.code) - { - log_printf("warning: heif reader error: %s\n", error_code.message); - heif_image_handle_release(handle); - heif_context_free(ctx); - return FALSE; - } + // decode the image and convert colorspace to RGB, saved as 24bit interleaved + heif_image *img; + heif_error error = heif_decode_image(handle.get_raw_image_handle(), &img, heif_colorspace_RGB, heif_chroma_interleaved_24bit, nullptr); + if (error.code) throw heif::Error(error); + + gint stride; + guint8* pixels = heif_image_get_plane(img, heif_channel_interleaved, &stride); + gint width = heif_image_get_width(img,heif_channel_interleaved); + gint height = heif_image_get_height(img,heif_channel_interleaved); + gboolean alpha = handle.has_alpha_channel(); - // decode the image and convert colorspace to RGB, saved as 24bit interleaved - error_code = heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_interleaved_24bit, nullptr); - if (error_code.code) + pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, alpha, 8, width, height, stride, free_buffer, img); + + area_updated_cb(nullptr, 0, 0, width, height, data); + } + catch (const heif::Error &error) { - log_printf("warning: heif reader error: %s\n", error_code.message); - heif_image_handle_release(handle); - heif_context_free(ctx); + log_printf("warning: heif reader error: %s\n", error.get_message().c_str()); return FALSE; } - pixels = heif_image_get_plane(img, heif_channel_interleaved, &stride); - - height = heif_image_get_height(img,heif_channel_interleaved); - width = heif_image_get_width(img,heif_channel_interleaved); - alpha = heif_image_handle_has_alpha_channel(handle); - heif_image_handle_release(handle); - - pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, alpha, 8, width, height, stride, free_buffer, img); - - area_updated_cb(nullptr, 0, 0, width, height, data); - - heif_context_free(ctx); - chunk_size = count; return TRUE; } diff --git a/src/image.cc b/src/image.cc index 3b7588d7c..29c16e552 100644 --- a/src/image.cc +++ b/src/image.cc @@ -489,7 +489,7 @@ static gboolean image_post_process_color(ImageWindow *imd, gint start_row, gbool { if (g_strcmp0(imd->image_fd->format_name, "heif") == 0) { - profile = heif_color_profile(imd->image_fd, &profile_len); + profile = heif_color_profile(imd->image_fd->path, profile_len); } if (!profile) diff --git a/src/thumb-standard.cc b/src/thumb-standard.cc index 1a02c9f90..70586c236 100644 --- a/src/thumb-standard.cc +++ b/src/thumb-standard.cc @@ -381,7 +381,7 @@ void thumb_loader_std_calibrate_pixbuf(FileData *fd, GdkPixbuf *pixbuf) { if (g_strcmp0(fd->format_name, "heif") == 0) { - profile = heif_color_profile(fd, &profile_len); + profile = heif_color_profile(fd->path, profile_len); } if (!profile)