[gimp] app: parallelize gimpbrush-transform.cc



commit c8d4c079a204dded5429f336e394e492a581226a
Author: Ell <ell_se yahoo com>
Date:   Wed Apr 4 16:57:35 2018 -0400

    app: parallelize gimpbrush-transform.cc
    
    Use gimp_parallel_distribute_foo() to parallelize the brush
    transform functions.

 app/core/gimpbrush-transform.cc |  683 +++++++++++++++++++++------------------
 1 files changed, 365 insertions(+), 318 deletions(-)
---
diff --git a/app/core/gimpbrush-transform.cc b/app/core/gimpbrush-transform.cc
index 5fcdf26..fc83488 100644
--- a/app/core/gimpbrush-transform.cc
+++ b/app/core/gimpbrush-transform.cc
@@ -33,11 +33,16 @@ extern "C"
 
 #include "gegl/gimp-gegl-loops.h"
 
+#include "gimp-parallel.h"
 #include "gimpbrush.h"
 #include "gimpbrush-transform.h"
 #include "gimptempbuf.h"
 
 
+#define MIN_PARALLEL_SUB_SIZE 64
+#define MIN_PARALLEL_SUB_AREA (MIN_PARALLEL_SUB_SIZE * MIN_PARALLEL_SUB_SIZE)
+
+
 /*  local function prototypes  */
 
 static void    gimp_brush_transform_bounding_box           (GimpBrush         *brush,
@@ -115,7 +120,6 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
 {
   GimpTempBuf  *result;
   GimpTempBuf  *source;
-  guchar       *dest;
   const guchar *src;
   GimpMatrix3   matrix;
   gint          src_width;
@@ -136,18 +140,6 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
   gint          src_walk_uy_i;
   gint          src_walk_vx_i;
   gint          src_walk_vy_i;
-  gint          src_space_cur_pos_x;
-  gint          src_space_cur_pos_y;
-  gint          src_space_cur_pos_x_i;
-  gint          src_space_cur_pos_y_i;
-  gint          src_space_row_start_x_i;
-  gint          src_space_row_start_y_i;
-  const guchar *src_walker;
-  const guchar *pixel_next;
-  const guchar *pixel_below;
-  const guchar *pixel_below_next;
-  gint          opposite_x, distance_from_true_x;
-  gint          opposite_y, distance_from_true_y;
 
   /*
    * tl, tr etc are used because it is easier to visualize top left,
@@ -229,8 +221,7 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
   result = gimp_temp_buf_new (dest_width, dest_height,
                               gimp_temp_buf_get_format (source));
 
-  dest = gimp_temp_buf_get_data (result);
-  src  = gimp_temp_buf_get_data (source);
+  src = gimp_temp_buf_get_data (source);
 
   /* prevent disappearance of 1x1 pixel brush at some rotations when
      scaling < 1 */
@@ -265,103 +256,124 @@ gimp_brush_real_transform_mask (GimpBrush *brush,
   src_walk_vx_i = (gint) ((src_tl_to_bl_delta_x / dest_height) * int_multiple);
   src_walk_vy_i = (gint) ((src_tl_to_bl_delta_y / dest_height) * int_multiple);
 
-  /* initialize current position in source space to the start position (tl)
-   * speed optimized, note conversion to int precision
-   */
-  src_space_cur_pos_x_i   = (gint) (t_lx* int_multiple);
-  src_space_cur_pos_y_i   = (gint) (t_ly* int_multiple);
-  src_space_cur_pos_x     = (gint) (src_space_cur_pos_x_i >> fraction_bits);
-  src_space_cur_pos_y     = (gint) (src_space_cur_pos_y_i >> fraction_bits);
-  src_space_row_start_x_i = (gint) (t_lx* int_multiple);
-  src_space_row_start_y_i = (gint) (t_ly* int_multiple);
-
-
-  for (y = 0; y < dest_height; y++)
+  gimp_parallel_distribute_area (GEGL_RECTANGLE (0, 0, dest_width, dest_height),
+                                 MIN_PARALLEL_SUB_AREA,
+                                 [=] (const GeglRectangle *area)
     {
-      for (x = 0; x < dest_width; x++)
+      guchar       *dest;
+      gint          src_space_cur_pos_x;
+      gint          src_space_cur_pos_y;
+      gint          src_space_cur_pos_x_i;
+      gint          src_space_cur_pos_y_i;
+      gint          src_space_row_start_x_i;
+      gint          src_space_row_start_y_i;
+      const guchar *src_walker;
+      const guchar *pixel_next;
+      const guchar *pixel_below;
+      const guchar *pixel_below_next;
+      gint          opposite_x, distance_from_true_x;
+      gint          opposite_y, distance_from_true_y;
+      gint          u, v;
+
+      dest = gimp_temp_buf_get_data (result) +
+             dest_width * area->y + area->x;
+
+      /* initialize current position in source space to the start position (tl)
+       * speed optimized, note conversion to int precision
+       */
+      src_space_row_start_x_i = (gint) (t_lx * int_multiple) +
+                                src_walk_vx_i * area->y      +
+                                src_walk_ux_i * area->x;
+      src_space_row_start_y_i = (gint) (t_ly * int_multiple) +
+                                src_walk_vy_i * area->y      +
+                                src_walk_uy_i * area->x;
+
+      for (v = 0; v < area->height; v++)
         {
-          if (src_space_cur_pos_x > src_width_minus_one ||
-              src_space_cur_pos_x < 0     ||
-              src_space_cur_pos_y > src_height_minus_one ||
-              src_space_cur_pos_y < 0)
-              /* no corresponding pixel in source space */
-            {
-              *dest = 0;
-            }
-          else /* reverse transformed point hits source pixel */
-            {
-              src_walker = src
-                        + src_space_cur_pos_y * src_width
-                        + src_space_cur_pos_x;
-
-              /* bottom right corner
-               * no pixel below, reuse current pixel instead
-               * no next pixel to the right so reuse current pixel instead
-               */
-              if (src_space_cur_pos_y == src_height_minus_one &&
-                  src_space_cur_pos_x == src_width_minus_one )
-                {
-                  pixel_next       = src_walker;
-                  pixel_below      = src_walker;
-                  pixel_below_next = src_walker;
-                }
+          src_space_cur_pos_x_i = src_space_row_start_x_i;
+          src_space_cur_pos_y_i = src_space_row_start_y_i;
 
-              /* bottom edge pixel row, except rightmost corner
-               * no pixel below, reuse current pixel instead  */
-              else if (src_space_cur_pos_y == src_height_minus_one)
+          for (u = 0; u < area->width; u++)
+            {
+              src_space_cur_pos_x = src_space_cur_pos_x_i >> fraction_bits;
+              src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
+
+              if (src_space_cur_pos_x > src_width_minus_one ||
+                  src_space_cur_pos_x < 0     ||
+                  src_space_cur_pos_y > src_height_minus_one ||
+                  src_space_cur_pos_y < 0)
+                  /* no corresponding pixel in source space */
                 {
-                  pixel_next       = src_walker + 1;
-                  pixel_below      = src_walker;
-                  pixel_below_next = src_walker + 1;
+                  *dest = 0;
                 }
-
-              /* right edge pixel column, except bottom corner
-               * no next pixel to the right so reuse current pixel instead */
-              else if (src_space_cur_pos_x == src_width_minus_one)
+              else /* reverse transformed point hits source pixel */
                 {
-                  pixel_next       = src_walker;
-                  pixel_below      = src_walker + src_width;
-                  pixel_below_next = pixel_below;
-                }
+                  src_walker = src                             +
+                               src_space_cur_pos_y * src_width +
+                               src_space_cur_pos_x;
+
+                  /* bottom right corner
+                   * no pixel below, reuse current pixel instead
+                   * no next pixel to the right so reuse current pixel instead
+                   */
+                  if (src_space_cur_pos_y == src_height_minus_one &&
+                      src_space_cur_pos_x == src_width_minus_one )
+                    {
+                      pixel_next       = src_walker;
+                      pixel_below      = src_walker;
+                      pixel_below_next = src_walker;
+                    }
 
-              /* neither on bottom edge nor on right edge */
-              else
-                {
-                  pixel_next       = src_walker + 1;
-                  pixel_below      = src_walker + src_width;
-                  pixel_below_next = pixel_below + 1;
-                }
+                  /* bottom edge pixel row, except rightmost corner
+                   * no pixel below, reuse current pixel instead  */
+                  else if (src_space_cur_pos_y == src_height_minus_one)
+                    {
+                      pixel_next       = src_walker + 1;
+                      pixel_below      = src_walker;
+                      pixel_below_next = src_walker + 1;
+                    }
 
-              distance_from_true_x = src_space_cur_pos_x_i & fraction_bitmask;
-              distance_from_true_y = src_space_cur_pos_y_i & fraction_bitmask;
-              opposite_x =  int_multiple - distance_from_true_x;
-              opposite_y =  int_multiple - distance_from_true_y;
+                  /* right edge pixel column, except bottom corner
+                   * no next pixel to the right so reuse current pixel instead */
+                  else if (src_space_cur_pos_x == src_width_minus_one)
+                    {
+                      pixel_next       = src_walker;
+                      pixel_below      = src_walker + src_width;
+                      pixel_below_next = pixel_below;
+                    }
 
-              *dest = ((src_walker[0] * opposite_x +
-                        pixel_next[0] * distance_from_true_x) * opposite_y +
-                       (pixel_below[0] * opposite_x +
-                        pixel_below_next[0] *distance_from_true_x) * distance_from_true_y
-                       ) >> recovery_bits;
-            }
+                  /* neither on bottom edge nor on right edge */
+                  else
+                    {
+                      pixel_next       = src_walker + 1;
+                      pixel_below      = src_walker + src_width;
+                      pixel_below_next = pixel_below + 1;
+                    }
 
-          src_space_cur_pos_x_i+=src_walk_ux_i;
-          src_space_cur_pos_y_i+=src_walk_uy_i;
+                  distance_from_true_x = src_space_cur_pos_x_i & fraction_bitmask;
+                  distance_from_true_y = src_space_cur_pos_y_i & fraction_bitmask;
+                  opposite_x =  int_multiple - distance_from_true_x;
+                  opposite_y =  int_multiple - distance_from_true_y;
 
-          src_space_cur_pos_x = src_space_cur_pos_x_i >> fraction_bits;
-          src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
+                  *dest = ((src_walker[0] * opposite_x +
+                            pixel_next[0] * distance_from_true_x) * opposite_y +
+                           (pixel_below[0] * opposite_x +
+                            pixel_below_next[0] *distance_from_true_x) * distance_from_true_y
+                           ) >> recovery_bits;
+                }
 
-          dest ++;
-        } /* end for x */
+              src_space_cur_pos_x_i += src_walk_ux_i;
+              src_space_cur_pos_y_i += src_walk_uy_i;
 
-        src_space_row_start_x_i +=src_walk_vx_i;
-        src_space_row_start_y_i +=src_walk_vy_i;
-        src_space_cur_pos_x_i = src_space_row_start_x_i;
-        src_space_cur_pos_y_i = src_space_row_start_y_i;
+              dest++;
+            } /* end for x */
 
-        src_space_cur_pos_x = src_space_cur_pos_x_i >> fraction_bits;
-        src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
+          src_space_row_start_x_i += src_walk_vx_i;
+          src_space_row_start_y_i += src_walk_vy_i;
 
-    } /* end for y */
+          dest += dest_width - area->width;
+        } /* end for y */
+    });
 
   gimp_brush_transform_blur (result, blur_radius);
 
@@ -408,7 +420,6 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
 {
   GimpTempBuf  *result;
   GimpTempBuf  *source;
-  guchar       *dest;
   const guchar *src;
   GimpMatrix3   matrix;
   gint          src_width;
@@ -429,18 +440,6 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   gint          src_walk_uy_i;
   gint          src_walk_vx_i;
   gint          src_walk_vy_i;
-  gint          src_space_cur_pos_x;
-  gint          src_space_cur_pos_y;
-  gint          src_space_cur_pos_x_i;
-  gint          src_space_cur_pos_y_i;
-  gint          src_space_row_start_x_i;
-  gint          src_space_row_start_y_i;
-  const guchar *src_walker;
-  const guchar *pixel_next;
-  const guchar *pixel_below;
-  const guchar *pixel_below_next;
-  gint          opposite_x, distance_from_true_x;
-  gint          opposite_y, distance_from_true_y;
 
   /*
    * tl, tr etc are used because it is easier to visualize top left,
@@ -448,7 +447,7 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
    * rectangle.
    */
   const gint fraction_bits = 12;
-  const gint int_multiple  = pow(2,fraction_bits);
+  const gint int_multiple  = pow (2, fraction_bits);
 
   /* In inner loop's bilinear calculation, two numbers that were each
    * previously multiplied by int_multiple are multiplied together.
@@ -470,7 +469,7 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
    * 2^9     = 0010 0000 0000
    * 2^9 - 1 = 0001 1111 1111
    */
-  const guint fraction_bitmask = pow(2, fraction_bits)- 1 ;
+  const guint fraction_bitmask = pow(2, fraction_bits) - 1 ;
 
   source = gimp_brush_get_pixmap (brush);
 
@@ -483,7 +482,6 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   if (gimp_matrix3_is_identity (&matrix) && hardness == 1.0)
     return gimp_temp_buf_copy (source);
 
-
   src_width_minus_one  = src_width  - 1;
   src_height_minus_one = src_height - 1;
 
@@ -523,8 +521,16 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   result = gimp_temp_buf_new (dest_width, dest_height,
                               gimp_temp_buf_get_format (source));
 
-  dest = gimp_temp_buf_get_data (result);
-  src  = gimp_temp_buf_get_data (source);
+  src = gimp_temp_buf_get_data (source);
+
+  /* prevent disappearance of 1x1 pixel brush at some rotations when
+     scaling < 1 */
+  /*
+  if (src_width == 1 && src_height == 1 && scale_x < 1 && scale_y < 1 )
+    {
+      *dest = src[0];
+      return result;
+    }*/
 
   gimp_matrix3_transform_point (&matrix, 0,          0,           &t_lx, &t_ly);
   gimp_matrix3_transform_point (&matrix, dest_width, 0,           &t_rx, &t_ry);
@@ -545,122 +551,143 @@ gimp_brush_real_transform_pixmap (GimpBrush *brush,
   src_tl_to_bl_delta_y = b_ly - t_ly;
 
   /* speed optimized, note conversion to int precision */
-  src_walk_ux_i = (gint) ((src_tl_to_tr_delta_x / dest_width)* int_multiple);
-  src_walk_uy_i = (gint) ((src_tl_to_tr_delta_y / dest_width)* int_multiple);
-  src_walk_vx_i = (gint) ((src_tl_to_bl_delta_x / dest_height)* int_multiple);
-  src_walk_vy_i = (gint) ((src_tl_to_bl_delta_y / dest_height)* int_multiple);
-
-  /* initialize current position in source space to the start position (tl)
-   * speed optimized, note conversion to int precision
-   */
-  src_space_cur_pos_x_i    = (gint) (t_lx* int_multiple);
-  src_space_cur_pos_y_i    = (gint) (t_ly* int_multiple);
-  src_space_cur_pos_x      = (gint) (src_space_cur_pos_x_i >> fraction_bits);
-  src_space_cur_pos_y      = (gint) (src_space_cur_pos_y_i >> fraction_bits);
-  src_space_row_start_x_i  = (gint) (t_lx* int_multiple);
-  src_space_row_start_y_i  = (gint) (t_ly* int_multiple);
-
+  src_walk_ux_i = (gint) ((src_tl_to_tr_delta_x / dest_width)  * int_multiple);
+  src_walk_uy_i = (gint) ((src_tl_to_tr_delta_y / dest_width)  * int_multiple);
+  src_walk_vx_i = (gint) ((src_tl_to_bl_delta_x / dest_height) * int_multiple);
+  src_walk_vy_i = (gint) ((src_tl_to_bl_delta_y / dest_height) * int_multiple);
 
-  for (y = 0; y < dest_height; y++)
+  gimp_parallel_distribute_area (GEGL_RECTANGLE (0, 0, dest_width, dest_height),
+                                 MIN_PARALLEL_SUB_AREA,
+                                 [=] (const GeglRectangle *area)
     {
-      for (x = 0; x < dest_width; x++)
+      guchar       *dest;
+      gint          src_space_cur_pos_x;
+      gint          src_space_cur_pos_y;
+      gint          src_space_cur_pos_x_i;
+      gint          src_space_cur_pos_y_i;
+      gint          src_space_row_start_x_i;
+      gint          src_space_row_start_y_i;
+      const guchar *src_walker;
+      const guchar *pixel_next;
+      const guchar *pixel_below;
+      const guchar *pixel_below_next;
+      gint          opposite_x, distance_from_true_x;
+      gint          opposite_y, distance_from_true_y;
+      gint          u, v;
+
+      dest = gimp_temp_buf_get_data (result) +
+             3 * (dest_width * area->y + area->x);
+
+      /* initialize current position in source space to the start position (tl)
+       * speed optimized, note conversion to int precision
+       */
+      src_space_row_start_x_i = (gint) (t_lx * int_multiple) +
+                                src_walk_vx_i * area->y      +
+                                src_walk_ux_i * area->x;
+      src_space_row_start_y_i = (gint) (t_ly * int_multiple) +
+                                src_walk_vy_i * area->y      +
+                                src_walk_uy_i * area->x;
+
+      for (v = 0; v < area->height; v++)
         {
-          if (src_space_cur_pos_x > src_width_minus_one  ||
-              src_space_cur_pos_x < 0     ||
-              src_space_cur_pos_y > src_height_minus_one ||
-              src_space_cur_pos_y < 0)
-              /* no corresponding pixel in source space */
-            {
-              dest[0] = 0;
-              dest[1] = 0;
-              dest[2] = 0;
-            }
-          else /* reverse transformed point hits source pixel */
+          src_space_cur_pos_x_i = src_space_row_start_x_i;
+          src_space_cur_pos_y_i = src_space_row_start_y_i;
+
+          for (u = 0; u < area->width; u++)
             {
-              src_walker = src
-                        + 3 * (
-                          src_space_cur_pos_y * src_width
-                        + src_space_cur_pos_x);
-
-              /* bottom right corner
-               * no pixel below, reuse current pixel instead
-               * no next pixel to the right so reuse current pixel instead
-               */
-              if (src_space_cur_pos_y == src_height_minus_one &&
-                  src_space_cur_pos_x == src_width_minus_one )
+              src_space_cur_pos_x = src_space_cur_pos_x_i >> fraction_bits;
+              src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
+
+              if (src_space_cur_pos_x > src_width_minus_one ||
+                  src_space_cur_pos_x < 0     ||
+                  src_space_cur_pos_y > src_height_minus_one ||
+                  src_space_cur_pos_y < 0)
+                  /* no corresponding pixel in source space */
                 {
-                  pixel_next  = src_walker;
-                  pixel_below = src_walker;
-                  pixel_below_next = src_walker;
+                  dest[0] = 0;
+                  dest[1] = 0;
+                  dest[2] = 0;
                 }
-
-              /* bottom edge pixel row, except rightmost corner
-               * no pixel below, reuse current pixel instead  */
-              else if (src_space_cur_pos_y == src_height_minus_one)
+              else /* reverse transformed point hits source pixel */
                 {
-                  pixel_next  = src_walker + 3;
-                  pixel_below = src_walker;
-                  pixel_below_next = src_walker + 3;
-                }
+                  src_walker = src                                  +
+                               3 * (src_space_cur_pos_y * src_width +
+                                    src_space_cur_pos_x);
+
+                  /* bottom right corner
+                   * no pixel below, reuse current pixel instead
+                   * no next pixel to the right so reuse current pixel instead
+                   */
+                  if (src_space_cur_pos_y == src_height_minus_one &&
+                      src_space_cur_pos_x == src_width_minus_one )
+                    {
+                      pixel_next       = src_walker;
+                      pixel_below      = src_walker;
+                      pixel_below_next = src_walker;
+                    }
 
-              /* right edge pixel column, except bottom corner
-               * no next pixel to the right so reuse current pixel instead */
-              else if (src_space_cur_pos_x == src_width_minus_one)
-                {
-                  pixel_next  = src_walker;
-                  pixel_below = src_walker + src_width * 3;
-                  pixel_below_next = pixel_below;
-                }
+                  /* bottom edge pixel row, except rightmost corner
+                   * no pixel below, reuse current pixel instead  */
+                  else if (src_space_cur_pos_y == src_height_minus_one)
+                    {
+                      pixel_next       = src_walker + 3;
+                      pixel_below      = src_walker;
+                      pixel_below_next = src_walker + 3;
+                    }
 
-              /* neither on bottom edge nor on right edge */
-              else
-                {
-                  pixel_next  = src_walker + 3;
-                  pixel_below = src_walker + src_width * 3;
-                  pixel_below_next = pixel_below + 3;
-                }
+                  /* right edge pixel column, except bottom corner
+                   * no next pixel to the right so reuse current pixel instead */
+                  else if (src_space_cur_pos_x == src_width_minus_one)
+                    {
+                      pixel_next       = src_walker;
+                      pixel_below      = src_walker + src_width * 3;
+                      pixel_below_next = pixel_below;
+                    }
 
-              distance_from_true_x = src_space_cur_pos_x_i & fraction_bitmask;
-              distance_from_true_y = src_space_cur_pos_y_i & fraction_bitmask;
-              opposite_x =  int_multiple - distance_from_true_x;
-              opposite_y =  int_multiple - distance_from_true_y;
-
-              dest[0] = ((src_walker[0] * opposite_x +
-                          pixel_next[0] * distance_from_true_x) * opposite_y +
-                         (pixel_below[0] * opposite_x +
-                          pixel_below_next[0] *distance_from_true_x) * distance_from_true_y
-                        ) >> recovery_bits;
-
-              dest[1] = ((src_walker[1] * opposite_x +
-                          pixel_next[1] * distance_from_true_x) * opposite_y +
-                         (pixel_below[1] * opposite_x +
-                          pixel_below_next[1] *distance_from_true_x) * distance_from_true_y
-                        ) >> recovery_bits;
-
-              dest[2] = ((src_walker[2] * opposite_x +
-                          pixel_next[2] * distance_from_true_x) * opposite_y +
-                         (pixel_below[2] * opposite_x +
-                          pixel_below_next[2] *distance_from_true_x) * distance_from_true_y
-                        ) >> recovery_bits;
-            }
+                  /* neither on bottom edge nor on right edge */
+                  else
+                    {
+                      pixel_next       = src_walker + 3;
+                      pixel_below      = src_walker + src_width * 3;
+                      pixel_below_next = pixel_below + 3;
+                    }
 
-          src_space_cur_pos_x_i += src_walk_ux_i;
-          src_space_cur_pos_y_i += src_walk_uy_i;
+                  distance_from_true_x = src_space_cur_pos_x_i & fraction_bitmask;
+                  distance_from_true_y = src_space_cur_pos_y_i & fraction_bitmask;
+                  opposite_x =  int_multiple - distance_from_true_x;
+                  opposite_y =  int_multiple - distance_from_true_y;
+
+                  dest[0] = ((src_walker[0] * opposite_x +
+                              pixel_next[0] * distance_from_true_x) * opposite_y +
+                             (pixel_below[0] * opposite_x +
+                              pixel_below_next[0] *distance_from_true_x) * distance_from_true_y
+                            ) >> recovery_bits;
+
+                  dest[1] = ((src_walker[1] * opposite_x +
+                              pixel_next[1] * distance_from_true_x) * opposite_y +
+                             (pixel_below[1] * opposite_x +
+                              pixel_below_next[1] *distance_from_true_x) * distance_from_true_y
+                            ) >> recovery_bits;
+
+                  dest[2] = ((src_walker[2] * opposite_x +
+                              pixel_next[2] * distance_from_true_x) * opposite_y +
+                             (pixel_below[2] * opposite_x +
+                              pixel_below_next[2] *distance_from_true_x) * distance_from_true_y
+                            ) >> recovery_bits;
+                }
 
-          src_space_cur_pos_x = src_space_cur_pos_x_i >> fraction_bits;
-          src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
+              src_space_cur_pos_x_i += src_walk_ux_i;
+              src_space_cur_pos_y_i += src_walk_uy_i;
 
-          dest += 3;
-        } /* end for x */
+              dest += 3;
+            } /* end for x */
 
-        src_space_row_start_x_i +=src_walk_vx_i;
-        src_space_row_start_y_i +=src_walk_vy_i;
-        src_space_cur_pos_x_i = src_space_row_start_x_i;
-        src_space_cur_pos_y_i = src_space_row_start_y_i;
+          src_space_row_start_x_i += src_walk_vx_i;
+          src_space_row_start_y_i += src_walk_vy_i;
 
-        src_space_cur_pos_x = src_space_cur_pos_x_i >> fraction_bits;
-        src_space_cur_pos_y = src_space_cur_pos_y_i >> fraction_bits;
-    } /* end for y */
+          dest += 3 * (dest_width - area->width);
+        } /* end for y */
+    });
 
   gimp_brush_transform_blur (result, blur_radius);
 
@@ -774,157 +801,177 @@ gimp_brush_transform_blur (GimpTempBuf *buf,
   gfloat      n_r          = n * r;
   gfloat      weight       = floor (n * n / 2) * (floor (n * n / 2) + 1);
   gfloat      weight_inv   = 1 / weight;
-  gint        x;
-  gint        y;
-  gint        c;
   Sums       *sums;
-  guchar     *d;
-  Sums       *s;
 
   if (rw <= 0 || rh <= 0)
     return;
 
   sums = g_new (Sums, width * height * components);
 
-  d = data;
-  s = sums;
-
-  for (y = 0; y < height; y++)
+  gimp_parallel_distribute_range (height, MIN_PARALLEL_SUB_SIZE,
+                                  [=] (gint y0, gint height)
     {
-      const guchar *p;
+      gint          x;
+      gint          y;
+      gint          c;
+      const guchar *d;
+      Sums         *s;
 
-      struct
-      {
-        gint sum;
-        gint weighted_sum;
-        gint leading_sum;
-        gint leading_weighted_sum;
-      } acc[components];
+      d = data + y0 * stride;
+      s = sums + y0 * stride;
 
-      memset (acc, 0, sizeof (acc));
+      for (y = 0; y < height; y++)
+        {
+          const guchar *p;
 
-      p = d;
+          struct
+          {
+            gint sum;
+            gint weighted_sum;
+            gint leading_sum;
+            gint leading_weighted_sum;
+          } acc[components];
 
-      for (x = 0; x <= rw; x++)
-        {
-          for (c = 0; c < components; c++)
+          memset (acc, 0, sizeof (acc));
+
+          p = d;
+
+          for (x = 0; x <= rw; x++)
             {
-              acc[c].sum          +=      *p;
-              acc[c].weighted_sum += -x * *p;
+              for (c = 0; c < components; c++)
+                {
+                  acc[c].sum          +=      *p;
+                  acc[c].weighted_sum += -x * *p;
 
-              p++;
+                  p++;
+                }
             }
-        }
 
-      for (x = 0; x < width; x++)
-        {
-          for (c = 0; c < components; c++)
+          for (x = 0; x < width; x++)
             {
-              if (x > 0)
+              for (c = 0; c < components; c++)
                 {
-                  acc[c].weighted_sum         += acc[c].sum;
-                  acc[c].leading_weighted_sum += acc[c].leading_sum;
-
-                  if (x < width - r)
+                  if (x > 0)
                     {
-                      acc[c].sum              +=      d[components_r];
-                      acc[c].weighted_sum     += -r * d[components_r];
+                      acc[c].weighted_sum         += acc[c].sum;
+                      acc[c].leading_weighted_sum += acc[c].leading_sum;
+
+                      if (x < width - r)
+                        {
+                          acc[c].sum              +=      d[components_r];
+                          acc[c].weighted_sum     += -r * d[components_r];
+                        }
                     }
-                }
 
-              acc[c].leading_sum += d[0];
+                  acc[c].leading_sum += d[0];
 
-              s->sum          = acc[c].sum;
-              s->weighted_sum = acc[c].weighted_sum;
-              s->middle_sum   = 2 * acc[c].leading_weighted_sum -
-                                acc[c].weighted_sum;
+                  s->sum          = acc[c].sum;
+                  s->weighted_sum = acc[c].weighted_sum;
+                  s->middle_sum   = 2 * acc[c].leading_weighted_sum -
+                                    acc[c].weighted_sum;
 
-              if (x >= r)
-                {
-                  acc[c].sum                  -=     d[-components_r];
-                  acc[c].weighted_sum         -= r * d[-components_r];
-                  acc[c].leading_sum          -=     d[-components_r];
-                  acc[c].leading_weighted_sum -= r * d[-components_r];
-                }
+                  if (x >= r)
+                    {
+                      acc[c].sum                  -=     d[-components_r];
+                      acc[c].weighted_sum         -= r * d[-components_r];
+                      acc[c].leading_sum          -=     d[-components_r];
+                      acc[c].leading_weighted_sum -= r * d[-components_r];
+                    }
 
-              d++;
-              s++;
+                  d++;
+                  s++;
+                }
             }
         }
-    }
+    });
 
-  for (x = 0; x < width; x++)
+  gimp_parallel_distribute_range (width, MIN_PARALLEL_SUB_SIZE,
+                                  [=] (gint x0, gint width)
     {
-      const Sums *p;
-      gfloat      n_y;
+      gint        x;
+      gint        y;
+      gint        c;
+      guchar     *d0;
+      const Sums *s0;
+      guchar     *d;
+      const Sums *s;
 
-      struct
-      {
-        gfloat weighted_sum;
-        gint   leading_sum;
-        gint   trailing_sum;
-      } acc[components];
+      d0 = data + x0 * components;
+      s0 = sums + x0 * components;
 
-      memset (acc, 0, sizeof (acc));
+      for (x = 0; x < width; x++)
+        {
+          const Sums *p;
+          gfloat      n_y;
 
-      d = data + components * x;
-      s = sums + components * x;
+          struct
+          {
+            gfloat weighted_sum;
+            gint   leading_sum;
+            gint   trailing_sum;
+          } acc[components];
 
-      p = s + stride;
+          memset (acc, 0, sizeof (acc));
 
-      for (y = 1, n_y = n; y <= rh; y++, n_y += n)
-        {
-          for (c = 0; c < components; c++)
+          d = d0 + components * x;
+          s = s0 + components * x;
+
+          p = s + stride;
+
+          for (y = 1, n_y = n; y <= rh; y++, n_y += n)
             {
-              acc[c].weighted_sum += n_y * p->sum - p->weighted_sum;
-              acc[c].trailing_sum += p->sum;
+              for (c = 0; c < components; c++)
+                {
+                  acc[c].weighted_sum += n_y * p->sum - p->weighted_sum;
+                  acc[c].trailing_sum += p->sum;
 
-              p++;
-            }
+                  p++;
+                }
 
-          p += stride - components;
-        }
+              p += stride - components;
+            }
 
-      for (y = 0; y < height; y++)
-        {
-          for (c = 0; c < components; c++)
+          for (y = 0; y < height; y++)
             {
-              if (y > 0)
+              for (c = 0; c < components; c++)
                 {
-                  acc[c].weighted_sum += s->weighted_sum          +
-                                         n * (acc[c].leading_sum  -
-                                              acc[c].trailing_sum);
-                  acc[c].trailing_sum -= s->sum;
-
-                  if (y < height - r)
+                  if (y > 0)
                     {
-                      acc[c].weighted_sum += n_r * s[stride_r].sum -
-                                             s[stride_r].weighted_sum;
-                      acc[c].trailing_sum += s[stride_r].sum;
+                      acc[c].weighted_sum += s->weighted_sum          +
+                                             n * (acc[c].leading_sum  -
+                                                  acc[c].trailing_sum);
+                      acc[c].trailing_sum -= s->sum;
+
+                      if (y < height - r)
+                        {
+                          acc[c].weighted_sum += n_r * s[stride_r].sum -
+                                                 s[stride_r].weighted_sum;
+                          acc[c].trailing_sum += s[stride_r].sum;
+                        }
                     }
-                }
 
-              acc[c].leading_sum  += s->sum;
+                  acc[c].leading_sum  += s->sum;
 
-              *d = (acc[c].weighted_sum + s->middle_sum) * weight_inv + 0.5f;
+                  *d = (acc[c].weighted_sum + s->middle_sum) * weight_inv + 0.5f;
 
-              acc[c].weighted_sum += s->weighted_sum;
+                  acc[c].weighted_sum += s->weighted_sum;
 
-              if (y >= r)
-                {
-                  acc[c].weighted_sum -= n_r * s[-stride_r].sum +
-                                         s[-stride_r].weighted_sum;
-                  acc[c].leading_sum  -= s[-stride_r].sum;
+                  if (y >= r)
+                    {
+                      acc[c].weighted_sum -= n_r * s[-stride_r].sum +
+                                             s[-stride_r].weighted_sum;
+                      acc[c].leading_sum  -= s[-stride_r].sum;
+                    }
+
+                  d++;
+                  s++;
                 }
 
-              d++;
-              s++;
+              d += stride - components;
+              s += stride - components;
             }
-
-          d += stride - components;
-          s += stride - components;
         }
-    }
+    });
 
   g_free (sums);
 }


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