Fix #344: Ignoring alpha channel
authorvonasekĀ  <>
Fri, 8 May 2020 15:47:06 +0000 (16:47 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 8 May 2020 15:47:06 +0000 (16:47 +0100)
https://github.com/BestImageViewer/geeqie/issues/344

13 files changed:
src/image.c
src/image.h
src/layout.c
src/layout_image.c
src/layout_image.h
src/layout_util.c
src/pixbuf-renderer.c
src/pixbuf-renderer.h
src/pixbuf_util.c
src/pixbuf_util.h
src/renderer-tiles.c
src/toolbar.c
src/typedefs.h

index 522e8bd..9ca1d2a 100644 (file)
@@ -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)
index 014dd1b..be96312 100644 (file)
@@ -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);
index 3be2130..6b1dbe1 100644 (file)
@@ -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;
index 1afa910..8d49985 100644 (file)
@@ -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)
index a284c7c..9d4b123 100644 (file)
@@ -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);
 
index af480da..9b5ee7c 100644 (file)
@@ -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"),          "<shift>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"),                    "<control>K",           N_("Info sidebar"),                     CB(layout_menu_bar_cb),          FALSE  },
@@ -2863,6 +2873,7 @@ static const gchar *menu_ui_description =
 "      <menuitem action='SBarSort'/>"
 "      <menuitem action='HideBars'/>"
 "      <menuitem action='ShowInfoPixel'/>"
+"      <menuitem action='IgnoreAlpha'/>"
 "      <placeholder name='ToolsSection'/>"
 "      <separator/>"
 "      <menuitem action='Animate'/>"
@@ -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)
index a09692c..b960cb9 100644 (file)
@@ -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: */
index c399e1f..7153490 100644 (file)
@@ -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: */
index fc41487..9d10630 100644 (file)
@@ -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: */
index 0a6fc35..6c8347c 100644 (file)
@@ -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 */
 
index efffba0..9b4f049 100644 (file)
@@ -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,
index d4076d5..4caeeba 100644 (file)
@@ -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},
index 596421f..04da8ba 100644 (file)
@@ -663,6 +663,7 @@ struct _LayoutOptions
        gboolean show_directory_date;
        gboolean show_info_pixel;
        gboolean split_pane_sync;
+       gboolean ignore_alpha;
 
        struct {
                gint w;