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)