# HG changeset patch # User Matti Hamalainen # Date 1544644968 -7200 # Node ID 550b482f7bd591330ce9591d56a2e20ec3a213a6 # Parent 0db2b9c1c9539a2efe3f38522d492c6324197f0b# Parent 6a16ed6742bea8a66f22445be154648f0df5c4c5 Merge. diff -r 6a16ed6742be -r 550b482f7bd5 configure.ac --- a/configure.ac Tue Dec 11 11:46:00 2018 +0000 +++ b/configure.ac Wed Dec 12 22:02:48 2018 +0200 @@ -393,6 +393,37 @@ AC_SUBST(FFMPEGTHUMBNAILER_CFLAGS) AC_SUBST(FFMPEGTHUMBNAILER_LIBS) +# libbpg support +# ---------------------------------------------------------------------- + +AC_ARG_ENABLE([bpg], + AS_HELP_STRING([--disable-bpg],[disable direct bpg support]), + [libbpg=$enableval], [libbpg=auto]) + +if test "x${libbpg}" = "xyes"; then + HAVE_BPG=yes + BPG_LIBS=/usr/local/lib/libbpg.a + BPG_CFLAGS=-I/usr/local/include/ + AC_DEFINE(HAVE_BPG, 1, [define to enable use of BPG loader]) +elif test "x${libbpg}" != "xno"; then + AC_CHECK_LIB(bpg, bpg_decoder_open, + [ + HAVE_BPG=yes + BPG_LIBS=-lbpg + AC_DEFINE(HAVE_BPG, 1, [define to enable use of BPG loader]) + ], + [ + HAVE_BPG=no + ]) +else + HAVE_BPG=disabled +fi + +AM_CONDITIONAL(HAVE_BPG, [test "x$HAVE_BPG" = xyes]) +AC_SUBST(BPG_CFLAGS) +AC_SUBST(BPG_LIBS) + + # Exiv2 support # ---------------------------------------------------------------------- @@ -672,6 +703,7 @@ Libchamplain: $HAVE_LIBCHAMPLAIN Libchamplain-gtk: $HAVE_LIBCHAMPLAIN_GTK Lua: $HAVE_LUA + Use libBPG: $HAVE_BPG FFmpegthumbnailer: $HAVE_FFMPEGTHUMBNAILER Pdf: $HAVE_PDF diff -r 6a16ed6742be -r 550b482f7bd5 src/Makefile.am --- a/src/Makefile.am Tue Dec 11 11:46:00 2018 +0000 +++ b/src/Makefile.am Wed Dec 12 22:02:48 2018 +0200 @@ -181,6 +181,8 @@ image_load_jpeg.h\ image_load_tiff.c\ image_load_tiff.h\ + image_load_bpg.c\ + image_load_bpg.h\ image_load_dds.c\ image_load_dds.h\ image_load_collection.c\ @@ -276,7 +278,7 @@ 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) $(BPG_LIBS) $(LCMS_LIBS) $(EXIV2_LIBS) $(LIBCHAMPLAIN_LIBS) $(LIBCHAMPLAIN_GTK_LIBS) $(LUA_LIBS) $(CLUTTER_LIBS) $(CLUTTER_GTK_LIBS) $(FFMPEGTHUMBNAILER_LIBS) $(PDF_LIBS) EXTRA_DIST = \ $(extra_SLIK) diff -r 6a16ed6742be -r 550b482f7bd5 src/editors.c --- a/src/editors.c Tue Dec 11 11:46:00 2018 +0000 +++ b/src/editors.c Wed Dec 12 22:02:48 2018 +0200 @@ -113,6 +113,7 @@ {"image/gif", ".gif"}, {"image/jpeg", ".jpeg;.jpg;.mpo"}, {"image/jpg", ".jpg;.jpeg"}, + {"image/bpg", ".bpg"}, {"image/pcx", ".pcx"}, {"image/png", ".png"}, {"image/svg", ".svg"}, diff -r 6a16ed6742be -r 550b482f7bd5 src/filefilter.c --- a/src/filefilter.c Tue Dec 11 11:46:00 2018 +0000 +++ b/src/filefilter.c Wed Dec 12 22:02:48 2018 +0200 @@ -237,6 +237,9 @@ /* add defaults even if gdk-pixbuf does not have them, but disabled */ filter_add_if_missing("jpeg", "JPEG group", ".jpg;.jpeg;.jpe", FORMAT_CLASS_IMAGE, TRUE, FALSE, FALSE); filter_add_if_missing("png", "Portable Network Graphic", ".png", FORMAT_CLASS_IMAGE, TRUE, FALSE, FALSE); +#ifdef HAVE_BPG + filter_add_if_missing("bpg", "Better Portable Graphics", ".bpg", FORMAT_CLASS_IMAGE, TRUE, FALSE, FALSE); +#endif filter_add_if_missing("tiff", "Tiff", ".tif;.tiff", FORMAT_CLASS_IMAGE, TRUE, FALSE, FALSE); filter_add_if_missing("pnm", "Packed Pixel formats", ".pbm;.pgm;.pnm;.ppm", FORMAT_CLASS_IMAGE, TRUE, FALSE, FALSE); filter_add_if_missing("gif", "Graphics Interchange Format", ".gif", FORMAT_CLASS_IMAGE, TRUE, FALSE, FALSE); diff -r 6a16ed6742be -r 550b482f7bd5 src/image-load.c --- a/src/image-load.c Tue Dec 11 11:46:00 2018 +0000 +++ b/src/image-load.c Wed Dec 12 22:02:48 2018 +0200 @@ -24,6 +24,7 @@ #include "image_load_gdk.h" #include "image_load_jpeg.h" #include "image_load_tiff.h" +#include "image_load_bpg.h" #include "image_load_dds.h" #include "image_load_pdf.h" #include "image_load_ffmpegthumbnailer.h" @@ -647,6 +648,16 @@ } else #endif +#ifdef HAVE_BPG + if (il->bytes_total >= 10 && + (memcmp(il->mapped_file, "BPG\xfb", 4) == 0 || + memcmp(il->mapped_file, "BPG\xfb", 4) == 0)) + { + DEBUG_1("Using custom BPG loader"); + image_loader_backend_set_bpg(&il->backend); + } + else +#endif if (il->bytes_total >= 3 && il->mapped_file[0] == 0x44 && il->mapped_file[1] == 0x44 && il->mapped_file[2] == 0x53) { DEBUG_1("Using dds loader"); diff -r 6a16ed6742be -r 550b482f7bd5 src/image_load_bpg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image_load_bpg.c Wed Dec 12 22:02:48 2018 +0200 @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2016 The Geeqie Team + * + * Authors: Matti Hämäläinen + * + * 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_bpg.h" + +#ifdef HAVE_BPG + +#include + + +typedef struct _ImageLoaderBPG ImageLoaderBPG; + +struct _ImageLoaderBPG +{ + 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_bpg_load(gpointer loader, const guchar* buf, gsize count, GError** error) +{ + ImageLoaderBPG* lt = (ImageLoaderBPG*)loader; + BPGDecoderContext *img = bpg_decoder_open(); + BPGImageInfo info_s, *info = &info_s; + guchar *pixels = NULL; + gint rowstride, y, bpp; + gsize bytes; + + if (bpg_decoder_decode(img, buf, count) < 0) + { + DEBUG_1("Failed to open BPG image"); + return FALSE; + } + + bpg_decoder_get_info(img, &info_s); + if (info->width <= 0 || info->height <= 0) + { + DEBUG_1("Width or height of BPG image is zero"); + goto err; + } + + bpp = info->has_alpha ? 4 : 3; + rowstride = info->width * bpp; + if (rowstride / bpp != info->width) + { + DEBUG_1("Dimensions of BPG image too large"); + goto err; + } + + bytes = info->height * rowstride; + if (bytes / rowstride != info->height) + { + DEBUG_1("Dimensions of BPG image too large"); + goto err; + } + + bpg_decoder_start(img, info->has_alpha ? BPG_OUTPUT_FORMAT_RGBA32 : BPG_OUTPUT_FORMAT_RGB24); + + lt->requested_width = info->width; + lt->requested_height = info->height; + lt->size_cb(loader, lt->requested_width, lt->requested_height, lt->data); + + pixels = g_try_malloc(bytes); + if (!pixels) + { + DEBUG_1("Insufficient memory to open BPG file"); + goto err; + } + + lt->pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, info->has_alpha, 8, info->width, info->height, rowstride, free_buffer, NULL); + if (!lt->pixbuf) + { + g_free(pixels); + DEBUG_1("Insufficient memory to open BPG file"); + goto err; + } + + lt->area_prepared_cb(loader, lt->data); + + for (y = 0; y < info->height; y++) + { + if (lt->abort) + break; + + bpg_decoder_get_line(img, pixels + y * info->width * bpp); + + lt->area_updated_cb(loader, 0, y, info->width, 1, lt->data); + } + + bpg_decoder_close(img); + + return TRUE; + +err: + if (img) + bpg_decoder_close(img); + + return FALSE; +} + +static gpointer image_loader_bpg_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, + ImageLoaderBackendCbSize size_cb, + ImageLoaderBackendCbAreaPrepared area_prepared_cb, + gpointer data) +{ + ImageLoaderBPG* loader = g_new0(ImageLoaderBPG, 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_bpg_set_size(gpointer loader, int width, int height) +{ + ImageLoaderBPG* lt = (ImageLoaderBPG*)loader; + lt->requested_width = width; + lt->requested_height = height; +} + +static GdkPixbuf* image_loader_bpg_get_pixbuf(gpointer loader) +{ + ImageLoaderBPG* lt = (ImageLoaderBPG*)loader; + return lt->pixbuf; +} + +static gchar* image_loader_bpg_get_format_name(gpointer loader) +{ + return g_strdup("bpg"); +} + +static gchar** image_loader_bpg_get_format_mime_types(gpointer loader) +{ + static gchar* mime[] = {"image/bpg", NULL}; + return g_strdupv(mime); +} + +static gboolean image_loader_bpg_close(gpointer loader, GError** error) +{ + return TRUE; +} + +static void image_loader_bpg_abort(gpointer loader) +{ + ImageLoaderBPG* lt = (ImageLoaderBPG*)loader; + lt->abort = TRUE; +} + +static void image_loader_bpg_free(gpointer loader) +{ + ImageLoaderBPG* lt = (ImageLoaderBPG*)loader; + if (lt->pixbuf) + g_object_unref(lt->pixbuf); + g_free(lt); +} + +void image_loader_backend_set_bpg(ImageLoaderBackend* funcs) +{ + funcs->loader_new = image_loader_bpg_new; + funcs->set_size = image_loader_bpg_set_size; + funcs->load = image_loader_bpg_load; + funcs->write = NULL; + funcs->get_pixbuf = image_loader_bpg_get_pixbuf; + funcs->close = image_loader_bpg_close; + funcs->abort = image_loader_bpg_abort; + funcs->free = image_loader_bpg_free; + + funcs->get_format_name = image_loader_bpg_get_format_name; + funcs->get_format_mime_types = image_loader_bpg_get_format_mime_types; +} + +#endif +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r 6a16ed6742be -r 550b482f7bd5 src/image_load_bpg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/image_load_bpg.h Wed Dec 12 22:02:48 2018 +0200 @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 The Geeqie Team + * + * Authors: Matti Hämäläinen + * + * 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_BPG_H +#define IMAGE_LOAD_BPG_H + +#ifdef HAVE_BPG +void image_loader_backend_set_bpg(ImageLoaderBackend *funcs); +#endif + +#endif + +/* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */