home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / levels.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  43.1 KB  |  1,592 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <errno.h>
  25.  
  26. #include <glib.h>
  27.  
  28. #include "apptypes.h"
  29.  
  30. #include "appenv.h"
  31. #include "drawable.h"
  32. #include "gdisplay.h"
  33. #include "histogramwidget.h"
  34. #include "gimphistogram.h"
  35. #include "gimpui.h"
  36. #include "image_map.h"
  37. #include "levels.h"
  38. #include "gimplut.h"
  39. #include "lut_funcs.h"
  40.  
  41. #include "libgimp/gimpenv.h"
  42. #include "libgimp/gimpmath.h"
  43.  
  44. #include "libgimp/gimpintl.h"
  45.  
  46. #define LOW_INPUT          0x1
  47. #define GAMMA              0x2
  48. #define HIGH_INPUT         0x4
  49. #define LOW_OUTPUT         0x8
  50. #define HIGH_OUTPUT        0x10
  51. #define INPUT_LEVELS       0x20
  52. #define OUTPUT_LEVELS      0x40
  53. #define INPUT_SLIDERS      0x80
  54. #define OUTPUT_SLIDERS     0x100
  55. #define DRAW               0x200
  56. #define ALL                0xFFF
  57.  
  58. #define DA_WIDTH         256
  59. #define DA_HEIGHT        25
  60. #define GRADIENT_HEIGHT  15
  61. #define CONTROL_HEIGHT   DA_HEIGHT - GRADIENT_HEIGHT
  62. #define HISTOGRAM_WIDTH  256
  63. #define HISTOGRAM_HEIGHT 150
  64.  
  65. #define LEVELS_DA_MASK  GDK_EXPOSURE_MASK | \
  66.                         GDK_ENTER_NOTIFY_MASK | \
  67.             GDK_BUTTON_PRESS_MASK | \
  68.             GDK_BUTTON_RELEASE_MASK | \
  69.             GDK_BUTTON1_MOTION_MASK | \
  70.             GDK_POINTER_MOTION_HINT_MASK
  71.  
  72. /*  the levels structures  */
  73.  
  74. typedef struct _Levels Levels;
  75.  
  76. struct _Levels
  77. {
  78.   gint x, y;    /*  coords for last mouse click  */
  79. };
  80.  
  81. typedef struct _LevelsDialog LevelsDialog;
  82.  
  83. struct _LevelsDialog
  84. {
  85.   GtkWidget       *shell;
  86.  
  87.   GtkAdjustment   *low_input_data;
  88.   GtkAdjustment   *gamma_data;
  89.   GtkAdjustment   *high_input_data;
  90.   GtkAdjustment   *low_output_data;
  91.   GtkAdjustment   *high_output_data;
  92.  
  93.   GtkWidget       *input_levels_da[2];
  94.   GtkWidget       *output_levels_da[2];
  95.   GtkWidget       *channel_menu;
  96.  
  97.   HistogramWidget *histogram;
  98.   GimpHistogram   *hist;
  99.  
  100.   GimpDrawable   *drawable;
  101.  
  102.   ImageMap        image_map;
  103.  
  104.   gint            color;
  105.   gint            channel;
  106.   gint            low_input[5];
  107.   gdouble         gamma[5];
  108.   gint            high_input[5];
  109.   gint            low_output[5];
  110.   gint            high_output[5];
  111.   gboolean        preview;
  112.  
  113.   gint            active_slider;
  114.   gint            slider_pos[5];  /*  positions for the five sliders  */
  115.  
  116.   guchar          input[5][256]; /* this is used only by the gui */
  117.  
  118.   GimpLut        *lut;
  119. };
  120.  
  121. /*  the levels tool options  */
  122. static ToolOptions *levels_options = NULL;
  123.  
  124. /*  the levels tool dialog  */
  125. static LevelsDialog *levels_dialog = NULL;
  126.  
  127. /*  the levels file dialog  */
  128. static GtkWidget *file_dlg = NULL;
  129. static gboolean   load_save;
  130.  
  131. static GtkWidget *color_option_items[5];
  132.  
  133. /*  levels action functions  */
  134. static void   levels_control (Tool *, ToolAction, gpointer);
  135.  
  136. static LevelsDialog * levels_dialog_new (void);
  137.  
  138. static void   levels_calculate_transfers           (LevelsDialog *);
  139. static void   levels_update                        (LevelsDialog *, gint);
  140. static void   levels_preview                       (LevelsDialog *);
  141. static void   levels_channel_callback              (GtkWidget *, gpointer);
  142. static void   levels_reset_callback                (GtkWidget *, gpointer);
  143. static void   levels_ok_callback                   (GtkWidget *, gpointer);
  144. static void   levels_cancel_callback               (GtkWidget *, gpointer);
  145. static void   levels_auto_callback                 (GtkWidget *, gpointer);
  146. static void   levels_load_callback                 (GtkWidget *, gpointer);
  147. static void   levels_save_callback                 (GtkWidget *, gpointer);
  148. static void   levels_preview_update                (GtkWidget *, gpointer);
  149. static void   levels_low_input_adjustment_update   (GtkAdjustment *, gpointer);
  150. static void   levels_gamma_adjustment_update       (GtkAdjustment *, gpointer);
  151. static void   levels_high_input_adjustment_update  (GtkAdjustment *, gpointer);
  152. static void   levels_low_output_adjustment_update  (GtkAdjustment *, gpointer);
  153. static void   levels_high_output_adjustment_update (GtkAdjustment *, gpointer);
  154. static gint   levels_input_da_events               (GtkWidget *, GdkEvent *, 
  155.                             LevelsDialog *);
  156. static gint   levels_output_da_events              (GtkWidget *, GdkEvent *,
  157.                             LevelsDialog *);
  158.  
  159. static void   file_dialog_create                   (GtkWidget *);
  160. static void   file_dialog_ok_callback              (GtkWidget *, gpointer);
  161. static void   file_dialog_cancel_callback          (GtkWidget *, gpointer);
  162.  
  163. static gboolean  levels_read_from_file             (FILE *f);
  164. static void      levels_write_to_file              (FILE *f);
  165.  
  166.  
  167. /*  levels action functions  */
  168.  
  169. static void
  170. levels_control (Tool       *tool,
  171.         ToolAction  action,
  172.         gpointer    gdisp_ptr)
  173. {
  174.   switch (action)
  175.     {
  176.     case PAUSE:
  177.       break;
  178.  
  179.     case RESUME:
  180.       break;
  181.  
  182.     case HALT:
  183.       levels_dialog_hide ();
  184.       break;
  185.  
  186.     default:
  187.       break;
  188.     }
  189. }
  190.  
  191. Tool *
  192. tools_new_levels (void)
  193. {
  194.   Tool * tool;
  195.   Levels * private;
  196.  
  197.   /*  The tool options  */
  198.   if (! levels_options)
  199.     {
  200.       levels_options = tool_options_new (_("Levels"));
  201.       tools_register (LEVELS, levels_options);
  202.     }
  203.  
  204.   tool = tools_new_tool (LEVELS);
  205.   private = g_new0 (Levels, 1);
  206.  
  207.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  208.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  209.  
  210.   tool->private = (void *) private;
  211.  
  212.   tool->control_func = levels_control;
  213.  
  214.   return tool;
  215. }
  216.  
  217. void
  218. levels_dialog_hide (void)
  219. {
  220.   if (levels_dialog)
  221.     levels_cancel_callback (NULL, (gpointer) levels_dialog);
  222. }
  223.  
  224. void
  225. tools_free_levels (Tool *tool)
  226. {
  227.   Levels * private;
  228.  
  229.   private = (Levels *) tool->private;
  230.  
  231.   /*  Close the color select dialog  */
  232.   levels_dialog_hide ();
  233.  
  234.   g_free (private);
  235. }
  236.  
  237. void
  238. levels_initialize (GDisplay *gdisp)
  239. {
  240.   gint i;
  241.  
  242.   if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
  243.     {
  244.       g_message (_("Levels for indexed drawables cannot be adjusted."));
  245.       return;
  246.     }
  247.  
  248.   /*  The levels dialog  */
  249.   if (!levels_dialog)
  250.     levels_dialog = levels_dialog_new ();
  251.   else
  252.     if (!GTK_WIDGET_VISIBLE (levels_dialog->shell))
  253.       gtk_widget_show (levels_dialog->shell);
  254.  
  255.   /*  Initialize the values  */
  256.   levels_dialog->channel = GIMP_HISTOGRAM_VALUE;
  257.   for (i = 0; i < 5; i++)
  258.     {
  259.       levels_dialog->low_input[i]   = 0;
  260.       levels_dialog->gamma[i]       = 1.0;
  261.       levels_dialog->high_input[i]  = 255;
  262.       levels_dialog->low_output[i]  = 0;
  263.       levels_dialog->high_output[i] = 255;
  264.     }
  265.  
  266.   levels_dialog->drawable  = gimage_active_drawable (gdisp->gimage);
  267.   levels_dialog->color     = drawable_color (levels_dialog->drawable);
  268.   levels_dialog->image_map = image_map_create (gdisp, levels_dialog->drawable);
  269.  
  270.   /* check for alpha channel */
  271.   gtk_widget_set_sensitive (color_option_items[4],
  272.                 drawable_has_alpha (levels_dialog->drawable));
  273.   
  274.   /*  hide or show the channel menu based on image type  */
  275.   if (levels_dialog->color)
  276.     for (i = 0; i < 4; i++) 
  277.        gtk_widget_set_sensitive (color_option_items[i], TRUE);
  278.   else 
  279.     for (i = 1; i < 4; i++) 
  280.        gtk_widget_set_sensitive (color_option_items[i], FALSE);
  281.  
  282.   /* set the current selection */
  283.   gtk_option_menu_set_history (GTK_OPTION_MENU (levels_dialog->channel_menu),
  284.                    levels_dialog->channel);
  285.  
  286.  
  287.   levels_update (levels_dialog, LOW_INPUT | GAMMA | HIGH_INPUT | LOW_OUTPUT | HIGH_OUTPUT | DRAW);
  288.   levels_update (levels_dialog, INPUT_LEVELS | OUTPUT_LEVELS);
  289.  
  290.   gimp_histogram_calculate_drawable (levels_dialog->hist,
  291.                      levels_dialog->drawable);
  292.   histogram_widget_update (levels_dialog->histogram, levels_dialog->hist);
  293.   histogram_widget_range (levels_dialog->histogram, -1, -1);
  294. }
  295.  
  296. void
  297. levels_free (void)
  298. {
  299.   if (levels_dialog)
  300.     {
  301.       if (levels_dialog->image_map)
  302.     {
  303.       active_tool->preserve = TRUE;
  304.       image_map_abort (levels_dialog->image_map);
  305.       active_tool->preserve = FALSE;
  306.  
  307.       levels_dialog->image_map = NULL;
  308.     }
  309.       gtk_widget_destroy (levels_dialog->shell);
  310.     }
  311. }
  312.  
  313. /*******************/
  314. /*  Levels dialog  */
  315. /*******************/
  316.  
  317. static LevelsDialog *
  318. levels_dialog_new (void)
  319. {
  320.   LevelsDialog *ld;
  321.   GtkWidget *main_vbox;
  322.   GtkWidget *vbox;
  323.   GtkWidget *hbox;
  324.   GtkWidget *vbox2;
  325.   GtkWidget *label;
  326.   GtkWidget *frame;
  327.   GtkWidget *toggle;
  328.   GtkWidget *channel_hbox;
  329.   GtkWidget *hbbox;
  330.   GtkWidget *button;
  331.   GtkWidget *spinbutton;
  332.   GtkObject *data;
  333.  
  334.   ld = g_new0 (LevelsDialog, 1);
  335.   ld->channel = GIMP_HISTOGRAM_VALUE;
  336.   ld->preview = TRUE;
  337.   ld->lut     = gimp_lut_new ();
  338.   ld->hist    = gimp_histogram_new ();
  339.  
  340.   /*  The shell and main vbox  */
  341.   ld->shell = gimp_dialog_new (_("Levels"), "levels",
  342.                    tools_help_func, tool_info[LEVELS].private_tip,
  343.                    GTK_WIN_POS_NONE,
  344.                    FALSE, TRUE, FALSE,
  345.  
  346.                    _("OK"), levels_ok_callback,
  347.                    ld, NULL, NULL, TRUE, FALSE,
  348.                    _("Reset"), levels_reset_callback,
  349.                    ld, NULL, NULL, FALSE, FALSE,
  350.                    _("Cancel"), levels_cancel_callback,
  351.                    ld, NULL, NULL, FALSE, TRUE,
  352.  
  353.                    NULL);
  354.  
  355.   main_vbox = gtk_vbox_new (FALSE, 4);
  356.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
  357.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (ld->shell)->vbox), main_vbox);
  358.  
  359.   hbox = gtk_hbox_new (TRUE, 0);
  360.   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  361.   gtk_widget_show (hbox);
  362.  
  363.   vbox = gtk_vbox_new (FALSE, 4);
  364.   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
  365.  
  366.   /*  The option menu for selecting channels  */
  367.   channel_hbox = gtk_hbox_new (FALSE, 4);
  368.   gtk_box_pack_start (GTK_BOX (vbox), channel_hbox, FALSE, FALSE, 0);
  369.  
  370.   label = gtk_label_new (_("Modify Levels for Channel:"));
  371.   gtk_box_pack_start (GTK_BOX (channel_hbox), label, FALSE, FALSE, 0);
  372.   gtk_widget_show (label);
  373.  
  374.   ld->channel_menu = gimp_option_menu_new2
  375.     (FALSE, levels_channel_callback,
  376.      ld, (gpointer) ld->channel,
  377.  
  378.      _("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, &color_option_items[0],
  379.      _("Red"),   (gpointer) GIMP_HISTOGRAM_RED,   &color_option_items[1],
  380.      _("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, &color_option_items[2],
  381.      _("Blue"),  (gpointer) GIMP_HISTOGRAM_BLUE,  &color_option_items[3],
  382.      _("Alpha"), (gpointer) GIMP_HISTOGRAM_ALPHA, &color_option_items[4],
  383.  
  384.      NULL);
  385.   gtk_box_pack_start (GTK_BOX (channel_hbox), ld->channel_menu, FALSE, FALSE, 0);
  386.   gtk_widget_show (ld->channel_menu);
  387.  
  388.   gtk_widget_show (channel_hbox);
  389.  
  390.   /*  Horizontal box for input levels spinbuttons  */
  391.   hbox = gtk_hbox_new (FALSE, 4);
  392.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  393.  
  394.   label = gtk_label_new (_("Input Levels:"));
  395.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  396.   gtk_widget_show (label);
  397.  
  398.   /*  low input spin  */
  399.   data = gtk_adjustment_new (0, 0, 255, 1, 10, 10);
  400.   ld->low_input_data = GTK_ADJUSTMENT (data);
  401.  
  402.   spinbutton = gtk_spin_button_new (ld->low_input_data, 0.5, 0);
  403.   gtk_widget_set_usize (spinbutton, 50, -1);
  404.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  405.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  406.  
  407.   gtk_signal_connect (GTK_OBJECT (ld->low_input_data), "value_changed",
  408.                       GTK_SIGNAL_FUNC (levels_low_input_adjustment_update),
  409.                       ld);
  410.  
  411.   gtk_widget_show (spinbutton);
  412.  
  413.   /*  input gamma spin  */
  414.   data = gtk_adjustment_new (1, 0.1, 10, 0.1, 1, 1);
  415.   ld->gamma_data = GTK_ADJUSTMENT (data);
  416.  
  417.   spinbutton = gtk_spin_button_new (ld->gamma_data, 0.5, 2);
  418.   gtk_widget_set_usize (spinbutton, 50, -1);
  419.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  420.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  421.  
  422.   gtk_signal_connect (GTK_OBJECT (ld->gamma_data), "value_changed",
  423.               GTK_SIGNAL_FUNC (levels_gamma_adjustment_update),
  424.               ld);
  425.  
  426.   gtk_widget_show (spinbutton);
  427.  
  428.   /*  high input spin  */
  429.   data = gtk_adjustment_new (255, 0, 255, 1, 10, 10);
  430.   ld->high_input_data = GTK_ADJUSTMENT (data);
  431.  
  432.   spinbutton = gtk_spin_button_new (ld->high_input_data, 0.5, 0);
  433.   gtk_widget_set_usize (spinbutton, 50, -1);
  434.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  435.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  436.  
  437.   gtk_signal_connect (GTK_OBJECT (ld->high_input_data), "value_changed",
  438.               GTK_SIGNAL_FUNC (levels_high_input_adjustment_update),
  439.               ld);
  440.  
  441.   gtk_widget_show (spinbutton);
  442.   gtk_widget_show (hbox);
  443.  
  444.   /*  The levels histogram  */
  445.   hbox = gtk_hbox_new (TRUE, 2);
  446.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
  447.  
  448.   frame = gtk_frame_new (NULL);
  449.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  450.   gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, FALSE, 0);
  451.   ld->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT);
  452.   gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (ld->histogram));
  453.  
  454.   /* ignore button_events, since we don't want the user to be able to set the range */
  455.   gtk_widget_set_events (GTK_WIDGET (ld->histogram), 
  456.              (GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK));
  457.  
  458.   gtk_widget_show (GTK_WIDGET (ld->histogram));
  459.   gtk_widget_show (frame);
  460.   gtk_widget_show (hbox);
  461.  
  462.   /*  The input levels drawing area  */
  463.   hbox = gtk_hbox_new (TRUE, 2);
  464.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
  465.  
  466.   frame = gtk_frame_new (NULL);
  467.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  468.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  469.  
  470.   vbox2 = gtk_vbox_new (FALSE, 2);
  471.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  472.  
  473.   ld->input_levels_da[0] = gtk_preview_new (GTK_PREVIEW_COLOR);
  474.   gtk_preview_size (GTK_PREVIEW (ld->input_levels_da[0]),
  475.             DA_WIDTH, GRADIENT_HEIGHT);
  476.   gtk_widget_set_events (ld->input_levels_da[0], LEVELS_DA_MASK);
  477.   gtk_box_pack_start (GTK_BOX (vbox2), ld->input_levels_da[0], FALSE, TRUE, 0);
  478.  
  479.   gtk_signal_connect (GTK_OBJECT (ld->input_levels_da[0]), "event",
  480.               GTK_SIGNAL_FUNC (levels_input_da_events),
  481.               ld);
  482.  
  483.   ld->input_levels_da[1] = gtk_drawing_area_new ();
  484.   gtk_drawing_area_size (GTK_DRAWING_AREA (ld->input_levels_da[1]),
  485.              DA_WIDTH, CONTROL_HEIGHT);
  486.   gtk_widget_set_events (ld->input_levels_da[1], LEVELS_DA_MASK);
  487.   gtk_box_pack_start (GTK_BOX (vbox2), ld->input_levels_da[1], FALSE, TRUE, 0);
  488.  
  489.   gtk_signal_connect (GTK_OBJECT (ld->input_levels_da[1]), "event",
  490.               GTK_SIGNAL_FUNC (levels_input_da_events),
  491.               ld);
  492.  
  493.   gtk_widget_show (ld->input_levels_da[0]);
  494.   gtk_widget_show (ld->input_levels_da[1]);
  495.   gtk_widget_show (vbox2);
  496.   gtk_widget_show (frame);
  497.   gtk_widget_show (hbox);
  498.  
  499.   /*  Horizontal box for levels spin widgets  */
  500.   hbox = gtk_hbox_new (FALSE, 4);
  501.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  502.  
  503.   label = gtk_label_new (_("Output Levels:"));
  504.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  505.   gtk_widget_show (label);
  506.  
  507.   /*  low output spin  */
  508.   data = gtk_adjustment_new (0, 0, 255, 1, 10, 10);
  509.   ld->low_output_data = GTK_ADJUSTMENT (data);
  510.  
  511.   spinbutton = gtk_spin_button_new (ld->low_output_data, 0.5, 0);
  512.   gtk_widget_set_usize (spinbutton, 50, -1);
  513.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  514.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  515.  
  516.   gtk_signal_connect (GTK_OBJECT (ld->low_output_data), "value_changed",
  517.                       GTK_SIGNAL_FUNC (levels_low_output_adjustment_update),
  518.                       ld);
  519.  
  520.   gtk_widget_show (spinbutton);
  521.  
  522.   /*  high output spin  */
  523.   data = gtk_adjustment_new (255, 0, 255, 1, 10, 10);
  524.   ld->high_output_data = GTK_ADJUSTMENT (data);
  525.  
  526.   spinbutton = gtk_spin_button_new (ld->high_output_data, 0.5, 0);
  527.   gtk_widget_set_usize (spinbutton, 50, -1);
  528.   gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE);
  529.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  530.  
  531.   gtk_signal_connect (GTK_OBJECT (ld->high_output_data), "value_changed",
  532.                       GTK_SIGNAL_FUNC (levels_high_output_adjustment_update),
  533.                       ld);
  534.  
  535.   gtk_widget_show (spinbutton);
  536.   gtk_widget_show (hbox);
  537.  
  538.   /*  The output levels drawing area  */
  539.   hbox = gtk_hbox_new (TRUE, 2);
  540.   gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
  541.  
  542.   frame = gtk_frame_new (NULL);
  543.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  544.   gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
  545.  
  546.   vbox2 = gtk_vbox_new (FALSE, 2);
  547.   gtk_container_add (GTK_CONTAINER (frame), vbox2);
  548.  
  549.   ld->output_levels_da[0] = gtk_preview_new (GTK_PREVIEW_COLOR);
  550.   gtk_preview_size (GTK_PREVIEW (ld->output_levels_da[0]), DA_WIDTH, GRADIENT_HEIGHT);
  551.   gtk_widget_set_events (ld->output_levels_da[0], LEVELS_DA_MASK);
  552.   gtk_box_pack_start (GTK_BOX (vbox2), ld->output_levels_da[0], FALSE, TRUE, 0);
  553.  
  554.   gtk_signal_connect (GTK_OBJECT (ld->output_levels_da[0]), "event",
  555.               GTK_SIGNAL_FUNC (levels_output_da_events),
  556.               ld);
  557.  
  558.   ld->output_levels_da[1] = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
  559.   gtk_preview_size (GTK_PREVIEW (ld->output_levels_da[1]), DA_WIDTH, CONTROL_HEIGHT);
  560.   gtk_widget_set_events (ld->output_levels_da[1], LEVELS_DA_MASK);
  561.   gtk_box_pack_start (GTK_BOX (vbox2), ld->output_levels_da[1], FALSE, TRUE, 0);
  562.  
  563.   gtk_signal_connect (GTK_OBJECT (ld->output_levels_da[1]), "event",
  564.               GTK_SIGNAL_FUNC (levels_output_da_events),
  565.               ld);
  566.  
  567.   gtk_widget_show (ld->output_levels_da[0]);
  568.   gtk_widget_show (ld->output_levels_da[1]);
  569.   gtk_widget_show (vbox2);
  570.   gtk_widget_show (frame);
  571.   gtk_widget_show (hbox);
  572.  
  573.   gtk_widget_show (vbox);
  574.  
  575.   /*  The preview toggle  */
  576.   hbox = gtk_hbox_new (FALSE, 4);
  577.   gtk_box_pack_end (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  578.  
  579.   toggle = gtk_check_button_new_with_label (_("Preview"));
  580.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), ld->preview);
  581.   gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
  582.  
  583.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  584.               GTK_SIGNAL_FUNC (levels_preview_update),
  585.               ld);
  586.  
  587.   gtk_widget_show (toggle);
  588.  
  589.   gtk_widget_show (hbox);
  590.  
  591.   /*  Horizontal button box for auto / load / save  */
  592.   hbbox = gtk_hbutton_box_new ();
  593.   gtk_button_box_set_spacing (GTK_BUTTON_BOX (hbbox), 4);
  594.   gtk_button_box_set_layout (GTK_BUTTON_BOX (hbbox), GTK_BUTTONBOX_SPREAD);
  595.   gtk_box_pack_end (GTK_BOX (main_vbox), hbbox, FALSE, FALSE, 0);
  596.  
  597.   button = gtk_button_new_with_label (_("Auto"));
  598.   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  599.   gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  600.  
  601.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  602.               GTK_SIGNAL_FUNC (levels_auto_callback),
  603.               ld);
  604.  
  605.   gtk_widget_show (button);
  606.  
  607.   button = gtk_button_new_with_label (_("Load"));
  608.   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  609.   gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  610.  
  611.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  612.               GTK_SIGNAL_FUNC (levels_load_callback),
  613.               ld->shell);
  614.  
  615.   gtk_widget_show (button);
  616.  
  617.   button = gtk_button_new_with_label (_("Save"));
  618.   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
  619.   gtk_box_pack_start (GTK_BOX (hbbox), button, FALSE, FALSE, 0);
  620.  
  621.   gtk_signal_connect (GTK_OBJECT (button), "clicked",
  622.               GTK_SIGNAL_FUNC (levels_save_callback),
  623.               ld->shell);
  624.  
  625.   gtk_widget_show (button);
  626.  
  627.   gtk_widget_show (hbbox);
  628.  
  629.   gtk_widget_show (main_vbox);
  630.   gtk_widget_show (ld->shell);
  631.  
  632.   return ld;
  633. }
  634.  
  635. static void
  636. levels_draw_slider (GdkWindow *window,
  637.             GdkGC     *border_gc,
  638.             GdkGC     *fill_gc,
  639.             gint       xpos)
  640. {
  641.   int y;
  642.  
  643.   for (y = 0; y < CONTROL_HEIGHT; y++)
  644.     gdk_draw_line(window, fill_gc, xpos - y / 2, y,
  645.           xpos + y / 2, y);
  646.  
  647.   gdk_draw_line (window, border_gc, xpos, 0,
  648.          xpos - (CONTROL_HEIGHT - 1) / 2,  CONTROL_HEIGHT - 1);
  649.  
  650.   gdk_draw_line (window, border_gc, xpos, 0,
  651.          xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
  652.  
  653.   gdk_draw_line (window, border_gc, xpos - (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1,
  654.          xpos + (CONTROL_HEIGHT - 1) / 2, CONTROL_HEIGHT - 1);
  655. }
  656.  
  657. static void
  658. levels_erase_slider (GdkWindow *window,
  659.              gint       xpos)
  660. {
  661.   gdk_window_clear_area (window, xpos - (CONTROL_HEIGHT - 1) / 2, 0,
  662.              CONTROL_HEIGHT - 1, CONTROL_HEIGHT);
  663. }
  664.  
  665. static void
  666. levels_calculate_transfers (LevelsDialog *ld)
  667. {
  668.   gdouble inten;
  669.   gint i, j;
  670.  
  671.   /*  Recalculate the levels arrays  */
  672.   for (j = 0; j < 5; j++)
  673.     {
  674.       for (i = 0; i < 256; i++)
  675.     {
  676.       /*  determine input intensity  */
  677.       if (ld->high_input[j] != ld->low_input[j])
  678.         inten = (double) (i - ld->low_input[j]) /
  679.           (double) (ld->high_input[j] - ld->low_input[j]);
  680.       else
  681.         inten = (double) (i - ld->low_input[j]);
  682.  
  683.       inten = CLAMP (inten, 0.0, 1.0);
  684.       if (ld->gamma[j] != 0.0)
  685.         inten = pow (inten, (1.0 / ld->gamma[j]));
  686.       ld->input[j][i] = (unsigned char) (inten * 255.0 + 0.5);
  687.     }
  688.     }
  689. }
  690.  
  691. static void
  692. levels_update (LevelsDialog *ld,
  693.            gint          update)
  694. {
  695.   gint i;
  696.   gint   sel_channel;
  697.   
  698.   if(ld->color) {
  699.     sel_channel = ld->channel;
  700.   } else {
  701.     if(ld->channel == 2)
  702.       sel_channel = GIMP_HISTOGRAM_ALPHA;
  703.     else
  704.       sel_channel = GIMP_HISTOGRAM_VALUE;
  705.   }
  706.  
  707.   /*  Recalculate the transfer arrays  */
  708.   levels_calculate_transfers (ld);
  709.   /* set up the lut */
  710.   levels_lut_setup (ld->lut, ld->gamma, ld->low_input, ld->high_input,
  711.             ld->low_output, ld->high_output,
  712.             gimp_drawable_bytes(ld->drawable));
  713.  
  714.   if (update & LOW_INPUT)
  715.     {
  716.       gtk_adjustment_set_value (ld->low_input_data,
  717.                 ld->low_input[ld->channel]);
  718.     }
  719.   if (update & GAMMA)
  720.     {
  721.       gtk_adjustment_set_value (ld->gamma_data,
  722.                 ld->gamma[ld->channel]);
  723.     }
  724.   if (update & HIGH_INPUT)
  725.     {
  726.       gtk_adjustment_set_value (ld->high_input_data,
  727.                 ld->high_input[ld->channel]);
  728.     }
  729.   if (update & LOW_OUTPUT)
  730.     {
  731.       gtk_adjustment_set_value (ld->low_output_data,
  732.                 ld->low_output[ld->channel]);
  733.     }
  734.   if (update & HIGH_OUTPUT)
  735.     {
  736.       gtk_adjustment_set_value (ld->high_output_data,
  737.                 ld->high_output[ld->channel]);
  738.     }
  739.   if (update & INPUT_LEVELS)
  740.     {
  741.       guchar buf[DA_WIDTH*3];
  742.  
  743.       switch (sel_channel)
  744.     {
  745.     default:
  746.       g_warning ("unknown channel type, can't happen\n");
  747.       /* fall through */
  748.     case GIMP_HISTOGRAM_VALUE:
  749.     case GIMP_HISTOGRAM_ALPHA:
  750.       for (i = 0; i < DA_WIDTH; i++)
  751.         {
  752.           buf[3*i+0] = ld->input[sel_channel][i];
  753.           buf[3*i+1] = ld->input[sel_channel][i];
  754.           buf[3*i+2] = ld->input[sel_channel][i];
  755.         }
  756.       break;
  757.  
  758.     case GIMP_HISTOGRAM_RED:
  759.     case GIMP_HISTOGRAM_GREEN:
  760.     case GIMP_HISTOGRAM_BLUE:      
  761.       for (i = 0; i < DA_WIDTH; i++)
  762.         {
  763.           buf[3*i+0] = ld->input[GIMP_HISTOGRAM_RED][i];
  764.           buf[3*i+1] = ld->input[GIMP_HISTOGRAM_GREEN][i];
  765.           buf[3*i+2] = ld->input[GIMP_HISTOGRAM_BLUE][i];
  766.         }
  767.       break;
  768.     }
  769.  
  770.       for (i = 0; i < GRADIENT_HEIGHT/2; i++)
  771.     gtk_preview_draw_row (GTK_PREVIEW (ld->input_levels_da[0]),
  772.                   buf, 0, i, DA_WIDTH);
  773.  
  774.  
  775.       for (i = 0; i < DA_WIDTH; i++)
  776.     {
  777.       buf[3*i+0] = i;
  778.       buf[3*i+1] = i;
  779.       buf[3*i+2] = i;
  780.     }
  781.  
  782.       for (i = GRADIENT_HEIGHT/2; i < GRADIENT_HEIGHT; i++)
  783.     gtk_preview_draw_row (GTK_PREVIEW (ld->input_levels_da[0]),
  784.                   buf, 0, i, DA_WIDTH);
  785.  
  786.       if (update & DRAW)
  787.     gtk_widget_draw (ld->input_levels_da[0], NULL);
  788.     }
  789.   if (update & OUTPUT_LEVELS)
  790.     {
  791.       guchar buf[DA_WIDTH*3];
  792.       guchar r, g, b;
  793.  
  794.       r = g = b = 0;
  795.       switch (sel_channel)
  796.     {
  797.     default:
  798.       g_warning ("unknown channel type, can't happen\n");
  799.       /* fall through */
  800.     case GIMP_HISTOGRAM_VALUE:
  801.     case GIMP_HISTOGRAM_ALPHA:  r = g = b = 1; break;
  802.     case GIMP_HISTOGRAM_RED:    r = 1;         break;
  803.     case GIMP_HISTOGRAM_GREEN:  g = 1;         break;
  804.     case GIMP_HISTOGRAM_BLUE:   b = 1;         break;
  805.     }
  806.  
  807.       for (i = 0; i < DA_WIDTH; i++)
  808.     {
  809.       buf[3*i+0] = i*r;
  810.       buf[3*i+1] = i*g;
  811.       buf[3*i+2] = i*b;
  812.     }
  813.  
  814.       for (i = 0; i < GRADIENT_HEIGHT; i++)
  815.     gtk_preview_draw_row (GTK_PREVIEW (ld->output_levels_da[0]),
  816.                   buf, 0, i, DA_WIDTH);
  817.  
  818.       if (update & DRAW)
  819.     gtk_widget_draw (ld->output_levels_da[0], NULL);
  820.     }
  821.   if (update & INPUT_SLIDERS)
  822.     {
  823.       double width, mid, tmp;
  824.  
  825.       levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[0]);
  826.       levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[1]);
  827.       levels_erase_slider (ld->input_levels_da[1]->window, ld->slider_pos[2]);
  828.  
  829.       ld->slider_pos[0] = DA_WIDTH * ((double) ld->low_input[ld->channel] / 255.0);
  830.       ld->slider_pos[2] = DA_WIDTH * ((double) ld->high_input[ld->channel] / 255.0);
  831.  
  832.       width = (double) (ld->slider_pos[2] - ld->slider_pos[0]) / 2.0;
  833.       mid = ld->slider_pos[0] + width;
  834.       tmp = log10 (1.0 / ld->gamma[ld->channel]);
  835.       ld->slider_pos[1] = (int) (mid + width * tmp + 0.5);
  836.  
  837.       levels_draw_slider (ld->input_levels_da[1]->window,
  838.               ld->input_levels_da[1]->style->black_gc,
  839.               ld->input_levels_da[1]->style->dark_gc[GTK_STATE_NORMAL],
  840.               ld->slider_pos[1]);
  841.       levels_draw_slider (ld->input_levels_da[1]->window,
  842.               ld->input_levels_da[1]->style->black_gc,
  843.               ld->input_levels_da[1]->style->black_gc,
  844.               ld->slider_pos[0]);
  845.       levels_draw_slider (ld->input_levels_da[1]->window,
  846.               ld->input_levels_da[1]->style->black_gc,
  847.               ld->input_levels_da[1]->style->white_gc,
  848.               ld->slider_pos[2]);
  849.     }
  850.   if (update & OUTPUT_SLIDERS)
  851.     {
  852.       levels_erase_slider (ld->output_levels_da[1]->window, ld->slider_pos[3]);
  853.       levels_erase_slider (ld->output_levels_da[1]->window, ld->slider_pos[4]);
  854.  
  855.       ld->slider_pos[3] = DA_WIDTH * ((double) ld->low_output[ld->channel] / 255.0);
  856.       ld->slider_pos[4] = DA_WIDTH * ((double) ld->high_output[ld->channel] / 255.0);
  857.  
  858.       levels_draw_slider (ld->output_levels_da[1]->window,
  859.               ld->output_levels_da[1]->style->black_gc,
  860.               ld->output_levels_da[1]->style->black_gc,
  861.               ld->slider_pos[3]);
  862.       levels_draw_slider (ld->output_levels_da[1]->window,
  863.               ld->output_levels_da[1]->style->black_gc,
  864.               ld->output_levels_da[1]->style->white_gc,
  865.               ld->slider_pos[4]);
  866.     }
  867. }
  868.  
  869. static void
  870. levels_preview (LevelsDialog *ld)
  871. {
  872.   if (!ld->image_map)
  873.     {
  874.       g_warning ("levels_preview: No Image Map");
  875.       return;
  876.     }
  877.   if (!ld->preview)
  878.     return;
  879.   active_tool->preserve = TRUE;
  880.   image_map_apply (ld->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  881.            (void *) ld->lut);
  882.   active_tool->preserve = FALSE;
  883. }
  884.  
  885. static void
  886. levels_channel_callback (GtkWidget *widget,
  887.              gpointer   data)
  888. {
  889.   LevelsDialog *ld;
  890.  
  891.   ld = (LevelsDialog *) data;
  892.  
  893.   gimp_menu_item_update (widget, &ld->channel);
  894.  
  895.   if(ld->color)
  896.     histogram_widget_channel (ld->histogram, ld->channel);
  897.   else
  898.     {
  899.       if(ld->channel > 1) 
  900.     {
  901.       histogram_widget_channel (ld->histogram, 1);
  902.       ld->channel = 2;
  903.     }
  904.       else
  905.     {
  906.       histogram_widget_channel (ld->histogram, 0);
  907.       ld->channel = 1;
  908.     } 
  909.     }
  910.   levels_update (ld, ALL);
  911. }
  912.  
  913. static void
  914. levels_adjust_channel (LevelsDialog    *ld,
  915.                GimpHistogram   *hist,
  916.                gint             channel)
  917. {
  918.   gint i;
  919.   gdouble count, new_count, percentage, next_percentage;
  920.  
  921.   ld->gamma[channel]       = 1.0;
  922.   ld->low_output[channel]  = 0;
  923.   ld->high_output[channel] = 255;
  924.  
  925.   count = gimp_histogram_get_count (hist, 0, 255);
  926.  
  927.   if (count == 0.0)
  928.     {
  929.       ld->low_input[channel] = 0;
  930.       ld->high_input[channel] = 0;
  931.     }
  932.   else
  933.     {
  934.       /*  Set the low input  */
  935.       new_count = 0.0;
  936.       for (i = 0; i < 255; i++)
  937.     {
  938.       new_count += gimp_histogram_get_value(hist, channel, i);
  939.       percentage = new_count / count;
  940.       next_percentage =
  941.         (new_count + gimp_histogram_get_value (hist,
  942.                            channel,
  943.                            i + 1)) / count;
  944.       if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
  945.         {
  946.           ld->low_input[channel] = i + 1;
  947.           break;
  948.         }
  949.     }
  950.       /*  Set the high input  */
  951.       new_count = 0.0;
  952.       for (i = 255; i > 0; i--)
  953.     {
  954.       new_count += gimp_histogram_get_value(hist, channel, i);
  955.       percentage = new_count / count;
  956.       next_percentage =
  957.         (new_count + gimp_histogram_get_value (hist,
  958.                            channel,
  959.                            i - 1)) / count;
  960.       if (fabs (percentage - 0.006) < fabs (next_percentage - 0.006))
  961.         {
  962.           ld->high_input[channel] = i - 1;
  963.           break;
  964.         }
  965.     }
  966.     }
  967. }
  968.  
  969. static void
  970. levels_reset_callback (GtkWidget *widget,
  971.                gpointer   data)
  972. {
  973.   LevelsDialog *ld;
  974.   int channel;
  975.   int maxChannels;
  976.  
  977.   ld = (LevelsDialog *) data;
  978.  
  979.   if (ld->color)
  980.     maxChannels = 4;
  981.   else
  982.     maxChannels = 1;
  983.   
  984.   for (channel = 0; channel < maxChannels; channel++)
  985.     {
  986.       ld->low_input[channel]   = 0;
  987.       ld->gamma[channel]       = 1.0;
  988.       ld->high_input[channel]  = 255;
  989.       ld->low_output[channel]  = 0;
  990.       ld->high_output[channel] = 255;
  991.       
  992.       levels_adjust_channel (ld, ld->hist, channel + 1);
  993.     }
  994.   levels_update (ld, ALL);
  995.   
  996.   if (ld->preview)
  997.     levels_preview (ld);
  998. }
  999.  
  1000. static void
  1001. levels_ok_callback (GtkWidget *widget,
  1002.             gpointer   data)
  1003. {
  1004.   LevelsDialog *ld;
  1005.  
  1006.   ld = (LevelsDialog *) data;
  1007.  
  1008.   gimp_dialog_hide (ld->shell);
  1009.  
  1010.   active_tool->preserve = TRUE;
  1011.  
  1012.   if (!ld->preview)
  1013.     {
  1014.       levels_lut_setup (ld->lut, ld->gamma, ld->low_input, ld->high_input,
  1015.             ld->low_output, ld->high_output,
  1016.             gimp_drawable_bytes (ld->drawable));
  1017.       image_map_apply (ld->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  1018.                (void *) ld->lut);
  1019.     }
  1020.  
  1021.   if (ld->image_map)
  1022.     image_map_commit (ld->image_map);
  1023.  
  1024.   active_tool->preserve = FALSE;
  1025.  
  1026.   ld->image_map = NULL;
  1027.  
  1028.   active_tool->gdisp_ptr = NULL;
  1029.   active_tool->drawable = NULL;
  1030. }
  1031.  
  1032. static void
  1033. levels_cancel_callback (GtkWidget *widget,
  1034.             gpointer   data)
  1035. {
  1036.   LevelsDialog *ld;
  1037.  
  1038.   ld = (LevelsDialog *) data;
  1039.  
  1040.   gimp_dialog_hide (ld->shell);
  1041.  
  1042.   if (ld->image_map)
  1043.     {
  1044.       active_tool->preserve = TRUE;
  1045.       image_map_abort (ld->image_map);
  1046.       active_tool->preserve = FALSE;
  1047.  
  1048.       gdisplays_flush ();
  1049.       ld->image_map = NULL;
  1050.     }
  1051.  
  1052.   active_tool->gdisp_ptr = NULL;
  1053.   active_tool->drawable = NULL;
  1054. }
  1055.  
  1056. static void
  1057. levels_auto_callback (GtkWidget *widget,
  1058.               gpointer   data)
  1059. {
  1060.   LevelsDialog *ld;
  1061.   int channel;
  1062.  
  1063.   ld = (LevelsDialog *) data;
  1064.  
  1065.   if (ld->color)
  1066.     {
  1067.       /*  Set the overall value to defaults  */
  1068.       ld->low_input[GIMP_HISTOGRAM_VALUE]   = 0;
  1069.       ld->gamma[GIMP_HISTOGRAM_VALUE]       = 1.0;
  1070.       ld->high_input[GIMP_HISTOGRAM_VALUE]  = 255;
  1071.       ld->low_output[GIMP_HISTOGRAM_VALUE]  = 0;
  1072.       ld->high_output[GIMP_HISTOGRAM_VALUE] = 255;
  1073.  
  1074.       for (channel = 0; channel < 3; channel ++)
  1075.     levels_adjust_channel (ld, ld->hist, channel + 1);
  1076.     }
  1077.   else
  1078.     levels_adjust_channel (ld, ld->hist, GIMP_HISTOGRAM_VALUE);
  1079.  
  1080.   levels_update (ld, ALL);
  1081.   if (ld->preview)
  1082.     levels_preview (ld);
  1083. }
  1084.  
  1085. static void
  1086. levels_load_callback (GtkWidget *widget,
  1087.               gpointer   data)
  1088. {
  1089.   if (!file_dlg)
  1090.     file_dialog_create (GTK_WIDGET (data));
  1091.   else if (GTK_WIDGET_VISIBLE (file_dlg)) 
  1092.     return;
  1093.  
  1094.   load_save = TRUE;
  1095.  
  1096.   gtk_window_set_title (GTK_WINDOW (file_dlg), _("Load Levels"));
  1097.   gtk_widget_show (file_dlg);
  1098. }
  1099.  
  1100. static void
  1101. levels_save_callback (GtkWidget *widget,
  1102.               gpointer   data)
  1103. {
  1104.   if (!file_dlg)
  1105.     file_dialog_create (GTK_WIDGET (data));
  1106.   else if (GTK_WIDGET_VISIBLE (file_dlg)) 
  1107.     return;
  1108.  
  1109.   load_save = FALSE;
  1110.  
  1111.   gtk_window_set_title (GTK_WINDOW (file_dlg), _("Save Levels"));
  1112.   gtk_widget_show (file_dlg);
  1113. }
  1114.  
  1115. static void
  1116. levels_preview_update (GtkWidget *widget,
  1117.                gpointer   data)
  1118. {
  1119.   LevelsDialog *ld;
  1120.  
  1121.   ld = (LevelsDialog *) data;
  1122.  
  1123.   if (GTK_TOGGLE_BUTTON (widget)->active)
  1124.     {
  1125.       ld->preview = TRUE;
  1126.       levels_preview (ld);
  1127.     }
  1128.   else
  1129.     {
  1130.       ld->preview = FALSE;
  1131.       if (ld->image_map)
  1132.     {
  1133.       active_tool->preserve = TRUE;
  1134.       image_map_clear (ld->image_map);
  1135.       active_tool->preserve = FALSE;
  1136.       gdisplays_flush ();
  1137.     }
  1138.     }
  1139.  
  1140. }
  1141.  
  1142. static void
  1143. levels_low_input_adjustment_update (GtkAdjustment *adjustment,
  1144.                     gpointer       data)
  1145. {
  1146.   LevelsDialog *ld;
  1147.   gint value;
  1148.  
  1149.   ld = (LevelsDialog *) data;
  1150.  
  1151.   value = (gint) (adjustment->value + 0.5);
  1152.   value = CLAMP (value, 0, ld->high_input[ld->channel]);
  1153.  
  1154.   /*  enforce a consistent displayed value (low_input <= high_input)  */
  1155.   gtk_adjustment_set_value (adjustment, value);
  1156.  
  1157.   if (ld->low_input[ld->channel] != value)
  1158.     {
  1159.       ld->low_input[ld->channel] = value;
  1160.       levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW);
  1161.  
  1162.       if (ld->preview)
  1163.     levels_preview (ld);
  1164.     }
  1165. }
  1166.  
  1167. static void
  1168. levels_gamma_adjustment_update (GtkAdjustment *adjustment,
  1169.                 gpointer       data)
  1170. {
  1171.   LevelsDialog *ld;
  1172.  
  1173.   ld = (LevelsDialog *) data;
  1174.  
  1175.   if (ld->gamma[ld->channel] != adjustment->value)
  1176.     {
  1177.       ld->gamma[ld->channel] = adjustment->value;
  1178.       levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW);
  1179.  
  1180.       if (ld->preview)
  1181.     levels_preview (ld);
  1182.     }
  1183. }
  1184.  
  1185. static void
  1186. levels_high_input_adjustment_update (GtkAdjustment *adjustment,
  1187.                      gpointer       data)
  1188. {
  1189.   LevelsDialog *ld;
  1190.   gint value;
  1191.  
  1192.   ld = (LevelsDialog *) data;
  1193.  
  1194.   value = (gint) (adjustment->value + 0.5);
  1195.   value = CLAMP (value, ld->low_input[ld->channel], 255);
  1196.  
  1197.   /*  enforce a consistent displayed value (high_input >= low_input)  */
  1198.   gtk_adjustment_set_value (adjustment, value);
  1199.  
  1200.   if (ld->high_input[ld->channel] != value)
  1201.     {
  1202.       ld->high_input[ld->channel] = value;
  1203.       levels_update (ld, INPUT_LEVELS | INPUT_SLIDERS | DRAW);
  1204.  
  1205.       if (ld->preview)
  1206.     levels_preview (ld);
  1207.     }
  1208. }
  1209.  
  1210. static void
  1211. levels_low_output_adjustment_update (GtkAdjustment *adjustment,
  1212.                      gpointer       data)
  1213. {
  1214.   LevelsDialog *ld;
  1215.   gint value;
  1216.  
  1217.   ld = (LevelsDialog *) data;
  1218.  
  1219.   value = (gint) (adjustment->value + 0.5);
  1220.  
  1221.   if (ld->low_output[ld->channel] != value)
  1222.     {
  1223.       ld->low_output[ld->channel] = value;
  1224.       levels_update (ld, OUTPUT_LEVELS | OUTPUT_SLIDERS | DRAW);
  1225.  
  1226.       if (ld->preview)
  1227.     levels_preview (ld);
  1228.     }
  1229. }
  1230.  
  1231. static void
  1232. levels_high_output_adjustment_update (GtkAdjustment *adjustment,
  1233.                       gpointer       data)
  1234. {
  1235.   LevelsDialog *ld;
  1236.   gint value;
  1237.  
  1238.   ld = (LevelsDialog *) data;
  1239.  
  1240.   value = (gint) (adjustment->value + 0.5);
  1241.  
  1242.   if (ld->high_output[ld->channel] != value)
  1243.     {
  1244.       ld->high_output[ld->channel] = value;
  1245.       levels_update (ld, OUTPUT_LEVELS | OUTPUT_SLIDERS | DRAW);
  1246.  
  1247.       if (ld->preview)
  1248.     levels_preview (ld);
  1249.     }
  1250. }
  1251.  
  1252. static gint
  1253. levels_input_da_events (GtkWidget    *widget,
  1254.             GdkEvent     *event,
  1255.             LevelsDialog *ld)
  1256. {
  1257.   GdkEventButton *bevent;
  1258.   GdkEventMotion *mevent;
  1259.   gchar text[12];
  1260.   gdouble width, mid, tmp;
  1261.   gint x, distance;
  1262.   gint i;
  1263.   gint update = FALSE;
  1264.  
  1265.   switch (event->type)
  1266.     {
  1267.     case GDK_EXPOSE:
  1268.       if (widget == ld->input_levels_da[1])
  1269.     levels_update (ld, INPUT_SLIDERS);
  1270.       break;
  1271.  
  1272.     case GDK_BUTTON_PRESS:
  1273.       gtk_grab_add (widget);
  1274.       bevent = (GdkEventButton *) event;
  1275.  
  1276.       distance = G_MAXINT;
  1277.       for (i = 0; i < 3; i++)
  1278.     if (fabs (bevent->x - ld->slider_pos[i]) < distance)
  1279.       {
  1280.         ld->active_slider = i;
  1281.         distance = fabs (bevent->x - ld->slider_pos[i]);
  1282.       }
  1283.  
  1284.       x = bevent->x;
  1285.       update = TRUE;
  1286.       break;
  1287.  
  1288.     case GDK_BUTTON_RELEASE:
  1289.       gtk_grab_remove (widget);
  1290.       switch (ld->active_slider)
  1291.     {
  1292.     case 0:  /*  low input  */
  1293.       levels_update (ld, LOW_INPUT | GAMMA | DRAW);
  1294.       break;
  1295.     case 1:  /*  gamma  */
  1296.       levels_update (ld, GAMMA);
  1297.       break;
  1298.     case 2:  /*  high input  */
  1299.       levels_update (ld, HIGH_INPUT | GAMMA | DRAW);
  1300.       break;
  1301.     }
  1302.  
  1303.       if (ld->preview)
  1304.     levels_preview (ld);
  1305.       break;
  1306.  
  1307.     case GDK_MOTION_NOTIFY:
  1308.       mevent = (GdkEventMotion *) event;
  1309.       gdk_window_get_pointer (widget->window, &x, NULL, NULL);
  1310.       update = TRUE;
  1311.       break;
  1312.  
  1313.     default:
  1314.       break;
  1315.     }
  1316.  
  1317.   if (update)
  1318.     {
  1319.       switch (ld->active_slider)
  1320.     {
  1321.     case 0:  /*  low input  */
  1322.       ld->low_input[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1323.       ld->low_input[ld->channel] = CLAMP (ld->low_input[ld->channel], 0,
  1324.                           ld->high_input[ld->channel]);
  1325.       break;
  1326.  
  1327.     case 1:  /*  gamma  */
  1328.       width = (double) (ld->slider_pos[2] - ld->slider_pos[0]) / 2.0;
  1329.       mid = ld->slider_pos[0] + width;
  1330.  
  1331.       x = CLAMP (x, ld->slider_pos[0], ld->slider_pos[2]);
  1332.       tmp = (double) (x - mid) / width;
  1333.       ld->gamma[ld->channel] = 1.0 / pow (10, tmp);
  1334.  
  1335.       /*  round the gamma value to the nearest 1/100th  */
  1336.       sprintf (text, "%2.2f", ld->gamma[ld->channel]);
  1337.       ld->gamma[ld->channel] = atof (text);
  1338.       break;
  1339.  
  1340.     case 2:  /*  high input  */
  1341.       ld->high_input[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1342.       ld->high_input[ld->channel] = CLAMP (ld->high_input[ld->channel],
  1343.                            ld->low_input[ld->channel], 255);
  1344.       break;
  1345.     }
  1346.  
  1347.       levels_update (ld, INPUT_SLIDERS | INPUT_LEVELS | DRAW);
  1348.     }
  1349.  
  1350.   return FALSE;
  1351. }
  1352.  
  1353. static gint
  1354. levels_output_da_events (GtkWidget    *widget,
  1355.              GdkEvent     *event,
  1356.              LevelsDialog *ld)
  1357. {
  1358.   GdkEventButton *bevent;
  1359.   GdkEventMotion *mevent;
  1360.   int x, distance;
  1361.   int i;
  1362.   int update = FALSE;
  1363.  
  1364.   switch (event->type)
  1365.     {
  1366.     case GDK_EXPOSE:
  1367.       if (widget == ld->output_levels_da[1])
  1368.     levels_update (ld, OUTPUT_SLIDERS);
  1369.       break;
  1370.  
  1371.  
  1372.     case GDK_BUTTON_PRESS:
  1373.       bevent = (GdkEventButton *) event;
  1374.  
  1375.       distance = G_MAXINT;
  1376.       for (i = 3; i < 5; i++)
  1377.     if (fabs (bevent->x - ld->slider_pos[i]) < distance)
  1378.       {
  1379.         ld->active_slider = i;
  1380.         distance = fabs (bevent->x - ld->slider_pos[i]);
  1381.       }
  1382.  
  1383.       x = bevent->x;
  1384.       update = TRUE;
  1385.       break;
  1386.  
  1387.     case GDK_BUTTON_RELEASE:
  1388.       switch (ld->active_slider)
  1389.     {
  1390.     case 3:  /*  low output  */
  1391.       levels_update (ld, LOW_OUTPUT | DRAW);
  1392.       break;
  1393.     case 4:  /*  high output  */
  1394.       levels_update (ld, HIGH_OUTPUT | DRAW);
  1395.       break;
  1396.     }
  1397.  
  1398.       if (ld->preview)
  1399.     levels_preview (ld);
  1400.       break;
  1401.  
  1402.     case GDK_MOTION_NOTIFY:
  1403.       mevent = (GdkEventMotion *) event;
  1404.       gdk_window_get_pointer (widget->window, &x, NULL, NULL);
  1405.       update = TRUE;
  1406.       break;
  1407.  
  1408.     default:
  1409.       break;
  1410.     }
  1411.  
  1412.   if (update)
  1413.     {
  1414.       switch (ld->active_slider)
  1415.     {
  1416.     case 3:  /*  low output  */
  1417.       ld->low_output[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1418.       ld->low_output[ld->channel] = CLAMP (ld->low_output[ld->channel],
  1419.                            0, 255);
  1420.       break;
  1421.  
  1422.     case 4:  /*  high output  */
  1423.       ld->high_output[ld->channel] = ((double) x / (double) DA_WIDTH) * 255.0;
  1424.       ld->high_output[ld->channel] = CLAMP (ld->high_output[ld->channel],
  1425.                         0, 255);
  1426.       break;
  1427.     }
  1428.  
  1429.       levels_update (ld, OUTPUT_SLIDERS | DRAW);
  1430.     }
  1431.  
  1432.   return FALSE;
  1433. }
  1434.  
  1435. static void
  1436. file_dialog_create (GtkWidget *parent)
  1437. {
  1438.   gchar *temp;
  1439.  
  1440.   file_dlg = gtk_file_selection_new (_("Load/Save Levels"));
  1441.   gtk_window_set_wmclass (GTK_WINDOW (file_dlg), "load_save_levels", "Gimp");
  1442.   gtk_window_set_position (GTK_WINDOW (file_dlg), GTK_WIN_POS_MOUSE);
  1443.  
  1444.   gtk_container_set_border_width (GTK_CONTAINER (file_dlg), 2);
  1445.   gtk_container_set_border_width (GTK_CONTAINER (GTK_FILE_SELECTION (file_dlg)->button_area), 2);
  1446.  
  1447.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->cancel_button),
  1448.               "clicked", GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
  1449.               NULL);
  1450.   gtk_signal_connect (GTK_OBJECT (file_dlg), "delete_event",
  1451.               GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
  1452.               NULL);
  1453.   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (file_dlg)->ok_button),
  1454.               "clicked", GTK_SIGNAL_FUNC (file_dialog_ok_callback),
  1455.               NULL);
  1456.  
  1457.   gtk_signal_connect (GTK_OBJECT (parent), "unmap",
  1458.               GTK_SIGNAL_FUNC (file_dialog_cancel_callback),
  1459.               NULL);
  1460.  
  1461.   temp = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "levels" G_DIR_SEPARATOR_S,
  1462.                     gimp_directory ());
  1463.   gtk_file_selection_set_filename (GTK_FILE_SELECTION (file_dlg), temp);
  1464.   g_free (temp);
  1465.  
  1466.   gimp_help_connect_help_accel (file_dlg, tools_help_func,
  1467.                 tool_info[LEVELS].private_tip);
  1468. }
  1469.  
  1470. static void
  1471. file_dialog_ok_callback (GtkWidget *widget,
  1472.              gpointer   data)
  1473. {
  1474.   FILE  *f;
  1475.   gchar *filename;
  1476.  
  1477.   filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_dlg));
  1478.  
  1479.   if (load_save)
  1480.     {
  1481.       f = fopen (filename, "rt");
  1482.  
  1483.       if (!f)
  1484.     {
  1485.       g_message (_("Unable to open file %s"), filename);
  1486.       return;
  1487.     }
  1488.  
  1489.       if (!levels_read_from_file (f))
  1490.     {
  1491.       g_message (("Error in reading file %s"), filename);
  1492.       return;
  1493.     }
  1494.  
  1495.       fclose (f);
  1496.     }
  1497.   else
  1498.     {
  1499.       f = fopen(filename, "wt");
  1500.  
  1501.       if (!f)
  1502.     {
  1503.       g_message (_("Unable to open file %s"), filename);
  1504.       return;
  1505.     }
  1506.  
  1507.       levels_write_to_file (f);
  1508.  
  1509.       fclose (f);
  1510.     }
  1511.   file_dialog_cancel_callback (file_dlg, NULL);
  1512. }
  1513.  
  1514. static void
  1515. file_dialog_cancel_callback (GtkWidget *widget,
  1516.                  gpointer   data)
  1517. {
  1518.   gimp_dialog_hide (file_dlg);
  1519. }
  1520.  
  1521. static gboolean
  1522. levels_read_from_file (FILE *f)
  1523. {
  1524.   int low_input[5];
  1525.   int high_input[5];
  1526.   int low_output[5];
  1527.   int high_output[5];
  1528.   double gamma[5];
  1529.   int i, fields;
  1530.   char buf[50], *nptr;
  1531.   
  1532.   if (!fgets (buf, 50, f))
  1533.     return FALSE;
  1534.  
  1535.   if (strcmp (buf, "# GIMP Levels File\n") != 0)
  1536.     return FALSE;
  1537.  
  1538.   for (i = 0; i < 5; i++)
  1539.     {
  1540.       fields = fscanf (f, "%d %d %d %d ",
  1541.                &low_input[i],
  1542.                &high_input[i],
  1543.                &low_output[i],
  1544.                &high_output[i]);
  1545.  
  1546.       if (fields != 4)
  1547.     return FALSE;
  1548.  
  1549.       if (!fgets (buf, 50, f))
  1550.     return FALSE;
  1551.  
  1552.       gamma[i] = strtod(buf, &nptr);
  1553.  
  1554.       if (buf == nptr || errno == ERANGE)
  1555.     return FALSE;
  1556.     }
  1557.  
  1558.   for (i = 0; i < 5; i++)
  1559.     {
  1560.       levels_dialog->low_input[i] = low_input[i];
  1561.       levels_dialog->high_input[i] = high_input[i];
  1562.       levels_dialog->low_output[i] = low_output[i];
  1563.       levels_dialog->high_output[i] = high_output[i];
  1564.       levels_dialog->gamma[i] = gamma[i];
  1565.     }
  1566.  
  1567.   levels_update (levels_dialog, ALL);
  1568.  
  1569.   if (levels_dialog->preview)
  1570.     levels_preview (levels_dialog);
  1571.  
  1572.   return TRUE;
  1573. }
  1574.  
  1575. static void
  1576. levels_write_to_file (FILE *f)
  1577. {
  1578.   int i;
  1579.  
  1580.   fprintf (f, "# GIMP Levels File\n");
  1581.  
  1582.   for (i = 0; i < 5; i++)
  1583.     {
  1584.       fprintf (f, "%d %d %d %d %f\n",
  1585.            levels_dialog->low_input[i],
  1586.            levels_dialog->high_input[i],
  1587.            levels_dialog->low_output[i],
  1588.            levels_dialog->high_output[i],
  1589.            levels_dialog->gamma[i]);
  1590.     }
  1591. }
  1592.