[recipes/image-download: 5/11] Add pixbuf blurring code



commit 3f5fe454595504999dc17fa3f7cb5e02e16bccb5
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Mar 3 21:59:09 2017 -0500

    Add pixbuf blurring code
    
    This is borrowed from libappstream-glib, and will
    be used for a similar purpose: Show a blurred version
    of a thumbnail when downloading images from the net.

 src/gr-utils.c |  133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gr-utils.h |    4 ++
 2 files changed, 137 insertions(+), 0 deletions(-)
---
diff --git a/src/gr-utils.c b/src/gr-utils.c
index f2056e3..86c6872 100644
--- a/src/gr-utils.c
+++ b/src/gr-utils.c
@@ -647,3 +647,136 @@ remove_image (const char *path)
                 g_print ("Not removing image %s", path);
         }
 }
+
+/* blur code borrowed from libappstream-glib */
+static void
+pixbuf_blur_private (GdkPixbuf *src, GdkPixbuf *dest, gint radius, guchar *div_kernel_size)
+{
+        gint width, height, src_rowstride, dest_rowstride, n_channels;
+        guchar *p_src, *p_dest, *c1, *c2;
+        gint x, y, i, i1, i2, width_minus_1, height_minus_1, radius_plus_1;
+        gint r, g, b, a;
+        guchar *p_dest_row, *p_dest_col;
+
+        width = gdk_pixbuf_get_width (src);
+        height = gdk_pixbuf_get_height (src);
+        n_channels = gdk_pixbuf_get_n_channels (src);
+        radius_plus_1 = radius + 1;
+
+        /* horizontal blur */
+        p_src = gdk_pixbuf_get_pixels (src);
+        p_dest = gdk_pixbuf_get_pixels (dest);
+        src_rowstride = gdk_pixbuf_get_rowstride (src);
+        dest_rowstride = gdk_pixbuf_get_rowstride (dest);
+        width_minus_1 = width - 1;
+        for (y = 0; y < height; y++) {
+
+                /* calc the initial sums of the kernel */
+                r = g = b = a = 0;
+                for (i = -radius; i <= radius; i++) {
+                        c1 = p_src + (CLAMP (i, 0, width_minus_1) * n_channels);
+                        r += c1[0];
+                        g += c1[1];
+                        b += c1[2];
+                }
+
+                p_dest_row = p_dest;
+                for (x = 0; x < width; x++) {
+                        /* set as the mean of the kernel */
+                        p_dest_row[0] = div_kernel_size[r];
+                        p_dest_row[1] = div_kernel_size[g];
+                        p_dest_row[2] = div_kernel_size[b];
+                        p_dest_row += n_channels;
+
+                        /* the pixel to add to the kernel */
+                        i1 = x + radius_plus_1;
+                        if (i1 > width_minus_1)
+                                i1 = width_minus_1;
+                        c1 = p_src + (i1 * n_channels);
+
+                        /* the pixel to remove from the kernel */
+                        i2 = x - radius;
+                        if (i2 < 0)
+                                i2 = 0;
+                        c2 = p_src + (i2 * n_channels);
+
+                        /* calc the new sums of the kernel */
+                        r += c1[0] - c2[0];
+                        g += c1[1] - c2[1];
+                        b += c1[2] - c2[2];
+                }
+
+                p_src += src_rowstride;
+                p_dest += dest_rowstride;
+        }
+
+        /* vertical blur */
+        p_src = gdk_pixbuf_get_pixels (dest);
+        p_dest = gdk_pixbuf_get_pixels (src);
+        src_rowstride = gdk_pixbuf_get_rowstride (dest);
+        dest_rowstride = gdk_pixbuf_get_rowstride (src);
+        height_minus_1 = height - 1;
+        for (x = 0; x < width; x++) {
+
+                /* calc the initial sums of the kernel */
+                r = g = b = a = 0;
+                for (i = -radius; i <= radius; i++) {
+                        c1 = p_src + (CLAMP (i, 0, height_minus_1) * src_rowstride);
+                        r += c1[0];
+                        g += c1[1];
+                        b += c1[2];
+                }
+
+                p_dest_col = p_dest;
+                for (y = 0; y < height; y++) {
+                        /* set as the mean of the kernel */
+
+                        p_dest_col[0] = div_kernel_size[r];
+                        p_dest_col[1] = div_kernel_size[g];
+                        p_dest_col[2] = div_kernel_size[b];
+                        p_dest_col += dest_rowstride;
+
+                        /* the pixel to add to the kernel */
+                        i1 = y + radius_plus_1;
+                        if (i1 > height_minus_1)
+                                i1 = height_minus_1;
+                        c1 = p_src + (i1 * src_rowstride);
+
+                        /* the pixel to remove from the kernel */
+                        i2 = y - radius;
+                        if (i2 < 0)
+                                i2 = 0;
+                        c2 = p_src + (i2 * src_rowstride);
+                        /* calc the new sums of the kernel */
+                        r += c1[0] - c2[0];
+                        g += c1[1] - c2[1];
+                        b += c1[2] - c2[2];
+                }
+
+                p_src += n_channels;
+                p_dest += n_channels;
+        }
+}
+
+void
+pixbuf_blur (GdkPixbuf *src, gint radius, gint iterations)
+{
+        gint kernel_size;
+        gint i;
+        g_autofree guchar *div_kernel_size = NULL;
+        g_autoptr(GdkPixbuf) tmp = NULL;
+
+        tmp = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (src),
+                              gdk_pixbuf_get_has_alpha (src),
+                              gdk_pixbuf_get_bits_per_sample (src),
+                              gdk_pixbuf_get_width (src),
+                              gdk_pixbuf_get_height (src));
+        kernel_size = 2 * radius + 1;
+        div_kernel_size = g_new (guchar, 256 * kernel_size);
+        for (i = 0; i < 256 * kernel_size; i++)
+                div_kernel_size[i] = (guchar) (i / kernel_size);
+
+        while (iterations-- > 0)
+                pixbuf_blur_private (src, tmp, radius, div_kernel_size);
+}
+
diff --git a/src/gr-utils.h b/src/gr-utils.h
index cd58b24..1214238 100644
--- a/src/gr-utils.h
+++ b/src/gr-utils.h
@@ -32,6 +32,10 @@ GdkPixbuf *load_pixbuf_fill_size (const char *path,
                                   int         width,
                                   int         height);
 
+void pixbuf_blur (GdkPixbuf *src,
+                  int        radius,
+                  int        iterations);
+
 const char *get_pkg_data_dir  (void);
 const char *get_user_data_dir (void);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]