This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository legacy-imlib2.

View the commit online.

commit f420464ee00933e89d432605bb369f542c400bc8
Author: Kim Woelders <k...@woelders.dk>
AuthorDate: Fri Aug 25 09:25:08 2023 +0200

    HEIF saver: Add one
    
    Seems to be leaky though.
---
 src/modules/loaders/Makefile.am   |   2 +-
 src/modules/loaders/loader_heif.c | 136 +++++++++++++++++++++++++++++++++++++-
 test/test_save.cpp                |  15 ++++-
 3 files changed, 149 insertions(+), 4 deletions(-)

diff --git a/src/modules/loaders/Makefile.am b/src/modules/loaders/Makefile.am
index 5be82aa..d5752ce 100644
--- a/src/modules/loaders/Makefile.am
+++ b/src/modules/loaders/Makefile.am
@@ -96,7 +96,7 @@ gif_la_LDFLAGS       = -module -avoid-version
 gif_la_LIBADD        = $(GIF_LIBS) $(top_builddir)/src/lib/libImlib2.la
 gif_la_LIBTOOLFLAGS  = --tag=disable-static
 
-heif_la_SOURCES      = loader_heif.c
+heif_la_SOURCES      = loader_heif.c $(SRCS_SAVE)
 heif_la_CPPFLAGS     = $(AM_CPPFLAGS) $(HEIF_CFLAGS)
 heif_la_LDFLAGS      = -module -avoid-version
 heif_la_LIBADD       = $(HEIF_LIBS) $(top_builddir)/src/lib/libImlib2.la
diff --git a/src/modules/loaders/loader_heif.c b/src/modules/loaders/loader_heif.c
index b6dacfe..2428103 100644
--- a/src/modules/loaders/loader_heif.c
+++ b/src/modules/loaders/loader_heif.c
@@ -6,7 +6,9 @@
  */
 #include "config.h"
 #include "Imlib2_Loader.h"
+#include "ldrs_util.h"
 
+#include <errno.h>
 #include <stdbool.h>
 #include <libheif/heif.h>
 
@@ -173,9 +175,139 @@ _load(ImlibImage *im, int load_data)
     return rc;
 }
 
+static struct heif_error
+_heif_writer(struct heif_context *ctx, const void *data, size_t size,
+             void *userdata)
+{
+    struct heif_error error = heif_error_success;
+    FILE           *fp = userdata;
+    size_t          nw;
+
+    nw = fwrite(data, 1, size, fp);
+    if (nw != size)
+    {
+        error.code = heif_error_Encoding_error;
+        error.subcode = errno;
+    }
+
+    return error;
+}
+
+static int
+_heif_write(struct heif_context *ctx, FILE *fp)
+{
+    struct heif_error error;
+    struct heif_writer writer;
+
+    writer.writer_api_version = 1;
+    writer.write = _heif_writer;
+
+    error = heif_context_write(ctx, &writer, fp);
+
+    return IS_ERROR(error) ? LOAD_FAIL : LOAD_SUCCESS;
+}
+
+static int
+_save(ImlibImage *im)
+{
+    int             rc = LOAD_FAIL;
+    ImlibSaverParam imsp;
+    int             compr_type;
+    bool            has_alpha;
+    struct heif_error error;
+    struct heif_context *ctx = NULL;
+    struct heif_encoder *encoder = NULL;
+    struct heif_image *image = NULL;
+    int             bit_depth, bypp, stride;
+    uint8_t        *img_plane;
+
+    ctx = heif_context_alloc();
+    if (!ctx)
+        goto quit;
+
+    compr_type = heif_compression_HEVC;
+    if (im->fi->name)
+    {
+        if (strstr(im->fi->name, ".avif"))
+            compr_type = heif_compression_AV1;
+        else if (strstr(im->fi->name, ".heic"))
+            compr_type = heif_compression_HEVC;
+    }
+
+    get_saver_params(im, &imsp);
+
+    if (imsp.compr_type >= 0)
+        compr_type = imsp.compr_type;
+
+    D("Compression type   : %d\n", compr_type);
+    D("Compression/quality: %d/%d\n", imsp.compression, imsp.quality);
+
+    error = heif_context_get_encoder_for_format(ctx, compr_type, &encoder);
+    if (IS_ERROR(error))
+        goto quit;
+
+    if (imsp.quality == 100)
+    {
+        heif_encoder_set_lossless(encoder, 1);
+    }
+    else
+    {
+        heif_encoder_set_lossless(encoder, 0);
+        heif_encoder_set_lossy_quality(encoder, imsp.quality);
+    }
+
+    has_alpha = im->has_alpha;
+
+    error = heif_image_create(im->w, im->h, heif_colorspace_RGB,
+                              has_alpha ?
+                              heif_chroma_interleaved_RGBA :
+                              heif_chroma_interleaved_RGB, &image);
+    if (IS_ERROR(error))
+        goto quit;
+
+    bit_depth = 8;
+    heif_image_add_plane(image, heif_channel_interleaved, im->w, im->h,
+                         bit_depth);
+
+    img_plane = heif_image_get_plane(image, heif_channel_interleaved, &stride);
+    if (!img_plane)
+        goto quit;
+
+    bypp = has_alpha ? 4 : 3;
+
+    for (int y = 0; y < im->h; y++)
+    {
+        const uint8_t  *pi;
+        uint8_t        *po;
+
+        pi = (const uint8_t *)(im->data + y * im->w);
+        po = img_plane + y * stride;
+
+        for (int x = 0; x < im->w; x++, pi += 4, po += bypp)
+        {
+            po[0] = pi[2];
+            po[1] = pi[1];
+            po[2] = pi[0];
+            if (has_alpha)
+                po[3] = pi[3];
+        }
+    }
+
+    heif_context_encode_image(ctx, image, encoder, NULL, NULL);
+
+    rc = _heif_write(ctx, im->fi->fp);
+
+  quit:
+    heif_image_release(image);
+    heif_encoder_release(encoder);
+    heif_context_free(ctx);
+
+    return rc;
+}
+
 #if !LIBHEIF_HAVE_VERSION(1, 13, 0)
 
-IMLIB_LOADER_KEEP(_formats, _load, NULL);
+IMLIB_LOADER_KEEP(_formats, _load, _save);
 
 #else
 
@@ -188,6 +320,6 @@ _inex(int init)
         heif_deinit();
 }
 
-IMLIB_LOADER_INEX(_formats, _load, NULL, _inex);
+IMLIB_LOADER_INEX(_formats, _load, _save, _inex);
 
 #endif
diff --git a/test/test_save.cpp b/test/test_save.cpp
index 604d9ad..c474f93 100644
--- a/test/test_save.cpp
+++ b/test/test_save.cpp
@@ -3,6 +3,9 @@
 #include "config.h"
 #include <fcntl.h>
 #include <Imlib2.h>
+#ifdef BUILD_HEIF_LOADER
+#include <libheif/heif.h>
+#endif
 #ifdef BUILD_JXL_LOADER
 #include <jxl/version.h>
 #endif
@@ -25,7 +28,17 @@ static const test_rec_t exts[] = {
 // { "bz2",  { 0, 0 } },
    { "ff",   { 1636116234,  169859126 } },
 // { "gif",  { 0, 0 } },
-// { "heif", { 0, 0 } },
+#ifdef BUILD_HEIF_LOADER
+#ifndef __SANITIZE_ADDRESS__
+#if LIBHEIF_HAVE_VERSION(1, 19, 0)
+   { "avif", {  271316575,  632516970 } },
+   { "heic", { 2429908023, 1720725349 } },
+#else
+   { "avif", {  458570512, 4237984766 } },
+   { "heic", { 4046271191,  793249753 } },
+#endif
+#endif
+#endif
 // { "ico",  { 0, 0 } },
 // { "id3",  { 0, 0 } },
 // { "j2k",  { 0, 0 } },

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to