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.