[Gimp-developer] automatic gimp-levels

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

 



Hi,

On a GIMP BBS I've heard that script-fu scripts cannot get the
effect of pushing the "Auto" button in the Image->Colors->Levels
dialog.  Here is a patch to add the procedure gimp-levels-auto,
an automatic version of gimp-levels.  I believe that all
features of the GIMP should be exported to script-fu scripts.
Comments?

-- 
KAJIYAMA, Tamito <kajiyama@xxxxxxxxxxxxxxxxxxxxxxxx>

diff -ru gimp-1.2.1.orig/app/color_cmds.c gimp-1.2.1/app/color_cmds.c
--- gimp-1.2.1.orig/app/color_cmds.c	Mon Dec 25 01:40:44 2000
+++ gimp-1.2.1/app/color_cmds.c	Thu Mar 15 22:15:42 2001
@@ -35,8 +35,11 @@
 #include "lut_funcs.h"
 #include "threshold.h"
 
+#include "libgimp/gimpmath.h" /* for fabs() */
+
 static ProcRecord brightness_contrast_proc;
 static ProcRecord levels_proc;
+static ProcRecord levels_auto_proc;
 static ProcRecord posterize_proc;
 static ProcRecord desaturate_proc;
 static ProcRecord equalize_proc;
@@ -53,6 +56,7 @@
 {
   procedural_db_register (&brightness_contrast_proc);
   procedural_db_register (&levels_proc);
+  procedural_db_register (&levels_auto_proc);
   procedural_db_register (&posterize_proc);
   procedural_db_register (&desaturate_proc);
   procedural_db_register (&equalize_proc);
@@ -308,6 +312,157 @@
   NULL,
   { { levels_invoker } }
 };
+
+/* levels_auto */
+static Argument *
+levels_auto_invoker (Argument *args)
+{
+  gboolean success = TRUE;
+  GimpDrawable *drawable;
+  gint32 channel;
+  PixelRegion srcPR, destPR;
+  int x1, y1, x2, y2;
+  GimpLut *lut;
+  int i;
+  int low_input[5];
+  int high_input[5];
+  double gamma[5];
+  int low_output[5];
+  int high_output[5];
+  GimpHistogram *hist;
+  gdouble count, new_count, percentage, next_percentage;
+
+  drawable = gimp_drawable_get_ID (args[0].value.pdb_int);
+  if (drawable == NULL)
+    success = FALSE;
+
+  channel = args[1].value.pdb_int;
+  if (channel < VALUE_LUT || channel > ALPHA_LUT)
+    success = FALSE;
+
+  if (success)
+    {
+      if (gimp_drawable_is_indexed (drawable) ||
+	  (!gimp_drawable_has_alpha (drawable) && channel == ALPHA_LUT) ||
+	  (gimp_drawable_is_gray (drawable) && channel != GRAY_LUT
+					    && channel != ALPHA_LUT))
+	success = FALSE;
+      else
+	{
+	  for (i = 0; i < 5; i++)
+	    {
+	      low_input[i] = 0;
+	      high_input[i] = 255;
+	      low_output[i] = 0;
+	      high_output[i] = 255;
+	      gamma[i] = 1.0;
+	    }
+
+	  hist  = gimp_histogram_new ();
+	  gimp_histogram_calculate_drawable (hist, drawable);
+
+	  count = gimp_histogram_get_count (hist, 0, 255);
+
+	  if (count == 0.0)
+	    {
+	      low_input[channel] = 0;
+	      high_input[channel] = 0;
+	    }
+	  else
+	    {
+	      /*  Set the low input  */
+	      new_count = 0.0;
+	      for (i = 0; i < 255; i++)
+		{
+		  new_count += gimp_histogram_get_value(hist, channel, i);
+		  percentage = new_count / count;
+		  next_percentage =
+		    (new_count + gimp_histogram_get_value (hist,
+							   channel,
+							   i + 1)) / count;
+		  if (fabs (percentage - 0.006) <
+		      fabs (next_percentage - 0.006))
+		    {
+		      low_input[channel] = i + 1;
+		      break;
+		    }
+		}
+	      /*  Set the high input  */
+	      new_count = 0.0;
+	      for (i = 255; i > 0; i--)
+		{
+		  new_count += gimp_histogram_get_value(hist, channel, i);
+		  percentage = new_count / count;
+		  next_percentage =
+		    (new_count + gimp_histogram_get_value (hist,
+							   channel,
+							   i - 1)) / count;
+		  if (fabs (percentage - 0.006) <
+		      fabs (next_percentage - 0.006))
+		    {
+		      high_input[channel] = i - 1;
+		      break;
+		    }
+		}
+	    }
+
+	  gimp_histogram_free (hist);
+    
+	  /* setup the lut */
+	  lut = levels_lut_new (gamma, low_input, high_input,
+				low_output, high_output,
+				gimp_drawable_bytes (drawable));
+    
+	  /* The application should occur only within selection bounds */
+	  gimp_drawable_mask_bounds (drawable, &x1, &y1, &x2, &y2);
+    
+	  pixel_region_init (&srcPR, gimp_drawable_data (drawable),
+			     x1, y1, (x2 - x1), (y2 - y1), FALSE);
+	  pixel_region_init (&destPR, gimp_drawable_shadow (drawable),
+			     x1, y1, (x2 - x1), (y2 - y1), TRUE);
+    
+	  pixel_regions_process_parallel ((p_func) gimp_lut_process, lut, 2,
+					  &srcPR, &destPR);
+    
+	  gimp_lut_free(lut);
+	  gimp_drawable_merge_shadow (drawable, TRUE);
+	  drawable_update (drawable, x1, y1, (x2 - x1), (y2 - y1));
+	}
+    }
+
+  return procedural_db_return_args (&levels_auto_proc, success);
+}
+
+static ProcArg levels_auto_inargs[] =
+{
+  {
+    PDB_DRAWABLE,
+    "drawable",
+    "The drawable"
+  },
+  {
+    PDB_INT32,
+    "channel",
+    "The channel to modify: { VALUE_LUT (0), RED_LUT (1), GREEN_LUT (2), BLUE_LUT (3), ALPHA_LUT (4) }"
+  },
+};
+
+static ProcRecord levels_auto_proc =
+{
+  "gimp_levels_auto",
+  "Modifies intensity levels in the specified drawable.",
+  "This tool automatically adjusts intensity levels in the specified drawable. This tool is only valid on RGB color and grayscale images. It will not operate on indexed drawables.",
+  "Spencer Kimball & Peter Mattis",
+  "Spencer Kimball & Peter Mattis",
+  "1995-1996",
+  PDB_INTERNAL,
+  2,
+  levels_auto_inargs,
+  0,
+  NULL,
+  { { levels_auto_invoker } }
+};
+/* end of levels_auto */
 
 static Argument *
 posterize_invoker (Argument *args)


[Index of Archives]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [GIMP for Windows]     [KDE]     [GEGL]     [Gimp's Home]     [Gimp on GUI]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux