[gimp/gimp-2-8] Bug 622054 - Levels Tool gray point picker causes lockup



commit e3a524e435ba36693042e4054a03e8267b943025
Author: Michael Natterer <mitch gimp org>
Date:   Wed Mar 27 22:28:29 2013 +0100

    Bug 622054 - Levels Tool gray point picker causes lockup
    
    Bail out in gimp_levels_config_adjust_by_colors() if pure
    back or white was picked as gray (gamma).
    (cherry picked from commit c865d8f1416a6917f120f7aaaa99b9aed7b0f280)

 app/gegl/gimplevelsconfig.c |   23 +++++++++++++++++------
 app/tests/test-core.c       |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 6 deletions(-)
---
diff --git a/app/gegl/gimplevelsconfig.c b/app/gegl/gimplevelsconfig.c
index 81f52d8..0ae85f6 100644
--- a/app/gegl/gimplevelsconfig.c
+++ b/app/gegl/gimplevelsconfig.c
@@ -565,24 +565,35 @@ gimp_levels_config_adjust_by_colors (GimpLevelsConfig     *config,
 
       range = config->high_input[channel] - config->low_input[channel];
       if (range <= 0)
-        return;
+        goto out;
 
       input -= config->low_input[channel];
       if (input < 0)
-        return;
+        goto out;
 
       /* Normalize input and lightness */
       inten = input / range;
-      out_light = lightness/ range;
-
-      if (out_light <= 0)
-        return;
+      out_light = lightness / range;
+
+      /* See bug 622054: picking pure black or white as gamma doesn't
+       * work. But we cannot compare to 0.0 or 1.0 because cpus and
+       * compilers are shit. If you try to check out_light using
+       * printf() it will give exact 0.0 or 1.0 anyway, probably
+       * because the generated code is different and out_light doesn't
+       * live in a register. That must be why the cpu/compiler mafia
+       * invented epsilon and defined this shit to be the programmer's
+       * responsibility.
+       */
+      if (out_light <= 0.0001 || out_light >= 0.9999)
+        goto out;
 
       /* Map selected color to corresponding lightness */
       config->gamma[channel] = log (inten) / log (out_light);
+      config->gamma[channel] = CLAMP (config->gamma[channel], 0.1, 10.0);
       g_object_notify (G_OBJECT (config), "gamma");
     }
 
+ out:
   g_object_thaw_notify (G_OBJECT (config));
 }
 
diff --git a/app/tests/test-core.c b/app/tests/test-core.c
index dc94336..7fc652b 100644
--- a/app/tests/test-core.c
+++ b/app/tests/test-core.c
@@ -27,6 +27,8 @@
 #include "core/gimpimage.h"
 #include "core/gimplayer.h"
 
+#include "operations/gimplevelsconfig.h"
+
 #include "tests.h"
 
 #include "gimp-app-test-utils.h"
@@ -221,6 +223,39 @@ remove_layer (GimpTestFixture *fixture,
   g_assert_cmpint (gimp_image_get_n_layers (image), ==, 0);
 }
 
+/**
+ * white_graypoint_in_red_levels:
+ * @fixture:
+ * @data:
+ *
+ * Makes sure the levels algorithm can handle when the graypoint is
+ * white. It's easy to get a divide by zero problem when trying to
+ * calculate what gamma will give a white graypoint.
+ **/
+static void
+white_graypoint_in_red_levels (GimpTestFixture *fixture,
+                               gconstpointer    data)
+{
+  GimpRGB              black   = { 0, 0, 0, 0 };
+  GimpRGB              gray    = { 1, 1, 1, 1 };
+  GimpRGB              white   = { 1, 1, 1, 1 };
+  GimpHistogramChannel channel = GIMP_HISTOGRAM_RED;
+  GimpLevelsConfig    *config;
+
+  config = g_object_new (GIMP_TYPE_LEVELS_CONFIG, NULL);
+
+  gimp_levels_config_adjust_by_colors (config,
+                                       channel,
+                                       &black,
+                                       &gray,
+                                       &white);
+
+  /* Make sure we didn't end up with an invalid gamma value */
+  g_object_set (config,
+                "gamma", config->gamma[channel],
+                NULL);
+}
+
 int
 main (int    argc,
       char **argv)
@@ -242,6 +277,7 @@ main (int    argc,
   ADD_IMAGE_TEST (add_layer);
   ADD_IMAGE_TEST (remove_layer);
   ADD_IMAGE_TEST (rotate_non_overlapping);
+  ADD_TEST (white_graypoint_in_red_levels);
 
   /* Run the tests */
   result = g_test_run ();


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