home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / posterize.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  9.3 KB  |  391 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 <glib.h>
  22.  
  23. #include "apptypes.h"
  24.  
  25. #include "appenv.h"
  26. #include "drawable.h"
  27. #include "gdisplay.h"
  28. #include "image_map.h"
  29. #include "posterize.h"
  30. #include "gimplut.h"
  31. #include "gimpui.h"
  32. #include "lut_funcs.h"
  33.  
  34. #include "libgimp/gimpintl.h"
  35.  
  36.  
  37. /*  the posterize structures  */
  38.  
  39. typedef struct _Posterize Posterize;
  40.  
  41. struct _Posterize
  42. {
  43.   gint x, y;    /*  coords for last mouse click  */
  44. };
  45.  
  46. typedef struct _PosterizeDialog PosterizeDialog;
  47.  
  48. struct _PosterizeDialog
  49. {
  50.   GtkWidget     *shell;
  51.  
  52.   GtkAdjustment *levels_data;
  53.  
  54.   GimpDrawable  *drawable;
  55.   ImageMap       image_map;
  56.  
  57.   gint           levels;
  58.  
  59.   gboolean       preview;
  60.  
  61.   GimpLut       *lut;
  62. };
  63.  
  64. /*  the posterize tool options  */
  65. static ToolOptions *posterize_options = NULL;
  66.  
  67. /* the posterize tool dialog  */
  68. static PosterizeDialog *posterize_dialog = NULL;
  69.  
  70.  
  71. /*  posterize action functions  */
  72. static void   posterize_control (Tool *, ToolAction, gpointer);
  73.  
  74. static PosterizeDialog * posterize_dialog_new (void);
  75.  
  76. static void   posterize_preview                  (PosterizeDialog *);
  77. static void   posterize_reset_callback           (GtkWidget *, gpointer);
  78. static void   posterize_ok_callback              (GtkWidget *, gpointer);
  79. static void   posterize_cancel_callback          (GtkWidget *, gpointer);
  80. static void   posterize_preview_update           (GtkWidget *, gpointer);
  81. static void   posterize_levels_adjustment_update (GtkAdjustment *, gpointer);
  82.  
  83. /*  posterize select action functions  */
  84.  
  85. static void
  86. posterize_control (Tool       *tool,
  87.            ToolAction  action,
  88.            gpointer    gdisp_ptr)
  89. {
  90.   switch (action)
  91.     {
  92.     case PAUSE:
  93.       break;
  94.  
  95.     case RESUME:
  96.       break;
  97.  
  98.     case HALT:
  99.       posterize_dialog_hide ();
  100.       break;
  101.  
  102.     default:
  103.       break;
  104.     }
  105. }
  106.  
  107. Tool *
  108. tools_new_posterize (void)
  109. {
  110.   Tool * tool;
  111.   Posterize * private;
  112.  
  113.   /*  The tool options  */
  114.   if (! posterize_options)
  115.     {
  116.       posterize_options = tool_options_new (("Posterize"));
  117.       tools_register (POSTERIZE, posterize_options);
  118.     }
  119.  
  120.   tool = tools_new_tool (POSTERIZE);
  121.   private = g_new0 (Posterize, 1);
  122.  
  123.   tool->scroll_lock = TRUE;   /*  Disallow scrolling  */
  124.   tool->preserve    = FALSE;  /*  Don't preserve on drawable change  */
  125.  
  126.   tool->private = (void *) private;
  127.  
  128.   tool->control_func = posterize_control;
  129.  
  130.   return tool;
  131. }
  132.  
  133. void
  134. posterize_dialog_hide (void)
  135. {
  136.   if (posterize_dialog)
  137.     posterize_cancel_callback (NULL, (gpointer) posterize_dialog);
  138. }
  139.  
  140. void
  141. tools_free_posterize (Tool *tool)
  142. {
  143.   Posterize * post;
  144.  
  145.   post = (Posterize *) tool->private;
  146.  
  147.   /*  Close the posterize dialog  */
  148.   posterize_dialog_hide ();
  149.  
  150.   g_free (post);
  151. }
  152.  
  153. void
  154. posterize_initialize (GDisplay *gdisp)
  155. {
  156.   if (drawable_indexed (gimage_active_drawable (gdisp->gimage)))
  157.     {
  158.       g_message (_("Posterize does not operate on indexed drawables."));
  159.       return;
  160.     }
  161.  
  162.   /*  The posterize dialog  */
  163.   if (!posterize_dialog)
  164.     posterize_dialog = posterize_dialog_new ();
  165.   else
  166.     if (!GTK_WIDGET_VISIBLE (posterize_dialog->shell))
  167.       gtk_widget_show (posterize_dialog->shell);
  168.  
  169.   posterize_dialog->levels = 3;
  170.  
  171.   posterize_dialog->drawable = gimage_active_drawable (gdisp->gimage);
  172.   posterize_dialog->image_map =
  173.     image_map_create (gdisp, posterize_dialog->drawable);
  174.  
  175.   gtk_adjustment_set_value (GTK_ADJUSTMENT (posterize_dialog->levels_data), 3);
  176.  
  177.   if (posterize_dialog->preview)
  178.     posterize_preview (posterize_dialog);
  179. }
  180.  
  181. /**********************/
  182. /*  Posterize dialog  */
  183. /**********************/
  184.  
  185. static PosterizeDialog *
  186. posterize_dialog_new (void)
  187. {
  188.   PosterizeDialog *pd;
  189.   GtkWidget *vbox;
  190.   GtkWidget *hbox;
  191.   GtkWidget *label;
  192.   GtkWidget *spinbutton;
  193.   GtkWidget *toggle;
  194.   GtkObject *data;
  195.  
  196.   pd = g_new (PosterizeDialog, 1);
  197.   pd->preview = TRUE;
  198.   pd->levels  = 3;
  199.   pd->lut     = gimp_lut_new ();
  200.  
  201.   /*  The shell and main vbox  */
  202.   pd->shell =
  203.     gimp_dialog_new (_("Posterize"), "posterize",
  204.              tools_help_func, NULL,
  205.              GTK_WIN_POS_NONE,
  206.              FALSE, TRUE, FALSE,
  207.  
  208.              _("OK"), posterize_ok_callback,
  209.              pd, NULL, NULL, TRUE, FALSE,
  210.              _("Reset"), posterize_reset_callback,
  211.              pd, NULL, NULL, TRUE, FALSE,
  212.              _("Cancel"), posterize_cancel_callback,
  213.              pd, NULL, NULL, FALSE, TRUE,
  214.  
  215.              NULL);
  216.  
  217.   vbox = gtk_vbox_new (FALSE, 2);
  218.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  219.   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (pd->shell)->vbox), vbox);
  220.  
  221.   /*  Horizontal box for levels text widget  */
  222.   hbox = gtk_hbox_new (FALSE, 4);
  223.   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  224.  
  225.   label = gtk_label_new (_("Posterize Levels:"));
  226.   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  227.   gtk_widget_show (label);
  228.  
  229.   /*  levels spinbutton  */
  230.   data = gtk_adjustment_new (3, 2, 256, 1.0, 10.0, 0.0);
  231.   pd->levels_data = GTK_ADJUSTMENT (data);
  232.  
  233.   spinbutton = gtk_spin_button_new (pd->levels_data, 1.0, 0);
  234.   gtk_widget_set_usize (spinbutton, 75, -1);
  235.   gtk_box_pack_start (GTK_BOX (hbox), spinbutton, FALSE, FALSE, 0);
  236.  
  237.   gtk_signal_connect (GTK_OBJECT (pd->levels_data), "value_changed",
  238.               GTK_SIGNAL_FUNC (posterize_levels_adjustment_update),
  239.               pd);
  240.  
  241.   gtk_widget_show (spinbutton);
  242.   gtk_widget_show (hbox);
  243.  
  244.   /*  Horizontal box for preview  */
  245.   hbox = gtk_hbox_new (FALSE, 4);
  246.   gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
  247.  
  248.   /*  The preview toggle  */
  249.   toggle = gtk_check_button_new_with_label (_("Preview"));
  250.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), pd->preview);
  251.   gtk_box_pack_end (GTK_BOX (hbox), toggle, FALSE, FALSE, 0);
  252.  
  253.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  254.               GTK_SIGNAL_FUNC (posterize_preview_update),
  255.               pd);
  256.  
  257.   gtk_widget_show (label);
  258.   gtk_widget_show (toggle);
  259.   gtk_widget_show (hbox);
  260.  
  261.   gtk_widget_show (vbox);
  262.   gtk_widget_show (pd->shell);
  263.  
  264.   return pd;
  265. }
  266.  
  267. static void
  268. posterize_preview (PosterizeDialog *pd)
  269. {
  270.   if (!pd->image_map)
  271.     {
  272.       g_warning ("posterize_preview(): No image map");
  273.       return;
  274.     }
  275.  
  276.   active_tool->preserve = TRUE;
  277.   posterize_lut_setup (pd->lut, pd->levels, gimp_drawable_bytes(pd->drawable));
  278.   image_map_apply (pd->image_map,  (ImageMapApplyFunc) gimp_lut_process_2,
  279.            (void *) pd->lut);
  280.   active_tool->preserve = FALSE;
  281. }
  282.  
  283. static void
  284. posterize_reset_callback (GtkWidget *widget,
  285.               gpointer   data)
  286. {
  287.   PosterizeDialog *pd;
  288.  
  289.   pd = (PosterizeDialog *) data;
  290.  
  291.   gtk_adjustment_set_value (GTK_ADJUSTMENT (pd->levels_data), 3);
  292. }
  293.  
  294. static void
  295. posterize_ok_callback (GtkWidget *widget,
  296.                gpointer   data)
  297. {
  298.   PosterizeDialog *pd;
  299.  
  300.   pd = (PosterizeDialog *) data;
  301.  
  302.   gimp_dialog_hide (pd->shell);
  303.  
  304.   active_tool->preserve = TRUE;
  305.  
  306.   if (!pd->preview)
  307.     {
  308.       posterize_lut_setup( pd->lut, pd->levels,
  309.                gimp_drawable_bytes (pd->drawable));
  310.       image_map_apply (pd->image_map, (ImageMapApplyFunc) gimp_lut_process_2,
  311.                (void *) pd->lut);
  312.     }
  313.  
  314.   if (pd->image_map)
  315.     image_map_commit (pd->image_map);
  316.  
  317.   active_tool->preserve = FALSE;
  318.  
  319.   pd->image_map = NULL;
  320.  
  321.   active_tool->gdisp_ptr = NULL;
  322.   active_tool->drawable = NULL;
  323. }
  324.  
  325. static void
  326. posterize_cancel_callback (GtkWidget *widget,
  327.                gpointer   data)
  328. {
  329.   PosterizeDialog *pd;
  330.  
  331.   pd = (PosterizeDialog *) data;
  332.  
  333.   gimp_dialog_hide (pd->shell);
  334.  
  335.   if (pd->image_map)
  336.     {
  337.       active_tool->preserve = TRUE;
  338.       image_map_abort (pd->image_map);
  339.       active_tool->preserve = FALSE;
  340.  
  341.       pd->image_map = NULL;
  342.       gdisplays_flush ();
  343.     }
  344.  
  345.   active_tool->gdisp_ptr = NULL;
  346.   active_tool->drawable = NULL;
  347. }
  348.  
  349. static void
  350. posterize_preview_update (GtkWidget *widget,
  351.               gpointer   data)
  352. {
  353.   PosterizeDialog *pd;
  354.  
  355.   pd = (PosterizeDialog *) data;
  356.  
  357.   if (GTK_TOGGLE_BUTTON (widget)->active)
  358.     {
  359.       pd->preview = TRUE;
  360.       posterize_preview (pd);
  361.     }
  362.   else
  363.     {
  364.       pd->preview = FALSE;
  365.       if (pd->image_map)
  366.     {
  367.       active_tool->preserve = TRUE;
  368.       image_map_clear (pd->image_map);
  369.       active_tool->preserve = FALSE;
  370.       gdisplays_flush ();
  371.     }
  372.     }
  373. }
  374.  
  375. static void
  376. posterize_levels_adjustment_update (GtkAdjustment *adjustment,
  377.                     gpointer       data)
  378. {
  379.   PosterizeDialog *pd;
  380.  
  381.   pd = (PosterizeDialog *) data;
  382.  
  383.   if (pd->levels != adjustment->value)
  384.     {
  385.       pd->levels = adjustment->value;
  386.  
  387.       if (pd->preview)
  388.     posterize_preview (pd);
  389.     }
  390. }
  391.