From 115f9840c030daeaaf7a5095b00b874a3c737efb Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Wed, 3 Jul 2019 13:50:48 +0100 Subject: [PATCH] Fix #610: Support heic image format https://github.com/BestImageViewer/geeqie/issues/610 Primary image only displayed --- configure.ac | 26 +++ .../GuideReferenceSupportedFormats.xml | 2 +- src/Makefile.am | 9 +- src/filefilter.c | 2 + src/icons/Makefile.am | 6 +- src/icons/icon_heic.png | Bin 0 -> 32245 bytes src/image-load.c | 9 + src/image.c | 3 + src/image_load_heif.c | 168 ++++++++++++++++++ src/image_load_heif.h | 29 +++ src/pixbuf_util.c | 4 + src/pixbuf_util.h | 1 + src/preferences.c | 3 +- src/remote.c | 3 + src/search.c | 6 + src/thumb.c | 2 +- src/thumb_standard.c | 2 +- src/typedefs.h | 1 + web/geeqie-install-debian.sh | 8 +- 19 files changed, 271 insertions(+), 13 deletions(-) create mode 100644 src/icons/icon_heic.png create mode 100644 src/image_load_heif.c create mode 100644 src/image_load_heif.h diff --git a/configure.ac b/configure.ac index 99b3e2d1..4a14918f 100644 --- a/configure.ac +++ b/configure.ac @@ -576,6 +576,31 @@ AM_CONDITIONAL(HAVE_PDF, [test "x$HAVE_PDF" = xyes]) AC_SUBST(PDF_CFLAGS) AC_SUBST(PDF_LIBS) +# Heif support +# ---------------------------------------------------------------------- + +AC_ARG_ENABLE([heif], + AC_HELP_STRING([--disable-heif], [disable heif support]), + [libheif=$enableval], [libheif=auto]) + +if test "x${libheif}" != "xno"; then + PKG_CHECK_MODULES(HEIF, libheif >= 1.3.2, + [ + HAVE_HEIF=yes + AC_DEFINE(HAVE_HEIF, 1, [define to enable heif support]) + ], + [ + HAVE_HEIF=no + AC_MSG_WARN([$HEIF_PKG_ERRORS]) + ]) +else + HAVE_HEIF=disabled +fi + +AM_CONDITIONAL(HAVE_HEIF, [test "x$HAVE_HEIF" = xyes]) +AC_SUBST(HEIF_CFLAGS) +AC_SUBST(HEIF_LIBS) + # Markdown support # ---------------------------------------------------------------------- @@ -681,6 +706,7 @@ Support: Lua: $HAVE_LUA FFmpegthumbnailer: $HAVE_FFMPEGTHUMBNAILER Pdf: $HAVE_PDF + Heif: $HAVE_HEIF Documentation: Doxygen: $DX_DOXYGEN diff --git a/doc/docbook/GuideReferenceSupportedFormats.xml b/doc/docbook/GuideReferenceSupportedFormats.xml index 6500868b..8d93f6c2 100644 --- a/doc/docbook/GuideReferenceSupportedFormats.xml +++ b/doc/docbook/GuideReferenceSupportedFormats.xml @@ -1,7 +1,7 @@
Supported File Formats - 3FR, ANI, APM, ARW, BMP, CR2, CRW, CUR, DDS, DNG, ERF, GIF, ICNS, ICO, JPE/JPEG/JPG, JPS, KDC, MEF, MPO, MOS, MRW, NEF, ORF, PEF, PTX, PBM/PGM/PNM/PPM, PNG, QIF/QTIF (QuickTime Image Format), RAF, RAW, RW2, SR2, SRF, SVG/SVGZ, TGA/TARGA, TIF/TIFF, WMF, XBM, XPM. Animated GIFs are supported. + 3FR, ANI, APM, ARW, BMP, CR2, CRW, CUR, DDS, DNG, ERF, GIF, ICNS, ICO, JPE/JPEG/JPG, JPS, KDC, MEF, MPO, MOS, MRW, NEF, ORF, PEF, PTX, PBM/PGM/PNM/PPM, PNG, QIF/QTIF (QuickTime Image Format), RAF, RAW, RW2, SR2, SRF, SVG/SVGZ, TGA/TARGA, TIF/TIFF, WMF, XBM, XPM, HEIF (primary image only). Animated GIFs are supported. Refer to diff --git a/src/Makefile.am b/src/Makefile.am index f5d88844..38a7e935 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,6 +12,7 @@ AM_CFLAGS = \ $(CLUTTER_GTK_CFLAGS) \ $(FFMPEGTHUMBNAILER_CFLAGS) \ $(PDF_CFLAGS) \ + $(HEIF_CFLAGS) \ -I$(top_srcdir) \ -I$(top_builddir) @@ -27,6 +28,7 @@ AM_CXXFLAGS = \ $(CLUTTER_GTK_CFLAGS) \ $(FFMPEGTHUMBNAILER_CFLAGS) \ $(PDF_CFLAGS) \ + $(HEIF_CFLAGS) \ -I$(top_srcdir) \ -I$(top_builddir) @@ -187,6 +189,8 @@ geeqie_SOURCES = \ image_load_collection.h\ image_load_pdf.c\ image_load_pdf.h\ + image_load_heif.c\ + image_load_heif.h\ image_load_ffmpegthumbnailer.c\ image_load_ffmpegthumbnailer.h\ image-overlay.c \ @@ -276,7 +280,7 @@ geeqie_SOURCES = \ zonedetect.c \ zonedetect.h -geeqie_LDADD = $(GTK_LIBS) $(GLIB_LIBS) $(INTLLIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LCMS_LIBS) $(EXIV2_LIBS) $(LIBCHAMPLAIN_LIBS) $(LIBCHAMPLAIN_GTK_LIBS) $(LUA_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(FFMPEGTHUMBNAILER_LIBS) $(PDF_LIBS) +geeqie_LDADD = $(GTK_LIBS) $(GLIB_LIBS) $(INTLLIBS) $(JPEG_LIBS) $(TIFF_LIBS) $(LCMS_LIBS) $(EXIV2_LIBS) $(LIBCHAMPLAIN_LIBS) $(LIBCHAMPLAIN_GTK_LIBS) $(LUA_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(FFMPEGTHUMBNAILER_LIBS) $(PDF_LIBS) $(HEIF_LIBS) EXTRA_DIST = \ $(extra_SLIK) @@ -286,6 +290,3 @@ gq-marshal.h: gq-marshal.list gq-marshal.c: gq-marshal.list gq-marshal.h (echo "#include \"gq-marshal.h\"" ; $(GLIB_GENMARSHAL) --prefix=gq_marshal $(srcdir)/gq-marshal.list --body ) >$@ - - - diff --git a/src/filefilter.c b/src/filefilter.c index 5410f778..a7f7ff23 100644 --- a/src/filefilter.c +++ b/src/filefilter.c @@ -292,6 +292,7 @@ void filter_add_defaults(void) /* other supported formats */ filter_add_if_missing("dds", "DirectDraw Surface", ".dds", FORMAT_CLASS_IMAGE, FALSE, FALSE, TRUE); filter_add_if_missing("pdf", "Portable Document Format", ".pdf", FORMAT_CLASS_PDF, FALSE, FALSE, TRUE); + filter_add_if_missing("HEIF", "HEIF Format", ".heic", FORMAT_CLASS_HEIF, FALSE, FALSE, TRUE); } GList *filter_to_list(const gchar *extensions) @@ -472,6 +473,7 @@ FileFormatClass filter_file_get_class(const gchar *name) if (filter_file_class(name, FORMAT_CLASS_VIDEO)) return FORMAT_CLASS_VIDEO; if (filter_file_class(name, FORMAT_CLASS_COLLECTION)) return FORMAT_CLASS_COLLECTION; if (filter_file_class(name, FORMAT_CLASS_PDF)) return FORMAT_CLASS_PDF; + if (filter_file_class(name, FORMAT_CLASS_HEIF)) return FORMAT_CLASS_HEIF; return FORMAT_CLASS_UNKNOWN; } diff --git a/src/icons/Makefile.am b/src/icons/Makefile.am index 82e4c5cc..d859b60c 100644 --- a/src/icons/Makefile.am +++ b/src/icons/Makefile.am @@ -47,7 +47,8 @@ ICONS_INLINE = \ icon_mirror.png \ icon_flip.png \ icon_original.png \ - icon_trash.png + icon_trash.png \ + icon_heic.png ICONS_INLINE_PAIRS = \ folder_closed $(srcdir)/folder_closed.png \ @@ -93,7 +94,8 @@ ICONS_INLINE_PAIRS = \ icon_mirror $(srcdir)/icon_mirror.png \ icon_flip $(srcdir)/icon_flip.png \ icon_original $(srcdir)/icon_original.png \ - icon_trash $(srcdir)/icon_trash.png + icon_trash $(srcdir)/icon_trash.png \ + icon_heic $(srcdir)/icon_heic.png icons_inline.h: $(ICONS_INLINE) Makefile.in @sh -ec "echo '/* Auto generated file, do not edit */'; echo; \ diff --git a/src/icons/icon_heic.png b/src/icons/icon_heic.png new file mode 100644 index 0000000000000000000000000000000000000000..c562f7fa542c4ae3cbe708b5353b289467dc1790 GIT binary patch literal 32245 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

pKw=zo7!v{MKe7z4e(dZ1F zuI~rhU2K}(=>625|p0wmwQt>eo5s^5Pu8m%2xOh_YG(qPzH z4JRdGTpEfbNG?H#&;%Knyc?d$CWLCLSb+A+HlZ?rwr}E*?yAMheNyWeH|xAxpYKNw z&py7~PanThtzhMK8vDteU&}=vpharF8zu>c{E$r9^VbbechL+iHcS_zCp7=SpC$@6 zAi;yWP1ouX0+}z+S0z*GhMIjBJM7Ifefe<)-NWFX=isd$mKm&tu6LqosYfZu4OV?% ziOF!a-6ecuIr1p!c=xN(DJ(&A5|{t=`|ku$l~+G2MJwY(b+JL9lPfDekwRV2OIx2V z{qIUthl;yelJS@v5pZFq5o+gQ(_)?30w}<^wzqlg&kE`TEBblic-q?khp$+E@}1?$uM3X#gOkEzQ5TO#}y|X9Xx%_D94!NJAFsj(X%odoKs?WvpXFX?mNe; z!lQlFe}V!6uFZKil(;W$?HR|sY{^2^@&Y|A23NOEvlo07u3(TN3 z+VSQFz0d;oGRrVc#V*JPo}ceTQ=s|k00ea+7ZYtfQ-ZuSsa$K?{@WLZ;SNo}!^$Tq-_>@+Qo_m{)~|agil?&zBSsy1bVf_=em=`JF_otpPG&*5E$z$5N z>E%NQUQ%ok&kfM|U7ON$b0rGCG$F{mUY`((9OK)0FP1s~>kuX)QfxH%a|mHsAESxK zv*+Vhx)s=hpp5+`HnF~*f|{apsnvb6C0p!lP|X+H&fBY+g5mdrG9@a1h1D*b`hu&4 zBPwElWR2ene%qy=G{lK$*?ayz9AWVa5JH$%V#8UY>GM3TrnXYIA6DwcXy-RT6u8~% zuKH6w=u)0CxE1~PS=Z?B6W>SDxR*om_8*&N2oYcacF;kzuz-Lx>93dRIDk57pKS

th4jJ70kWc(!gkN&5xUdlQ>(S8&kNkA0#sCox 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 literal 0 HcmV?d00001 diff --git a/src/image-load.c b/src/image-load.c index 9fc4bdc5..02688dfa 100644 --- a/src/image-load.c +++ b/src/image-load.c @@ -26,6 +26,7 @@ #include "image_load_tiff.h" #include "image_load_dds.h" #include "image_load_pdf.h" +#include "image_load_heif.h" #include "image_load_ffmpegthumbnailer.h" #include "image_load_collection.h" @@ -627,6 +628,14 @@ static void image_loader_setup_loader(ImageLoader *il) } else #endif +#ifdef HAVE_HEIF + if (il->fd->format_class == FORMAT_CLASS_HEIF) + { + DEBUG_1("Using custom heif loader"); + image_loader_backend_set_heif(&il->backend); + } + else +#endif #ifdef HAVE_JPEG if (il->bytes_total >= 2 && il->mapped_file[0] == 0xff && il->mapped_file[1] == 0xd8) { diff --git a/src/image.c b/src/image.c index 57670abb..aa74327d 100644 --- a/src/image.c +++ b/src/image.c @@ -862,6 +862,9 @@ static void image_load_done_cb(ImageLoader *il, gpointer data) case FORMAT_CLASS_PDF: pixbuf = pixbuf_inline(PIXBUF_INLINE_ICON_PDF); break; + case FORMAT_CLASS_HEIF: + pixbuf = pixbuf_inline(PIXBUF_INLINE_ICON_HEIF); + break; default: pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN); } diff --git a/src/image_load_heif.c b/src/image_load_heif.c new file mode 100644 index 00000000..ae144066 --- /dev/null +++ b/src/image_load_heif.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 20019 - The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "main.h" + +#include "image-load.h" +#include "image_load_heif.h" + +#ifdef HAVE_HEIF +#include + +typedef struct _ImageLoaderHEIF ImageLoaderHEIF; +struct _ImageLoaderHEIF { + ImageLoaderBackendCbAreaUpdated area_updated_cb; + ImageLoaderBackendCbSize size_cb; + ImageLoaderBackendCbAreaPrepared area_prepared_cb; + gpointer data; + GdkPixbuf *pixbuf; + guint requested_width; + guint requested_height; + gboolean abort; +}; + +static void free_buffer(guchar *pixels, gpointer data) +{ + g_free (pixels); +} + +static gboolean image_loader_heif_load(gpointer loader, const guchar *buf, gsize count, GError **error) +{ + ImageLoaderHEIF *ld = (ImageLoaderHEIF *) loader; + struct heif_context* ctx; + struct heif_image* img; + struct heif_error error_code; + struct heif_image_handle* handle; + guint8* data; + gint width, height; + gint stride; + gboolean alpha; + + ctx = heif_context_alloc(); + + error_code = heif_context_read_from_memory_without_copy(ctx, buf, count, NULL); + if (error_code.code) + { + log_printf("warning: heif reader error: %s\n", error_code.message); + heif_context_free(ctx); + return FALSE; + } + + // get a handle to the primary image + error_code = heif_context_get_primary_image_handle(ctx, &handle); + if (error_code.code) + { + log_printf("warning: heif reader error: %s\n", error_code.message); + heif_context_free(ctx); + return FALSE; + } + + // 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, NULL); + if (error_code.code) + { + log_printf("warning: heif reader error: %s\n", error_code.message); + heif_context_free(ctx); + return FALSE; + } + + data = 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); + + ld->pixbuf = gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, alpha, 8, width, height, stride, free_buffer, NULL); + + ld->area_updated_cb(loader, 0, 0, width, height, ld->data); + + heif_context_free(ctx); + + return TRUE; +} + +static gpointer image_loader_heif_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data) +{ + ImageLoaderHEIF *loader = g_new0(ImageLoaderHEIF, 1); + loader->area_updated_cb = area_updated_cb; + loader->size_cb = size_cb; + loader->area_prepared_cb = area_prepared_cb; + loader->data = data; + return (gpointer) loader; +} + +static void image_loader_heif_set_size(gpointer loader, int width, int height) +{ + ImageLoaderHEIF *ld = (ImageLoaderHEIF *) loader; + ld->requested_width = width; + ld->requested_height = height; +} + +static GdkPixbuf* image_loader_heif_get_pixbuf(gpointer loader) +{ + ImageLoaderHEIF *ld = (ImageLoaderHEIF *) loader; + return ld->pixbuf; +} + +static gchar* image_loader_heif_get_format_name(gpointer loader) +{ + return g_strdup("heif"); +} + +static gchar** image_loader_heif_get_format_mime_types(gpointer loader) +{ + static gchar *mime[] = {"image/heic", NULL}; + return g_strdupv(mime); +} + +static gboolean image_loader_heif_close(gpointer loader, GError **error) +{ + return TRUE; +} + +static void image_loader_heif_abort(gpointer loader) +{ + ImageLoaderHEIF *ld = (ImageLoaderHEIF *) loader; + ld->abort = TRUE; +} + +static void image_loader_heif_free(gpointer loader) +{ + ImageLoaderHEIF *ld = (ImageLoaderHEIF *) loader; + if (ld->pixbuf) g_object_unref(ld->pixbuf); + g_free(ld); +} + +void image_loader_backend_set_heif(ImageLoaderBackend *funcs) +{ + funcs->loader_new = image_loader_heif_new; + funcs->set_size = image_loader_heif_set_size; + funcs->load = image_loader_heif_load; + funcs->write = NULL; + funcs->get_pixbuf = image_loader_heif_get_pixbuf; + funcs->close = image_loader_heif_close; + funcs->abort = image_loader_heif_abort; + funcs->free = image_loader_heif_free; + funcs->get_format_name = image_loader_heif_get_format_name; + funcs->get_format_mime_types = image_loader_heif_get_format_mime_types; +} + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/image_load_heif.h b/src/image_load_heif.h new file mode 100644 index 00000000..63378173 --- /dev/null +++ b/src/image_load_heif.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 20019 - The Geeqie Team + * + * Author: Colin Clark + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef IMAGE_LOAD_HEIF_H +#define IMAGE_LOAD_HEIF_H + +#ifdef HAVE_HEIF +void image_loader_backend_set_heif(ImageLoaderBackend *funcs); +#endif + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/pixbuf_util.c b/src/pixbuf_util.c index f2a44a02..35c9cdf4 100644 --- a/src/pixbuf_util.c +++ b/src/pixbuf_util.c @@ -146,6 +146,7 @@ static PixbufInline inline_pixbuf_data[] = { { PIXBUF_INLINE_ICON_FLIP, icon_flip }, { PIXBUF_INLINE_ICON_ORIGINAL, icon_original }, { PIXBUF_INLINE_ICON_TRASH, icon_trash }, + { PIXBUF_INLINE_ICON_HEIF, icon_heic }, { NULL, NULL } }; @@ -296,6 +297,9 @@ GdkPixbuf *pixbuf_fallback(FileData *fd, gint requested_width, gint requested_he case FORMAT_CLASS_PDF: pixbuf = pixbuf_inline(PIXBUF_INLINE_ICON_PDF); break; + case FORMAT_CLASS_HEIF: + pixbuf = pixbuf_inline(PIXBUF_INLINE_ICON_HEIF); + break; default: pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN); } diff --git a/src/pixbuf_util.h b/src/pixbuf_util.h index eb7df097..901d4065 100644 --- a/src/pixbuf_util.h +++ b/src/pixbuf_util.h @@ -74,6 +74,7 @@ gboolean pixbuf_scale_aspect(gint req_w, gint req_h, gint old_w, gint old_h, gin #define PIXBUF_INLINE_ICON_SELECT_RECTANGLE "icon_select_rectangle" #define PIXBUF_INLINE_ICON_FILE_FILTER "icon_file_filter" #define PIXBUF_INLINE_ICON_TRASH "icon_trash" +#define PIXBUF_INLINE_ICON_HEIF "icon_heic" #define PIXBUF_INLINE_ICON_CW "icon_rotate_clockwise" #define PIXBUF_INLINE_ICON_CCW "icon_rotate_counter_clockwise" diff --git a/src/preferences.c b/src/preferences.c index 5d6db5dc..3b33b578 100644 --- a/src/preferences.c +++ b/src/preferences.c @@ -117,7 +117,8 @@ gchar *format_class_list[] = { N_("Metadata"), N_("Video"), N_("Collection"), - N_("Pdf") + N_("Pdf"), + N_("HEIF") }; /* config memory values */ diff --git a/src/remote.c b/src/remote.c index b5435444..76a7d529 100644 --- a/src/remote.c +++ b/src/remote.c @@ -855,6 +855,9 @@ static void get_filelist(const gchar *text, GIOChannel *channel, gboolean recurs case FORMAT_CLASS_PDF: out_string = g_string_append(out_string, " Class: PDF"); break; + case FORMAT_CLASS_HEIF: + out_string = g_string_append(out_string, " Class: HEIF"); + break; case FORMAT_CLASS_UNKNOWN: out_string = g_string_append(out_string, " Class: Unknown"); break; diff --git a/src/search.c b/src/search.c index 575b5573..3437b6d2 100644 --- a/src/search.c +++ b/src/search.c @@ -2184,6 +2184,11 @@ static gboolean search_file_next(SearchData *sd) { search_class = FORMAT_CLASS_RAWIMAGE; } + else if (g_strcmp0(gtk_combo_box_text_get_active_text( + GTK_COMBO_BOX_TEXT(sd->class_type)), _("HEIF")) == 0) + { + search_class = FORMAT_CLASS_HEIF; + } else if (g_strcmp0(gtk_combo_box_text_get_active_text( GTK_COMBO_BOX_TEXT(sd->class_type)), _("Video")) == 0) { @@ -3369,6 +3374,7 @@ void search_new(FileData *dir_fd, FileData *example_file) sd->class_type = gtk_combo_box_text_new(); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Image")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Raw Image")); + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("HEIF")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Video")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Metadata")); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(sd->class_type), _("Unknown")); diff --git a/src/thumb.c b/src/thumb.c index bf18c60b..c249569d 100644 --- a/src/thumb.c +++ b/src/thumb.c @@ -337,7 +337,7 @@ gboolean thumb_loader_start(ThumbLoader *tl, FileData *fd) if (!tl->fd) tl->fd = file_data_ref(fd); - if (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_PDF && !options->file_filter.disable) + if (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_PDF && tl->fd->format_class != FORMAT_CLASS_HEIF && !options->file_filter.disable) { thumb_loader_set_fallback(tl); return FALSE; diff --git a/src/thumb_standard.c b/src/thumb_standard.c index f21906b6..ff2d02d1 100644 --- a/src/thumb_standard.c +++ b/src/thumb_standard.c @@ -667,7 +667,7 @@ gboolean thumb_loader_std_start(ThumbLoaderStd *tl, FileData *fd) tl->fd = file_data_ref(fd); - if (!stat_utf8(fd->path, &st) || (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_PDF && !options->file_filter.disable)) + if (!stat_utf8(fd->path, &st) || (tl->fd->format_class != FORMAT_CLASS_IMAGE && tl->fd->format_class != FORMAT_CLASS_RAWIMAGE && tl->fd->format_class != FORMAT_CLASS_VIDEO && tl->fd->format_class != FORMAT_CLASS_COLLECTION && tl->fd->format_class != FORMAT_CLASS_PDF && tl->fd->format_class != FORMAT_CLASS_HEIF && !options->file_filter.disable)) { thumb_loader_std_set_fallback(tl); return FALSE; diff --git a/src/typedefs.h b/src/typedefs.h index b31ca33a..8b94a456 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -145,6 +145,7 @@ typedef enum { FORMAT_CLASS_VIDEO, FORMAT_CLASS_COLLECTION, FORMAT_CLASS_PDF, + FORMAT_CLASS_HEIF, FILE_FORMAT_CLASSES } FileFormatClass; diff --git a/web/geeqie-install-debian.sh b/web/geeqie-install-debian.sh index db4d982a..d72896a6 100755 --- a/web/geeqie-install-debian.sh +++ b/web/geeqie-install-debian.sh @@ -1,5 +1,5 @@ #!/bin/bash -version="2018-10-23" +version="2019-07-03" description=$' Geeqie is an image viewer. This script will download, compile, and install Geeqie on Debian-based systems. @@ -39,9 +39,9 @@ optional_array=( "libffmpegthumbnailer-dev" "libtiff (for tiff support)" "libtiff-dev" -"libjpeg (for jpeg support" +"libjpeg (for jpeg support)" "libjpeg-dev" -"librsvg2 (for viewing .svg images" +"librsvg2 (for viewing .svg images)" "librsvg2-common" "libwmf (for viewing .wmf images)" "libwmf0.2-7-gtk" @@ -61,6 +61,8 @@ optional_array=( "gphoto2" "libimage-exiftool-perl (for jpeg extraction plugin)" "libimage-exiftool-perl" +"libheif (for HEIF support)" +"libheif-dev" ) # Optional for GTK3 only -- 2.20.1