[gimp/goat-invasion: 516/608] app: add format parameter to GimpPickable::get_pixel_at()



commit af0665690f73b3c5c18a14884451845ec7ce6b93
Author: Michael Natterer <mitch gimp org>
Date:   Sat Apr 21 10:03:32 2012 +0200

    app: add format parameter to GimpPickable::get_pixel_at()
    
    allowing NULL for the pickable's native format. Fix and simplify auto
    cropping to always use "R'G'B'A u8".

 app/core/gimpdrawable.c   |    9 ++--
 app/core/gimpimage-crop.c |  103 ++++++++++++++++++--------------------------
 app/core/gimpimagemap.c   |   11 +++--
 app/core/gimppickable.c   |   64 ++++++++++++++-------------
 app/core/gimppickable.h   |    6 ++-
 app/core/gimpprojection.c |    9 ++--
 6 files changed, 95 insertions(+), 107 deletions(-)
---
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 37e5dea..4573977 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -118,7 +118,8 @@ static void       gimp_drawable_transform          (GimpItem          *item,
 static gboolean   gimp_drawable_get_pixel_at       (GimpPickable      *pickable,
                                                     gint               x,
                                                     gint               y,
-                                                    guchar            *pixel);
+                                                    const Babl        *format,
+                                                    gpointer           pixel);
 static void       gimp_drawable_real_update        (GimpDrawable      *drawable,
                                                     gint               x,
                                                     gint               y,
@@ -636,7 +637,8 @@ static gboolean
 gimp_drawable_get_pixel_at (GimpPickable *pickable,
                             gint          x,
                             gint          y,
-                            guchar       *pixel)
+                            const Babl   *format,
+                            gpointer      pixel)
 {
   GimpDrawable *drawable = GIMP_DRAWABLE (pickable);
 
@@ -646,8 +648,7 @@ gimp_drawable_get_pixel_at (GimpPickable *pickable,
     return FALSE;
 
   gegl_buffer_sample (gimp_drawable_get_buffer (drawable),
-                      x, y, NULL, pixel,
-                      gimp_drawable_get_format (drawable),
+                      x, y, NULL, pixel, format,
                       GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
 
   return TRUE;
diff --git a/app/core/gimpimage-crop.c b/app/core/gimpimage-crop.c
index cb36f40..36a20d9 100644
--- a/app/core/gimpimage-crop.c
+++ b/app/core/gimpimage-crop.c
@@ -48,26 +48,21 @@ typedef enum
 
 
 typedef AutoCropType (* ColorsEqualFunc) (guchar *col1,
-                                          guchar *col2,
-                                          gint    bytes);
+                                          guchar *col2);
 
 
 /*  local function prototypes  */
 
 static AutoCropType gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
-                                                   gint          bytes,
-                                                   gboolean      has_alpha,
                                                    guchar       *color,
                                                    gint          x1,
                                                    gint          x2,
                                                    gint          y1,
                                                    gint          y2);
 static gint         gimp_image_crop_colors_equal  (guchar       *col1,
-                                                   guchar       *col2,
-                                                   gint          bytes);
+                                                   guchar       *col2);
 static gint         gimp_image_crop_colors_alpha  (guchar       *col1,
-                                                   guchar       *col2,
-                                                   gint          bytes);
+                                                   guchar       *col2);
 
 
 /*  public functions  */
@@ -310,11 +305,9 @@ gimp_image_crop_auto_shrink (GimpImage *image,
   GeglRectangle    rect;
   ColorsEqualFunc  colors_equal_func;
   guchar           bgcolor[MAX_CHANNELS] = { 0, 0, 0, 0 };
-  gboolean         has_alpha;
   guchar          *buf = NULL;
   gint             width, height;
   const Babl      *format;
-  gint             bytes;
   gint             x, y, abort;
   gboolean         retval = FALSE;
 
@@ -349,13 +342,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
 
   gimp_pickable_flush (pickable);
 
-  format    = gimp_pickable_get_format (pickable);
-  bytes     = babl_format_get_bytes_per_pixel (format);
-  has_alpha = babl_format_has_alpha (format);
+  format = babl_format ("R'G'B'A u8");
 
-  switch (gimp_image_crop_guess_bgcolor (pickable,
-                                         bytes, has_alpha, bgcolor,
-                                         x1, x2-1, y1, y2-1))
+  switch (gimp_image_crop_guess_bgcolor (pickable, bgcolor,
+                                         x1, x2 - 1, y1, y2 - 1))
     {
     case AUTO_CROP_ALPHA:
       colors_equal_func = (ColorsEqualFunc) gimp_image_crop_colors_alpha;
@@ -377,7 +367,7 @@ gimp_image_crop_auto_shrink (GimpImage *image,
    * the smaller side first instead of defaulting to width    --Sven
    */
 
-  buf = g_malloc (MAX (width, height) * bytes);
+  buf = g_malloc (MAX (width, height) * 4);
 
   /* Check how many of the top lines are uniform/transparent. */
   rect.x      = x1;
@@ -389,11 +379,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
   for (y = y1; y < y2 && !abort; y++)
     {
       rect.y = y;
-      /* XXX use an appropriate format here */
-      gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
+      gegl_buffer_get (buffer, &rect, 1.0, format, buf,
                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
       for (x = 0; x < width && !abort; x++)
-        abort = !(colors_equal_func) (bgcolor, buf + x * bytes, bytes);
+        abort = ! colors_equal_func (bgcolor, buf + x * 4);
     }
   if (y == y2 && !abort)
     goto FINISH;
@@ -409,10 +398,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
   for (y = y2; y > y1 && !abort; y--)
     {
       rect.y = y - 1;
-      gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
+      gegl_buffer_get (buffer, &rect, 1.0, format, buf,
                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
       for (x = 0; x < width && !abort; x++)
-        abort = !(colors_equal_func) (bgcolor, buf + x * bytes, bytes);
+        abort = ! colors_equal_func  (bgcolor, buf + x * 4);
     }
   y2 = y + 1;
 
@@ -429,10 +418,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
   for (x = x1; x < x2 && !abort; x++)
     {
       rect.x = x;
-      gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
+      gegl_buffer_get (buffer, &rect, 1.0, format, buf,
                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
       for (y = 0; y < height && !abort; y++)
-        abort = !(colors_equal_func) (bgcolor, buf + y * bytes, bytes);
+        abort = ! colors_equal_func (bgcolor, buf + y * 4);
     }
   x1 = x - 1;
 
@@ -446,10 +435,10 @@ gimp_image_crop_auto_shrink (GimpImage *image,
   for (x = x2; x > x1 && !abort; x--)
     {
       rect.x = x - 1;
-      gegl_buffer_get (buffer, &rect, 1.0, NULL, buf,
+      gegl_buffer_get (buffer, &rect, 1.0, format, buf,
                        GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
       for (y = 0; y < height && !abort; y++)
-        abort = !(colors_equal_func) (bgcolor, buf + y * bytes, bytes);
+        abort = ! colors_equal_func (bgcolor, buf + y * 4);
     }
   x2 = x + 1;
 
@@ -472,59 +461,53 @@ gimp_image_crop_auto_shrink (GimpImage *image,
 
 static AutoCropType
 gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
-                               gint          bytes,
-                               gboolean      has_alpha,
                                guchar       *color,
                                gint          x1,
                                gint          x2,
                                gint          y1,
                                gint          y2)
 {
-  guchar  tl[4];
-  guchar  tr[4];
-  guchar  bl[4];
-  guchar  br[4];
-  gint    i;
-
-  for (i = 0; i < bytes; i++)
+  const Babl *format = babl_format ("R'G'B'A u8");
+  guchar      tl[4];
+  guchar      tr[4];
+  guchar      bl[4];
+  guchar      br[4];
+  gint        i;
+
+  for (i = 0; i < 4; i++)
     color[i] = 0;
 
   /* First check if there's transparency to crop. If not, guess the
    * background-color to see if at least 2 corners are equal.
    */
 
-  if (! gimp_pickable_get_pixel_at (pickable, x1, y1, tl) ||
-      ! gimp_pickable_get_pixel_at (pickable, x1, y2, tr) ||
-      ! gimp_pickable_get_pixel_at (pickable, x2, y1, bl) ||
-      ! gimp_pickable_get_pixel_at (pickable, x2, y2, br))
+  if (! gimp_pickable_get_pixel_at (pickable, x1, y1, format, tl) ||
+      ! gimp_pickable_get_pixel_at (pickable, x1, y2, format, tr) ||
+      ! gimp_pickable_get_pixel_at (pickable, x2, y1, format, bl) ||
+      ! gimp_pickable_get_pixel_at (pickable, x2, y2, format, br))
     {
       return AUTO_CROP_NOTHING;
     }
 
-  if (has_alpha)
+  if ((tl[ALPHA] == 0 && tr[ALPHA] == 0) ||
+      (tl[ALPHA] == 0 && bl[ALPHA] == 0) ||
+      (tr[ALPHA] == 0 && br[ALPHA] == 0) ||
+      (bl[ALPHA] == 0 && br[ALPHA] == 0))
     {
-      gint alpha = bytes - 1;
-
-      if ((tl[alpha] == 0 && tr[alpha] == 0) ||
-          (tl[alpha] == 0 && bl[alpha] == 0) ||
-          (tr[alpha] == 0 && br[alpha] == 0) ||
-          (bl[alpha] == 0 && br[alpha] == 0))
-        {
-          return AUTO_CROP_ALPHA;
-        }
+      return AUTO_CROP_ALPHA;
     }
 
-  if (gimp_image_crop_colors_equal (tl, tr, bytes) ||
-      gimp_image_crop_colors_equal (tl, bl, bytes))
+  if (gimp_image_crop_colors_equal (tl, tr) ||
+      gimp_image_crop_colors_equal (tl, bl))
     {
-      memcpy (color, tl, bytes);
+      memcpy (color, tl, 4);
       return AUTO_CROP_COLOR;
     }
 
-  if (gimp_image_crop_colors_equal (br, bl, bytes) ||
-      gimp_image_crop_colors_equal (br, tr, bytes))
+  if (gimp_image_crop_colors_equal (br, bl) ||
+      gimp_image_crop_colors_equal (br, tr))
     {
-      memcpy (color, br, bytes);
+      memcpy (color, br, 4);
       return AUTO_CROP_COLOR;
     }
 
@@ -533,12 +516,11 @@ gimp_image_crop_guess_bgcolor (GimpPickable *pickable,
 
 static int
 gimp_image_crop_colors_equal (guchar *col1,
-                              guchar *col2,
-                              gint    bytes)
+                              guchar *col2)
 {
   gint b;
 
-  for (b = 0; b < bytes; b++)
+  for (b = 0; b < 4; b++)
     {
       if (col1[b] != col2[b])
         return FALSE;
@@ -549,8 +531,7 @@ gimp_image_crop_colors_equal (guchar *col1,
 
 static gboolean
 gimp_image_crop_colors_alpha (guchar *dummy,
-                              guchar *col,
-                              gint    bytes)
+                              guchar *col)
 {
-  return (col[bytes - 1] == 0);
+  return (col[ALPHA] == 0);
 }
diff --git a/app/core/gimpimagemap.c b/app/core/gimpimagemap.c
index 3e1c4dd..a2d9ddd 100644
--- a/app/core/gimpimagemap.c
+++ b/app/core/gimpimagemap.c
@@ -96,7 +96,8 @@ static TileManager   * gimp_image_map_get_tiles       (GimpPickable        *pick
 static gboolean        gimp_image_map_get_pixel_at    (GimpPickable        *pickable,
                                                        gint                 x,
                                                        gint                 y,
-                                                       guchar              *pixel);
+                                                       const Babl          *format,
+                                                       gpointer             pixel);
 
 static void            gimp_image_map_update_undo_buffer
                                                       (GimpImageMap        *image_map,
@@ -280,7 +281,8 @@ static gboolean
 gimp_image_map_get_pixel_at (GimpPickable *pickable,
                              gint          x,
                              gint          y,
-                             guchar       *pixel)
+                             const Babl   *format,
+                             gpointer      pixel)
 {
   GimpImageMap *image_map = GIMP_IMAGE_MAP (pickable);
   GimpItem     *item      = GIMP_ITEM (image_map->drawable);
@@ -301,8 +303,7 @@ gimp_image_map_get_pixel_at (GimpPickable *pickable,
             {
               gegl_buffer_sample (image_map->undo_buffer,
                                   x - offset_x, y - offset_y,
-                                  NULL, pixel,
-                                  gimp_drawable_get_format (image_map->drawable),
+                                  NULL, pixel, format,
                                   GEGL_SAMPLER_NEAREST,
                                   GEGL_ABYSS_NONE);
 
@@ -311,7 +312,7 @@ gimp_image_map_get_pixel_at (GimpPickable *pickable,
         }
 
       return gimp_pickable_get_pixel_at (GIMP_PICKABLE (image_map->drawable),
-                                         x, y, pixel);
+                                         x, y, format, pixel);
     }
 
   return FALSE;
diff --git a/app/core/gimppickable.c b/app/core/gimppickable.c
index 138a69b..319a80c 100644
--- a/app/core/gimppickable.c
+++ b/app/core/gimppickable.c
@@ -155,17 +155,21 @@ gboolean
 gimp_pickable_get_pixel_at (GimpPickable *pickable,
                             gint          x,
                             gint          y,
-                            guchar       *pixel)
+                            const Babl   *format,
+                            gpointer      pixel)
 {
   GimpPickableInterface *pickable_iface;
 
   g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
   g_return_val_if_fail (pixel != NULL, FALSE);
 
+  if (! format)
+    format = gimp_pickable_get_format (pickable);
+
   pickable_iface = GIMP_PICKABLE_GET_INTERFACE (pickable);
 
   if (pickable_iface->get_pixel_at)
-    return pickable_iface->get_pixel_at (pickable, x, y, pixel);
+    return pickable_iface->get_pixel_at (pickable, x, y, format, pixel);
 
   return FALSE;
 }
@@ -181,7 +185,7 @@ gimp_pickable_get_color_at (GimpPickable *pickable,
   g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
   g_return_val_if_fail (color != NULL, FALSE);
 
-  if (! gimp_pickable_get_pixel_at (pickable, x, y, pixel))
+  if (! gimp_pickable_get_pixel_at (pickable, x, y, NULL, pixel))
     return FALSE;
 
   gimp_rgba_set_pixel (color, gimp_pickable_get_format (pickable), pixel);
@@ -216,17 +220,14 @@ gimp_pickable_pick_color (GimpPickable *pickable,
                           gint         *color_index)
 {
   const Babl *format;
-  const Babl *fish;
   guchar      pixel[4];
-  guchar      col[4];
 
   g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), FALSE);
 
-  if (! gimp_pickable_get_pixel_at (pickable, x, y, pixel))
-    return FALSE;
+  format = babl_format ("R'G'B'A u8");
 
-  format = gimp_pickable_get_format (pickable);
-  fish   = babl_fish (format, babl_format ("R'G'B'A u8"));
+  if (! gimp_pickable_get_pixel_at (pickable, x, y, format, pixel))
+    return FALSE;
 
   if (sample_average)
     {
@@ -237,41 +238,42 @@ gimp_pickable_pick_color (GimpPickable *pickable,
 
       for (i = x - radius; i <= x + radius; i++)
         for (j = y - radius; j <= y + radius; j++)
-          if (gimp_pickable_get_pixel_at (pickable, i, j, pixel))
+          if (gimp_pickable_get_pixel_at (pickable, i, j, format, pixel))
             {
               count++;
 
-              babl_process (fish, pixel, col, 1);
-
-              color_avg[RED]   += col[RED];
-              color_avg[GREEN] += col[GREEN];
-              color_avg[BLUE]  += col[BLUE];
-              color_avg[ALPHA] += col[ALPHA];
+              color_avg[RED]   += pixel[RED];
+              color_avg[GREEN] += pixel[GREEN];
+              color_avg[BLUE]  += pixel[BLUE];
+              color_avg[ALPHA] += pixel[ALPHA];
             }
 
-      col[RED]   = (guchar) ((color_avg[RED]   + count / 2) / count);
-      col[GREEN] = (guchar) ((color_avg[GREEN] + count / 2) / count);
-      col[BLUE]  = (guchar) ((color_avg[BLUE]  + count / 2) / count);
-      col[ALPHA] = (guchar) ((color_avg[ALPHA] + count / 2) / count);
+      pixel[RED]   = (guchar) ((color_avg[RED]   + count / 2) / count);
+      pixel[GREEN] = (guchar) ((color_avg[GREEN] + count / 2) / count);
+      pixel[BLUE]  = (guchar) ((color_avg[BLUE]  + count / 2) / count);
+      pixel[ALPHA] = (guchar) ((color_avg[ALPHA] + count / 2) / count);
     }
-  else
-    {
-      babl_process (fish, pixel, col, 1);
-    }
-
 
   gimp_rgba_set_uchar (color,
-                       col[RED],
-                       col[GREEN],
-                       col[BLUE],
-                       col[ALPHA]);
+                       pixel[RED],
+                       pixel[GREEN],
+                       pixel[BLUE],
+                       pixel[ALPHA]);
 
   if (color_index)
     {
+      format = gimp_pickable_get_format (pickable);
+
       if (babl_format_is_palette (format) && ! sample_average)
-        *color_index = pixel[0];
+        {
+          gimp_pickable_get_pixel_at (pickable, x, y, format, pixel);
+
+          *color_index = pixel[0];
+        }
       else
-        *color_index = -1;
+        {
+          *color_index = -1;
+        }
     }
 
   return TRUE;
diff --git a/app/core/gimppickable.h b/app/core/gimppickable.h
index 2477bd5..c894a81 100644
--- a/app/core/gimppickable.h
+++ b/app/core/gimppickable.h
@@ -44,7 +44,8 @@ struct _GimpPickableInterface
   gboolean        (* get_pixel_at)          (GimpPickable *pickable,
                                              gint          x,
                                              gint          y,
-                                             guchar       *pixel);
+                                             const Babl   *format,
+                                             gpointer      pixel);
   gint            (* get_opacity_at)        (GimpPickable *pickable,
                                              gint          x,
                                              gint          y);
@@ -62,7 +63,8 @@ TileManager   * gimp_pickable_get_tiles             (GimpPickable *pickable);
 gboolean        gimp_pickable_get_pixel_at          (GimpPickable *pickable,
                                                      gint          x,
                                                      gint          y,
-                                                     guchar       *pixel);
+                                                     const Babl   *format,
+                                                     gpointer      pixel);
 gboolean        gimp_pickable_get_color_at          (GimpPickable *pickable,
                                                      gint          x,
                                                      gint          y,
diff --git a/app/core/gimpprojection.c b/app/core/gimpprojection.c
index 406606c..028c485 100644
--- a/app/core/gimpprojection.c
+++ b/app/core/gimpprojection.c
@@ -67,7 +67,8 @@ static TileManager * gimp_projection_get_tiles           (GimpPickable    *picka
 static gboolean    gimp_projection_get_pixel_at          (GimpPickable    *pickable,
                                                           gint             x,
                                                           gint             y,
-                                                          guchar          *pixel);
+                                                          const Babl      *format,
+                                                          gpointer         pixel);
 static gint        gimp_projection_get_opacity_at        (GimpPickable    *pickable,
                                                           gint             x,
                                                           gint             y);
@@ -338,7 +339,8 @@ static gboolean
 gimp_projection_get_pixel_at (GimpPickable *pickable,
                               gint          x,
                               gint          y,
-                              guchar       *pixel)
+                              const Babl   *format,
+                              gpointer      pixel)
 {
   GeglBuffer *buffer = gimp_projection_get_buffer (pickable);
 
@@ -348,8 +350,7 @@ gimp_projection_get_pixel_at (GimpPickable *pickable,
       y >= gegl_buffer_get_height (buffer))
     return FALSE;
 
-  gegl_buffer_sample (buffer, x, y, NULL, pixel,
-                      gimp_projection_get_format (pickable),
+  gegl_buffer_sample (buffer, x, y, NULL, pixel, format,
                       GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
 
   return TRUE;



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