Skip to content

Commit

Permalink
Use libheif C++ API
Browse files Browse the repository at this point in the history
Simplify heif_color_profile() and related a bit.
  • Loading branch information
qarkai authored and caclark committed Jan 26, 2025
1 parent 13b3f2e commit 590a5c2
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 122 deletions.
101 changes: 33 additions & 68 deletions src/color-man.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
# include <lcms.h>
#endif

#include "filedata.h"
#include "image.h"
#include "intl.h"
#include "options.h"
Expand Down Expand Up @@ -440,7 +439,9 @@ void color_man_update()

#if HAVE_HEIF
#include <cmath>
#include <libheif/heif.h>
#include <libheif/heif_cxx.h>

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))
{
Expand Down Expand Up @@ -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 = "";
Expand Down Expand Up @@ -657,98 +658,62 @@ static guchar *nclx_to_lcms_profile(const struct heif_color_profile_nclx *nclx,
data = static_cast<guint8 *>(g_malloc(size));
if (cmsSaveProfileToMem(profile, data, &size))
{
*profile_len = size;
profile_len = size;
}
cmsCloseProfile(profile);
return static_cast<guchar *>(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<guint8 *>(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<guint8 *>(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<guchar *>(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<guchar *>(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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
3 changes: 1 addition & 2 deletions src/color-man.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glib.h>

class FileData;
struct ImageWindow;

enum ColorManProfileType {
Expand Down Expand Up @@ -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: */
75 changes: 25 additions & 50 deletions src/image-load-heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <glib-object.h>
#include <glib.h>
#include <libheif/heif.h>
#include <libheif/heif_cxx.h>

#include "image-load.h"

Expand Down Expand Up @@ -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<heif_item_id> IDs(page_total);
/* get list of all (top level) image IDs */
std::vector<heif_item_id> 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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/image.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/thumb-standard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 590a5c2

Please sign in to comment.