aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlo Abelli <carlo@abelli.me>2020-03-15 12:51:46 -0400
committerHarry Jeffery <harry@exec64.co.uk>2020-05-21 11:31:04 +0100
commiteb60fefc3b7e9b5367bca9d3b5e5d4e50f5b72a7 (patch)
treefc243dd3251785facd58b332921723b488fae533
parentbdfa1fcbae4ce41ecfc92ab0a04a0262875b1730 (diff)
downloadimv-eb60fefc3b7e9b5367bca9d3b5e5d4e50f5b72a7.tar.gz
Add HEIF support
Support the HEIF format using libheif.
-rw-r--r--.builds/archlinux.yml1
-rw-r--r--.builds/debian.yml1
-rw-r--r--.builds/fedora.yml5
-rw-r--r--.builds/freebsd.yml1
-rw-r--r--.builds/ubuntu.yml1
-rw-r--r--AUTHORS1
-rw-r--r--meson.build1
-rw-r--r--meson_options.txt8
-rw-r--r--src/backend_libheif.c119
-rw-r--r--src/main.c5
10 files changed, 141 insertions, 2 deletions
diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml
index 4038414..4ba7b83 100644
--- a/.builds/archlinux.yml
+++ b/.builds/archlinux.yml
@@ -7,6 +7,7 @@ packages:
- glu
- icu
- libglvnd
+ - libheif
- libjpeg-turbo
- libnsgif
- libpng
diff --git a/.builds/debian.yml b/.builds/debian.yml
index 08bc065..b86a6ab 100644
--- a/.builds/debian.yml
+++ b/.builds/debian.yml
@@ -6,6 +6,7 @@ packages:
- libegl1-mesa-dev
- libfreeimage-dev
- libglu-dev
+ - libheif-dev
- libicu-dev
- libpango1.0-dev
- libpng-dev
diff --git a/.builds/fedora.yml b/.builds/fedora.yml
index 7e275ed..b4ea167 100644
--- a/.builds/fedora.yml
+++ b/.builds/fedora.yml
@@ -22,10 +22,11 @@ packages:
sources:
- https://git.sr.ht/~exec64/imv
tasks:
+ # libheif ins't packaged by fedora
# libnsgif isn't packaged by fedora
- gcc: |
- CC=gcc meson imv build_gcc -D auto_features=enabled -D libnsgif=disabled
+ CC=gcc meson imv build_gcc -D auto_features=enabled -D libheif=disabled -D libnsgif=disabled
CC=gcc ninja -C build_gcc test
- clang: |
- CC=clang meson imv build_clang -D auto_features=enabled -D libnsgif=disabled
+ CC=clang meson imv build_clang -D auto_features=enabled -D libheif=disabled -D libnsgif=disabled
CC=clang ninja -C build_clang test
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
index 97193d7..ddabea2 100644
--- a/.builds/freebsd.yml
+++ b/.builds/freebsd.yml
@@ -5,6 +5,7 @@ packages:
- devel/pkgconf
- graphics/freeimage
- graphics/libGLU
+ - graphics/libheif
- graphics/libjpeg-turbo
- graphics/libnsgif
- graphics/librsvg2
diff --git a/.builds/ubuntu.yml b/.builds/ubuntu.yml
index cc35286..3070596 100644
--- a/.builds/ubuntu.yml
+++ b/.builds/ubuntu.yml
@@ -6,6 +6,7 @@ packages:
- libegl1-mesa-dev
- libfreeimage-dev
- libglu-dev
+ - libheif-dev
- libicu-dev
- libpango1.0-dev
- libpng-dev
diff --git a/AUTHORS b/AUTHORS
index 385dba0..571ed3d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,6 +2,7 @@ Author and maintainer of imv:
* Harry Jeffery <harry@exec64.co.uk>
People who have contributed to imv:
+ * Carlo Abelli
* Guillaume Brogi
* Dmitrij D. Czarkoff
* Jose Diez
diff --git a/meson.build b/meson.build
index f7c1263..648b7d1 100644
--- a/meson.build
+++ b/meson.build
@@ -107,6 +107,7 @@ foreach backend : [
['libjpeg', 'dependency', 'libturbojpeg', []],
['librsvg', 'dependency', 'librsvg-2.0', '>= 2.44'],
['libnsgif', 'dependency', 'libnsgif', []],
+ ['libheif', 'dependency', 'libheif', []],
]
_backend_name = backend[0]
_dep_type = backend[1]
diff --git a/meson_options.txt b/meson_options.txt
index 18159dc..f7ecd79 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -57,3 +57,11 @@ option('libnsgif',
type : 'feature',
description : 'provides: animated gif'
)
+
+# libheif http://www.libheif.org
+# depends: none
+# license: LGPL
+option('libheif',
+ type : 'feature',
+ description : 'provides: heif'
+)
diff --git a/src/backend_libheif.c b/src/backend_libheif.c
new file mode 100644
index 0000000..8264e87
--- /dev/null
+++ b/src/backend_libheif.c
@@ -0,0 +1,119 @@
+#include <stdlib.h>
+#include <string.h>
+#include <libheif/heif.h>
+
+#include "backend.h"
+#include "bitmap.h"
+#include "image.h"
+#include "source_private.h"
+
+struct private {
+ struct heif_image *img;
+};
+
+static void free_private(void *raw_private)
+{
+ if (!raw_private) {
+ return;
+ }
+ struct private *private = raw_private;
+ heif_image_release(private->img);
+ free(private);
+}
+
+static void load_image(void *raw_private, struct imv_image **image, int *frametime)
+{
+ *image = NULL;
+ *frametime = 0;
+
+ struct private *private = raw_private;
+
+ int stride;
+ const uint8_t *data = heif_image_get_plane_readonly(private->img, heif_channel_interleaved, &stride);
+
+ int width = heif_image_get_width(private->img, heif_channel_interleaved);
+ int height = heif_image_get_height(private->img, heif_channel_interleaved);
+ unsigned char *bitmap = malloc(width * height * 4);
+ memcpy(bitmap, data, width * height * 4);
+
+ struct imv_bitmap *bmp = malloc(sizeof *bmp);
+ bmp->width = width,
+ bmp->height = height,
+ bmp->format = IMV_ABGR;
+ bmp->data = bitmap;
+ *image = imv_image_create_from_bitmap(bmp);
+}
+
+static const struct imv_source_vtable vtable = {
+ .load_first_frame = load_image,
+ .free = free_private,
+};
+
+struct heif_error get_primary_image(struct heif_context *ctx, struct heif_image **img)
+{
+ struct heif_image_handle *handle;
+ struct heif_error err = heif_context_get_primary_image_handle(ctx, &handle);
+ if (err.code != heif_error_Ok) {
+ return err;
+ }
+
+ err = heif_decode_image(handle, img, heif_colorspace_RGB, heif_chroma_interleaved_RGBA, NULL);
+ heif_image_handle_release(handle);
+ return err;
+}
+
+static enum backend_result open_path(const char *path, struct imv_source **src)
+{
+ struct heif_context *ctx = heif_context_alloc();
+ struct heif_error err = heif_context_read_from_file(ctx, path, NULL); // TODO: error
+ if (err.code != heif_error_Ok) {
+ heif_context_free(ctx);
+ if (err.code == heif_error_Input_does_not_exist) {
+ return BACKEND_BAD_PATH;
+ }
+ return BACKEND_UNSUPPORTED;
+ }
+
+ struct heif_image *img;
+ err = get_primary_image(ctx, &img);
+ heif_context_free(ctx);
+ if (err.code != heif_error_Ok) {
+ return BACKEND_UNSUPPORTED;
+ }
+
+ struct private *private = malloc(sizeof *private);
+ private->img = img;
+ *src = imv_source_create(&vtable, private);
+ return BACKEND_SUCCESS;
+}
+
+static enum backend_result open_memory(void *data, size_t len, struct imv_source **src)
+{
+ struct heif_context *ctx = heif_context_alloc();
+ struct heif_error err = heif_context_read_from_memory_without_copy(ctx, data, len, NULL);
+ if (err.code != heif_error_Ok) {
+ heif_context_free(ctx);
+ return BACKEND_UNSUPPORTED;
+ }
+
+ struct heif_image *img;
+ err = get_primary_image(ctx, &img);
+ heif_context_free(ctx);
+ if (err.code != heif_error_Ok) {
+ return BACKEND_UNSUPPORTED;
+ }
+
+ struct private *private = malloc(sizeof *private);
+ private->img = img;
+ *src = imv_source_create(&vtable, private);
+ return BACKEND_SUCCESS;
+}
+
+const struct imv_backend imv_backend_libheif = {
+ .name = "libheif",
+ .description = "ISO/IEC 23008-12:2017 HEIF file format decoder and encoder.",
+ .website = "http://www.libheif.org",
+ .license = "GNU Lesser General Public License",
+ .open_path = &open_path,
+ .open_memory = &open_memory,
+};
diff --git a/src/main.c b/src/main.c
index cb0db83..1e11f07 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,6 +8,7 @@ extern const struct imv_backend imv_backend_librsvg;
extern const struct imv_backend imv_backend_libtiff;
extern const struct imv_backend imv_backend_libjpeg;
extern const struct imv_backend imv_backend_libnsgif;
+extern const struct imv_backend imv_backend_libheif;
int main(int argc, char **argv)
{
@@ -41,6 +42,10 @@ int main(int argc, char **argv)
imv_install_backend(imv, &imv_backend_freeimage);
#endif
+#ifdef IMV_BACKEND_LIBHEIF
+ imv_install_backend(imv, &imv_backend_libheif);
+#endif
+
if (!imv_load_config(imv)) {
imv_free(imv);
return 1;