From c6080e0fd59df9b1fa378c7386f81c81d02e138e Mon Sep 17 00:00:00 2001 From: =?utf8?q?vonasek=C2=A0?= <> Date: Fri, 8 May 2020 16:47:06 +0100 Subject: [PATCH] Fix #344: Ignoring alpha channel https://github.com/BestImageViewer/geeqie/issues/344 --- src/image.c | 5 ++++ src/image.h | 1 + src/layout.c | 2 ++ src/layout_image.c | 8 ++++++ src/layout_image.h | 1 + src/layout_util.c | 15 +++++++++++ src/pixbuf-renderer.c | 9 +++++++ src/pixbuf-renderer.h | 4 +++ src/pixbuf_util.c | 39 +++++++++++++++++++++++++++ src/pixbuf_util.h | 3 ++- src/renderer-tiles.c | 61 +++++++++++++++++++++++++++++++------------ src/toolbar.c | 1 + src/typedefs.h | 1 + 13 files changed, 132 insertions(+), 18 deletions(-) diff --git a/src/image.c b/src/image.c index 522e8bd1..9ca1d2aa 100644 --- a/src/image.c +++ b/src/image.c @@ -686,6 +686,11 @@ gboolean image_get_overunderexposed(ImageWindow *imd) return imd->overunderexposed; } +void image_set_ignore_alpha(ImageWindow *imd, gboolean ignore_alpha) +{ + pixbuf_renderer_set_ignore_alpha((PixbufRenderer *)imd->pr, ignore_alpha); +} + /* *------------------------------------------------------------------- * read ahead (prebuffer) diff --git a/src/image.h b/src/image.h index 014dd1bf..be963124 100644 --- a/src/image.h +++ b/src/image.h @@ -90,6 +90,7 @@ void image_set_desaturate(ImageWindow *imd, gboolean desaturate); gboolean image_get_desaturate(ImageWindow *imd); void image_set_overunderexposed(ImageWindow *imd, gboolean overunderexposed); gboolean image_get_overunderexposed(ImageWindow *imd); +void image_set_ignore_alpha(ImageWindow *imd, gboolean ignore_alpha); /* zoom */ void image_zoom_adjust(ImageWindow *imd, gdouble increment); diff --git a/src/layout.c b/src/layout.c index 3be21309..6b1dbe19 100644 --- a/src/layout.c +++ b/src/layout.c @@ -2667,6 +2667,7 @@ void layout_write_attributes(LayoutOptions *layout, GString *outstr, gint indent WRITE_NL(); WRITE_BOOL(*layout, toolbar_hidden); WRITE_NL(); WRITE_BOOL(*layout, show_info_pixel); + WRITE_NL(); WRITE_BOOL(*layout, ignore_alpha); WRITE_SEPARATOR(); WRITE_NL(); WRITE_BOOL(*layout, bars_state.info); @@ -2772,6 +2773,7 @@ void layout_load_attributes(LayoutOptions *layout, const gchar **attribute_names if (READ_BOOL(*layout, tools_hidden)) continue; if (READ_BOOL(*layout, toolbar_hidden)) continue; if (READ_BOOL(*layout, show_info_pixel)) continue; + if (READ_BOOL(*layout, ignore_alpha)) continue; if (READ_BOOL(*layout, bars_state.info)) continue; if (READ_BOOL(*layout, bars_state.sort)) continue; diff --git a/src/layout_image.c b/src/layout_image.c index 1afa9107..8d499851 100644 --- a/src/layout_image.c +++ b/src/layout_image.c @@ -1308,6 +1308,14 @@ gboolean layout_image_get_overunderexposed(LayoutWindow *lw) return image_get_overunderexposed(lw->image); } +void layout_image_set_ignore_alpha(LayoutWindow *lw, gboolean ignore_alpha) +{ + if (!layout_valid(&lw)) return; + + lw->options.ignore_alpha = ignore_alpha; + image_set_ignore_alpha(lw->image, ignore_alpha); +} + /* stereo */ /* gint layout_image_stereo_get(LayoutWindow *lw) diff --git a/src/layout_image.h b/src/layout_image.h index a284c7c6..9d4b1237 100644 --- a/src/layout_image.h +++ b/src/layout_image.h @@ -65,6 +65,7 @@ void layout_image_set_desaturate(LayoutWindow *lw, gboolean desaturate); gboolean layout_image_get_desaturate(LayoutWindow *lw); void layout_image_set_overunderexposed(LayoutWindow *lw, gboolean overunderexposed); gboolean layout_image_get_overunderexposed(LayoutWindow *lw); +void layout_image_set_ignore_alpha(LayoutWindow *lw, gboolean ignore_alpha); void layout_image_rating(LayoutWindow *lw, const gchar *rating); diff --git a/src/layout_util.c b/src/layout_util.c index af480da5..9b5ee7cf 100644 --- a/src/layout_util.c +++ b/src/layout_util.c @@ -512,6 +512,15 @@ static void layout_menu_alter_desaturate_cb(GtkToggleAction *action, gpointer da layout_image_set_desaturate(lw, gtk_toggle_action_get_active(action)); } +static void layout_menu_alter_ignore_alpha_cb(GtkToggleAction *action, gpointer data) +{ + LayoutWindow *lw = data; + + if (lw->options.ignore_alpha == gtk_toggle_action_get_active(action)) return; + + layout_image_set_ignore_alpha(lw, gtk_toggle_action_get_active(action)); +} + static void layout_menu_alter_none_cb(GtkAction *action, gpointer data) { LayoutWindow *lw = data; @@ -2577,6 +2586,7 @@ static GtkToggleActionEntry menu_toggle_entries[] = { { "ShowMarks", PIXBUF_INLINE_ICON_MARKS, N_("Show _Marks"), "M", N_("Show Marks"), CB(layout_menu_marks_cb), FALSE }, { "ShowFileFilter", PIXBUF_INLINE_ICON_FILE_FILTER, N_("Show File Filter"), NULL, N_("Show File Filter"), CB(layout_menu_file_filter_cb), FALSE }, { "ShowInfoPixel", GTK_STOCK_COLOR_PICKER, N_("Pi_xel Info"), NULL, N_("Show Pixel Info"), CB(layout_menu_info_pixel_cb), FALSE }, + { "IgnoreAlpha", GTK_STOCK_STRIKETHROUGH, N_("Hide _alpha"), "A", N_("Hide alpha channel"), CB(layout_menu_alter_ignore_alpha_cb), FALSE}, { "FloatTools", PIXBUF_INLINE_ICON_FLOAT,N_("_Float file list"), "L", N_("Float file list"), CB(layout_menu_float_cb), FALSE }, { "HideToolbar", NULL, N_("Hide tool_bar"), NULL, N_("Hide toolbar"), CB(layout_menu_toolbar_cb), FALSE }, { "SBar", PIXBUF_INLINE_ICON_INFO, N_("_Info sidebar"), "K", N_("Info sidebar"), CB(layout_menu_bar_cb), FALSE }, @@ -2863,6 +2873,7 @@ static const gchar *menu_ui_description = " " " " " " +" " " " " " " " @@ -3770,6 +3781,9 @@ static void layout_util_sync_views(LayoutWindow *lw) action = gtk_action_group_get_action(lw->action_group, "SlideShow"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), layout_image_slideshow_active(lw)); + action = gtk_action_group_get_action(lw->action_group, "IgnoreAlpha"); + gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.ignore_alpha); + action = gtk_action_group_get_action(lw->action_group, "Animate"); gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lw->options.animate); @@ -3824,6 +3838,7 @@ static void layout_util_sync_views(LayoutWindow *lw) layout_util_sync_marks(lw); layout_util_sync_color(lw); + layout_image_set_ignore_alpha(lw, lw->options.ignore_alpha); } void layout_util_sync_thumb(LayoutWindow *lw) diff --git a/src/pixbuf-renderer.c b/src/pixbuf-renderer.c index a09692cb..b960cb91 100644 --- a/src/pixbuf-renderer.c +++ b/src/pixbuf-renderer.c @@ -2995,4 +2995,13 @@ void pixbuf_renderer_set_size_early(PixbufRenderer *pr, guint width, guint heigh #endif } +void pixbuf_renderer_set_ignore_alpha(PixbufRenderer *pr, gint ignore_alpha) +{ + g_return_if_fail(IS_PIXBUF_RENDERER(pr)); + + pr->ignore_alpha = ignore_alpha; + pr_pixbuf_size_sync(pr); + pr_zoom_sync(pr, pr->zoom, PR_ZOOM_FORCE, 0, 0); +} + /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/pixbuf-renderer.h b/src/pixbuf-renderer.h index c399e1fd..71534902 100644 --- a/src/pixbuf-renderer.h +++ b/src/pixbuf-renderer.h @@ -213,6 +213,8 @@ struct _PixbufRenderer RendererFuncs *renderer; RendererFuncs *renderer2; + + gboolean ignore_alpha; }; struct _PixbufRendererClass @@ -369,5 +371,7 @@ void pr_coords_map_orientation_reverse(gint orientation, GList *pr_source_tile_compute_region(PixbufRenderer *pr, gint x, gint y, gint w, gint h, gboolean request); void pr_create_anaglyph(guint mode, GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h); + +void pixbuf_renderer_set_ignore_alpha(PixbufRenderer *pr, gint ignore_alpha); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/pixbuf_util.c b/src/pixbuf_util.c index fc41487e..9d10630f 100644 --- a/src/pixbuf_util.c +++ b/src/pixbuf_util.c @@ -1509,4 +1509,43 @@ void pixbuf_highlight_overunderexposed(GdkPixbuf *pb, gint x, gint y, gint w, gi } } } + +/* + *----------------------------------------------------------------------------- + * pixbuf ignore alpha + *----------------------------------------------------------------------------- +*/ +void pixbuf_ignore_alpha_rect(GdkPixbuf *pb, + gint x, gint y, gint w, gint h) +{ + gboolean has_alpha; + gint pw, ph, prs; + guchar *p_pix; + guchar *pp; + gint i, j; + + if (!pb) return; + + pw = gdk_pixbuf_get_width(pb); + ph = gdk_pixbuf_get_height(pb); + + if (x < 0 || x + w > pw) return; + if (y < 0 || y + h > ph) return; + + has_alpha = gdk_pixbuf_get_has_alpha(pb); + if (!has_alpha) return; + + prs = gdk_pixbuf_get_rowstride(pb); + p_pix = gdk_pixbuf_get_pixels(pb); + + for (i = 0; i < h; i++) + { + pp = p_pix + (y + i) * prs + (x * 4 ); + for (j = 0; j < w; j++) + { + pp[3] = 0xff; + pp+=4; + } + } +} /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/pixbuf_util.h b/src/pixbuf_util.h index 0a6fc35e..6c8347c0 100644 --- a/src/pixbuf_util.h +++ b/src/pixbuf_util.h @@ -135,7 +135,8 @@ void pixbuf_desaturate_rect(GdkPixbuf *pb, gint x, gint y, gint w, gint h); void pixbuf_highlight_overunderexposed(GdkPixbuf *pb, gint x, gint y, gint w, gint h); - +void pixbuf_ignore_alpha_rect(GdkPixbuf *pb, + gint x, gint y, gint w, gint h); /* clipping utils */ diff --git a/src/renderer-tiles.c b/src/renderer-tiles.c index efffba03..9b4f0498 100644 --- a/src/renderer-tiles.c +++ b/src/renderer-tiles.c @@ -1256,13 +1256,15 @@ static gboolean rt_source_tile_render(RendererTiles *rt, ImageTile *it, return draw; } -static void rt_tile_get_region(gboolean has_alpha, +static void rt_tile_get_region(gboolean has_alpha, gboolean ignore_alpha, const GdkPixbuf *src, GdkPixbuf *dest, int pb_x, int pb_y, int pb_w, int pb_h, double offset_x, double offset_y, double scale_x, double scale_y, GdkInterpType interp_type, int check_x, int check_y) { + GdkPixbuf* tmppixbuf; + if (!has_alpha) { if (scale_x == 1.0 && scale_y == 1.0) @@ -1285,20 +1287,45 @@ static void rt_tile_get_region(gboolean has_alpha, } else { - gdk_pixbuf_composite_color(src, dest, - pb_x, pb_y, pb_w, pb_h, - offset_x, - offset_y, - scale_x, scale_y, - (scale_x == 1.0 && scale_y == 1.0) ? GDK_INTERP_NEAREST : interp_type, - 255, check_x, check_y, - PR_ALPHA_CHECK_SIZE, - ((options->image.alpha_color_1.red << 8 & 0x00FF0000) + - (options->image.alpha_color_1.green & 0x00FF00) + - (options->image.alpha_color_1.blue >> 8 & 0x00FF)), - ((options->image.alpha_color_2.red << 8 & 0x00FF0000) + - (options->image.alpha_color_2.green & 0x00FF00) + - (options->image.alpha_color_2.blue >> 8 & 0x00FF))); + if (ignore_alpha) + { + tmppixbuf = gdk_pixbuf_add_alpha(src, FALSE, 0, 0, 0); + + pixbuf_ignore_alpha_rect(tmppixbuf, 0, 0, gdk_pixbuf_get_width(src), gdk_pixbuf_get_height(src)); + + gdk_pixbuf_composite_color(tmppixbuf, dest, + pb_x, pb_y, pb_w, pb_h, + offset_x, + offset_y, + scale_x, scale_y, + (scale_x == 1.0 && scale_y == 1.0) ? GDK_INTERP_NEAREST : interp_type, + 255, check_x, check_y, + PR_ALPHA_CHECK_SIZE, + ((options->image.alpha_color_1.red << 8 & 0x00FF0000) + + (options->image.alpha_color_1.green & 0x00FF00) + + (options->image.alpha_color_1.blue >> 8 & 0x00FF)), + ((options->image.alpha_color_2.red << 8 & 0x00FF0000) + + (options->image.alpha_color_2.green & 0x00FF00) + + (options->image.alpha_color_2.blue >> 8 & 0x00FF))); + g_object_unref(tmppixbuf); + } + else + { + gdk_pixbuf_composite_color(src, dest, + pb_x, pb_y, pb_w, pb_h, + offset_x, + offset_y, + scale_x, scale_y, + (scale_x == 1.0 && scale_y == 1.0) ? GDK_INTERP_NEAREST : interp_type, + 255, check_x, check_y, + PR_ALPHA_CHECK_SIZE, + ((options->image.alpha_color_1.red << 8 & 0x00FF0000) + + (options->image.alpha_color_1.green & 0x00FF00) + + (options->image.alpha_color_1.blue >> 8 & 0x00FF)), + ((options->image.alpha_color_2.red << 8 & 0x00FF0000) + + (options->image.alpha_color_2.green & 0x00FF00) + + (options->image.alpha_color_2.blue >> 8 & 0x00FF))); + } } } @@ -1417,7 +1444,7 @@ static void rt_tile_render(RendererTiles *rt, ImageTile *it, */ if (pr->width < PR_MIN_SCALE_SIZE || pr->height < PR_MIN_SCALE_SIZE) fast = TRUE; - rt_tile_get_region(has_alpha, + rt_tile_get_region(has_alpha, pr->ignore_alpha, pr->pixbuf, it->pixbuf, pb_x, pb_y, pb_w, pb_h, (gdouble) 0.0 - src_x - GET_RIGHT_PIXBUF_OFFSET(rt) * scale_x, (gdouble) 0.0 - src_y, @@ -1428,7 +1455,7 @@ static void rt_tile_render(RendererTiles *rt, ImageTile *it, (pr->stereo_pixbuf_offset_right > 0 || pr->stereo_pixbuf_offset_left > 0)) { GdkPixbuf *right_pb = rt_get_spare_tile(rt); - rt_tile_get_region(has_alpha, + rt_tile_get_region(has_alpha, pr->ignore_alpha, pr->pixbuf, right_pb, pb_x, pb_y, pb_w, pb_h, (gdouble) 0.0 - src_x - GET_LEFT_PIXBUF_OFFSET(rt) * scale_x, (gdouble) 0.0 - src_y, diff --git a/src/toolbar.c b/src/toolbar.c index d4076d54..4caeeba7 100644 --- a/src/toolbar.c +++ b/src/toolbar.c @@ -129,6 +129,7 @@ static const UseableToolbarItems useable_toolbar_items[] = { {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE}, {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE}, {"ShowInfoPixel", N_("Pixel Info"), GTK_STOCK_COLOR_PICKER}, + {"IgnoreAlpha", N_("Ignore Alpha"), GTK_STOCK_STRIKETHROUGH}, {"ExifRotate", N_("_Exif rotate"), GTK_STOCK_ORIENTATION_PORTRAIT}, {"UseColorProfiles", N_("Use color profiles"), GTK_STOCK_SELECT_COLOR}, {"SaveMetadata", N_("Save metadata"), GTK_STOCK_SAVE}, diff --git a/src/typedefs.h b/src/typedefs.h index 596421f1..04da8ba2 100644 --- a/src/typedefs.h +++ b/src/typedefs.h @@ -663,6 +663,7 @@ struct _LayoutOptions gboolean show_directory_date; gboolean show_info_pixel; gboolean split_pane_sync; + gboolean ignore_alpha; struct { gint w; -- 2.20.1