home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / histogram_tool.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-20  |  12.8 KB  |  454 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. #include "config.h"
  19.  
  20. #include <glib.h>
  21.  
  22. #include "apptypes.h"
  23.  
  24. #include "appenv.h"
  25. #include "drawable.h"
  26. #include "gdisplay.h"
  27. #include "gimpui.h"
  28. #include "histogram_tool.h"
  29.  
  30. #include "libgimp/gimpintl.h"
  31. #include "libgimp/gimpmath.h"
  32.  
  33. #define TEXT_WIDTH       45
  34. #define GRADIENT_HEIGHT  15
  35.  
  36. /*  the histogram structures  */
  37.  
  38. typedef struct _HistogramTool HistogramTool;
  39.  
  40. struct _HistogramTool
  41. {
  42.   gint x, y;   /*  coords for last mouse click  */
  43. };
  44.  
  45. /*  the histogram tool options  */
  46. static ToolOptions * histogram_tool_options = NULL;
  47.  
  48. /*  the histogram tool dialog  */
  49. static HistogramToolDialog * histogram_tool_dialog = NULL;
  50.  
  51. /*  histogram_tool action functions  */
  52. static void   histogram_tool_control (Tool *, ToolAction, gpointer);
  53.  
  54. static HistogramToolDialog *  histogram_tool_dialog_new (void);
  55.  
  56. static void   histogram_tool_close_callback   (GtkWidget *, gpointer);
  57. static void   histogram_tool_channel_callback (GtkWidget *, gpointer);
  58. static void   histogram_tool_gradient_draw    (GtkWidget *, gint);
  59.  
  60. static void   histogram_tool_dialog_update    (HistogramToolDialog *,
  61.                            gint, gint);
  62.  
  63. /*  histogram_tool machinery  */
  64.  
  65. void
  66. histogram_tool_histogram_range (HistogramWidget *widget,
  67.                 gint             start,
  68.                 gint             end,
  69.                 gpointer         data)
  70. {
  71.   HistogramToolDialog *htd;
  72.   gdouble pixels;
  73.   gdouble count;
  74.  
  75.   htd = (HistogramToolDialog *) data;
  76.  
  77.   if (htd == NULL || htd->hist == NULL ||
  78.       gimp_histogram_nchannels(htd->hist) <= 0)
  79.     return;
  80.  
  81.   pixels = gimp_histogram_get_count (htd->hist, 0, 255);
  82.   count  = gimp_histogram_get_count (htd->hist, start, end);
  83.  
  84.   htd->mean       = gimp_histogram_get_mean (htd->hist, htd->channel,
  85.                          start, end);
  86.   htd->std_dev    = gimp_histogram_get_std_dev (htd->hist, htd->channel,
  87.                         start, end);
  88.   htd->median     = gimp_histogram_get_median (htd->hist, htd->channel,
  89.                            start, end);
  90.   htd->pixels     = pixels;
  91.   htd->count      = count;
  92.   htd->percentile = count / pixels;
  93.  
  94.   if (htd->shell)
  95.     histogram_tool_dialog_update (htd, start, end);
  96. }
  97.  
  98. static void
  99. histogram_tool_dialog_update (HistogramToolDialog *htd,
  100.                   gint                 start,
  101.                   gint                 end)
  102. {
  103.   gchar text[12];
  104.  
  105.   /*  mean  */
  106.   g_snprintf (text, sizeof (text), "%3.1f", htd->mean);
  107.   gtk_label_set_text (GTK_LABEL (htd->info_labels[0]), text);
  108.  
  109.   /*  std dev  */
  110.   g_snprintf (text, sizeof (text), "%3.1f", htd->std_dev);
  111.   gtk_label_set_text (GTK_LABEL (htd->info_labels[1]), text);
  112.  
  113.   /*  median  */
  114.   g_snprintf (text, sizeof (text), "%3.1f", htd->median);
  115.   gtk_label_set_text (GTK_LABEL (htd->info_labels[2]), text);
  116.  
  117.   /*  pixels  */
  118.   g_snprintf (text, sizeof (text), "%8.1f", htd->pixels);
  119.   gtk_label_set_text (GTK_LABEL (htd->info_labels[3]), text);
  120.  
  121.   /*  intensity  */
  122.   if (start == end)
  123.     g_snprintf (text, sizeof (text), "%d", start);
  124.   else
  125.     g_snprintf (text, sizeof (text), "%d..%d", start, end);
  126.   gtk_label_set_text (GTK_LABEL (htd->info_labels[4]), text);
  127.  
  128.   /*  count  */
  129.   g_snprintf (text, sizeof (text), "%8.1f", htd->count);
  130.   gtk_label_set_text (GTK_LABEL (htd->info_labels[5]), text);
  131.  
  132.   /*  percentile  */
  133.   g_snprintf (text, sizeof (text), "%2.2f", htd->percentile * 100);
  134.   gtk_label_set_text (GTK_LABEL (htd->info_labels[6]), text);
  135. }
  136.  
  137. /*  histogram_tool action functions  */
  138.  
  139. static void
  140. histogram_tool_control (Tool       *tool,
  141.             ToolAction  action,
  142.             gpointer    gdisp_ptr)
  143. {
  144.   switch (action)
  145.     {
  146.     case PAUSE:
  147.       break;
  148.  
  149.     case RESUME:
  150.       break;
  151.  
  152.     case HALT:
  153.       if (histogram_tool_dialog)
  154.     histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog);
  155.       break;
  156.  
  157.     default:
  158.       break;
  159.     }
  160. }
  161.  
  162. Tool *
  163. tools_new_histogram_tool (void)
  164. {
  165.   Tool * tool;
  166.   HistogramTool * private;
  167.  
  168.   /*  The tool options  */
  169.   if (! histogram_tool_options)
  170.     {
  171.       histogram_tool_options = tool_options_new (_("Histogram"));
  172.       tools_register (HISTOGRAM, histogram_tool_options);
  173.     }
  174.  
  175.   tool = tools_new_tool (HISTOGRAM);
  176.   private = g_new0 (HistogramTool, 1);
  177.  
  178.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  179.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  180.  
  181.   tool->private = (void *) private;
  182.  
  183.   tool->control_func = histogram_tool_control;
  184.  
  185.   return tool;
  186. }
  187.  
  188. void
  189. tools_free_histogram_tool (Tool *tool)
  190. {
  191.   HistogramTool * hist;
  192.  
  193.   hist = (HistogramTool *) tool->private;
  194.  
  195.   /*  Close the histogram dialog  */
  196.   if (histogram_tool_dialog)
  197.     histogram_tool_close_callback (NULL, (gpointer) histogram_tool_dialog);
  198.  
  199.   g_free (hist);
  200. }
  201.  
  202. void
  203. histogram_tool_initialize (GDisplay *gdisp)
  204. {
  205.   PixelRegion PR;
  206.  
  207.   if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
  208.     {
  209.       g_message (_("Histogram does not operate on indexed drawables."));
  210.       return;
  211.     }
  212.  
  213.   /*  The histogram_tool dialog  */
  214.   if (!histogram_tool_dialog)
  215.     histogram_tool_dialog = histogram_tool_dialog_new ();
  216.   else if (!GTK_WIDGET_VISIBLE (histogram_tool_dialog->shell))
  217.     gtk_widget_show (histogram_tool_dialog->shell);
  218.  
  219.   histogram_tool_dialog->drawable = gimage_active_drawable (gdisp->gimage);
  220.   histogram_tool_dialog->color = drawable_color (histogram_tool_dialog->drawable);
  221.  
  222.   /*  hide or show the channel menu based on image type  */
  223.   if (histogram_tool_dialog->color)
  224.     gtk_widget_show (histogram_tool_dialog->channel_menu);
  225.   else
  226.     gtk_widget_hide (histogram_tool_dialog->channel_menu);
  227.  
  228.   /* calculate the histogram */
  229.   pixel_region_init (&PR, drawable_data (histogram_tool_dialog->drawable), 0, 0,
  230.              drawable_width (histogram_tool_dialog->drawable),
  231.              drawable_height (histogram_tool_dialog->drawable),
  232.              FALSE);
  233.   gimp_histogram_calculate (histogram_tool_dialog->hist, &PR, NULL);
  234.  
  235.   histogram_widget_update (histogram_tool_dialog->histogram,
  236.                histogram_tool_dialog->hist);
  237.   histogram_widget_range (histogram_tool_dialog->histogram, 0, 255);
  238. }
  239.  
  240. /***************************/
  241. /*  Histogram Tool dialog  */
  242. /***************************/
  243.  
  244. static HistogramToolDialog *
  245. histogram_tool_dialog_new (void)
  246. {
  247.   HistogramToolDialog *htd;
  248.   GtkWidget *main_vbox;
  249.   GtkWidget *hbox;
  250.   GtkWidget *vbox;
  251.   GtkWidget *grad_hbox;
  252.   GtkWidget *frame;
  253.   GtkWidget *table;
  254.   GtkWidget *label;
  255.   GtkWidget *option_menu;
  256.   gint i;
  257.   gint x, y;
  258.  
  259.   static gchar * histogram_info_names[] =
  260.   {
  261.     N_("Mean:"),
  262.     N_("Std Dev:"),
  263.     N_("Median:"),
  264.     N_("Pixels:"),
  265.     N_("Intensity:"),
  266.     N_("Count:"),
  267.     N_("Percentile:")
  268.   };
  269.  
  270.   htd = g_new (HistogramToolDialog, 1);
  271.   htd->channel = GIMP_HISTOGRAM_VALUE;
  272.   htd->hist    = gimp_histogram_new ();
  273.  
  274.   /*  The shell and main vbox  */
  275.   htd->shell = gimp_dialog_new (_("Histogram"), "histogram",
  276.                 tools_help_func,
  277.                 tool_info[HISTOGRAM].private_tip,
  278.                 GTK_WIN_POS_NONE,
  279.                 FALSE, TRUE, FALSE,
  280.  
  281.                 _("Close"), histogram_tool_close_callback,
  282.                 htd, NULL, NULL, TRUE, TRUE,
  283.  
  284.                 NULL);
  285.  
  286.   main_vbox = gtk_vbox_new (FALSE, 4);
  287.   gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 4);
  288.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (htd->shell)->vbox), main_vbox);
  289.  
  290.   hbox = gtk_hbox_new (TRUE, 0);
  291.   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0);
  292.  
  293.   vbox = gtk_vbox_new (FALSE, 4);
  294.   gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
  295.  
  296.   /*  The option menu for selecting channels  */
  297.   htd->channel_menu = gtk_hbox_new (FALSE, 6);
  298.   gtk_box_pack_start (GTK_BOX (vbox), htd->channel_menu, FALSE, FALSE, 0);
  299.  
  300.   label = gtk_label_new (_("Information on Channel:"));
  301.   gtk_box_pack_start (GTK_BOX (htd->channel_menu), label, FALSE, FALSE, 0);
  302.   gtk_widget_show (label);
  303.  
  304.   option_menu = gimp_option_menu_new2
  305.     (FALSE, histogram_tool_channel_callback,
  306.      htd, (gpointer) htd->channel,
  307.  
  308.      _("Value"), (gpointer) GIMP_HISTOGRAM_VALUE, NULL,
  309.      _("Red"),   (gpointer) GIMP_HISTOGRAM_RED, NULL,
  310.      _("Green"), (gpointer) GIMP_HISTOGRAM_GREEN, NULL,
  311.      _("Blue"),  (gpointer) GIMP_HISTOGRAM_BLUE, NULL,
  312.  
  313.      NULL);
  314.   gtk_box_pack_start (GTK_BOX (htd->channel_menu), option_menu, FALSE, FALSE, 0);
  315.   gtk_widget_show (option_menu);
  316.  
  317.   gtk_widget_show (htd->channel_menu);
  318.  
  319.   /*  The histogram tool histogram  */
  320.   frame = gtk_frame_new (NULL);
  321.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  322.   gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  323.  
  324.   htd->histogram = histogram_widget_new (HISTOGRAM_WIDTH, HISTOGRAM_HEIGHT);
  325.   gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->histogram));
  326.  
  327.   gtk_signal_connect (GTK_OBJECT (htd->histogram), "range_changed",
  328.               GTK_SIGNAL_FUNC (histogram_tool_histogram_range),
  329.               htd);
  330.  
  331.   gtk_widget_show (GTK_WIDGET (htd->histogram));
  332.   gtk_widget_show (frame);
  333.  
  334.   /*  The gradient below the histogram */
  335.   grad_hbox = gtk_hbox_new (TRUE, 0);
  336.   gtk_box_pack_start (GTK_BOX (vbox), grad_hbox, FALSE, FALSE, 0);
  337.   frame = gtk_frame_new (NULL);
  338.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  339.   gtk_box_pack_start (GTK_BOX (grad_hbox), frame, FALSE, FALSE, 0);
  340.  
  341.   htd->gradient = gtk_preview_new (GTK_PREVIEW_COLOR);
  342.   gtk_preview_size (GTK_PREVIEW (htd->gradient), 
  343.             HISTOGRAM_WIDTH, GRADIENT_HEIGHT);
  344.   gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET(htd->gradient));
  345.   gtk_widget_show (htd->gradient);
  346.   gtk_widget_show (frame);
  347.   gtk_widget_show (grad_hbox);
  348.   histogram_tool_gradient_draw (htd->gradient, GIMP_HISTOGRAM_VALUE);
  349.  
  350.   gtk_widget_show (vbox);
  351.   gtk_widget_show (hbox);
  352.  
  353.   /*  The table containing histogram information  */
  354.   table = gtk_table_new (4, 4, TRUE);
  355.   gtk_table_set_col_spacings (GTK_TABLE (table), 6);
  356.   gtk_box_pack_start (GTK_BOX (main_vbox), table, FALSE, FALSE, 0);
  357.  
  358.   /*  the labels for histogram information  */
  359.   for (i = 0; i < 7; i++)
  360.     {
  361.       y = (i % 4);
  362.       x = (i / 4) * 2;
  363.  
  364.       label = gtk_label_new (gettext(histogram_info_names[i]));
  365.       gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  366.       gtk_table_attach (GTK_TABLE (table), label, x, x + 1, y, y + 1,
  367.             GTK_FILL, GTK_FILL, 2, 2);
  368.       gtk_widget_show (label);
  369.  
  370.       htd->info_labels[i] = gtk_label_new ("0");
  371.       gtk_misc_set_alignment (GTK_MISC (htd->info_labels[i]), 0.0, 0.5);
  372.       gtk_table_attach (GTK_TABLE (table), htd->info_labels[i],
  373.             x + 1, x + 2, y, y + 1,
  374.             GTK_FILL, GTK_FILL, 2, 2);
  375.       gtk_widget_show (htd->info_labels[i]);
  376.     }
  377.  
  378.   gtk_widget_show (table);
  379.  
  380.   gtk_widget_show (main_vbox);
  381.   gtk_widget_show (htd->shell);
  382.  
  383.   return htd;
  384. }
  385.  
  386. static void
  387. histogram_tool_close_callback (GtkWidget *widget,
  388.                    gpointer   data)
  389. {
  390.   HistogramToolDialog *htd;
  391.  
  392.   htd = (HistogramToolDialog *) data;
  393.  
  394.   gimp_dialog_hide (htd->shell);
  395.        
  396.   active_tool->gdisp_ptr = NULL;
  397.   active_tool->drawable = NULL;
  398. }
  399.  
  400. static void
  401. histogram_tool_channel_callback (GtkWidget *widget,
  402.                  gpointer   data)
  403. {
  404.   HistogramToolDialog *htd;
  405.  
  406.   htd = (HistogramToolDialog *) data;
  407.  
  408.   gimp_menu_item_update (widget, &htd->channel);
  409.  
  410.   histogram_widget_channel (htd->histogram, htd->channel);
  411.   histogram_tool_gradient_draw (htd->gradient, htd->channel);
  412. }
  413.  
  414. static void
  415. histogram_tool_gradient_draw (GtkWidget *gradient,
  416.                   gint       channel)
  417. {
  418.   guchar buf[HISTOGRAM_WIDTH * 3];
  419.   guchar r, g, b;
  420.   gint i;
  421.  
  422.   r = g = b = 0;
  423.   switch (channel)
  424.     {
  425.     case GIMP_HISTOGRAM_VALUE:
  426.     case GIMP_HISTOGRAM_ALPHA:  r = g = b = 1;
  427.       break;
  428.     case GIMP_HISTOGRAM_RED:    r = 1;
  429.       break;
  430.     case GIMP_HISTOGRAM_GREEN:  g = 1;
  431.       break;
  432.     case GIMP_HISTOGRAM_BLUE:   b = 1;
  433.       break;
  434.     default:
  435.       g_warning ("unknown channel type, can't happen\n");
  436.       break;
  437.     }
  438.   
  439.   for (i = 0; i < HISTOGRAM_WIDTH; i++)
  440.     {
  441.       buf[3*i+0] = i*r;
  442.       buf[3*i+1] = i*g;
  443.       buf[3*i+2] = i*b;
  444.     }
  445.  
  446.   for (i = 0; i < GRADIENT_HEIGHT; i++)
  447.     gtk_preview_draw_row (GTK_PREVIEW (gradient),
  448.               buf, 0, i, HISTOGRAM_WIDTH);
  449.   
  450.   gtk_widget_queue_draw (gradient);
  451. }
  452.  
  453.  
  454.