home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / modules / cdisplay_gamma.c next >
Encoding:
C/C++ Source or Header  |  2000-10-17  |  9.1 KB  |  373 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1999 Manish Singh <yosh@gimp.org>
  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 <string.h>
  21.  
  22. #include <gtk/gtk.h>
  23.  
  24. #include "app/dialog_handler.h"
  25.  
  26. #include "gimpmodregister.h"
  27.  
  28. #include <libgimp/gimpcolordisplay.h>
  29. #include <libgimp/gimpmodule.h>
  30. #include <libgimp/gimpparasite.h>
  31. #include <libgimp/gimpmath.h>
  32. #include <libgimp/gimpui.h>
  33.  
  34. #include "libgimp/gimpintl.h"
  35.  
  36.  
  37. #define COLOR_DISPLAY_NAME _("Gamma")
  38.  
  39. typedef struct _GammaContext GammaContext;
  40.  
  41. struct _GammaContext
  42. {
  43.   GFunc    ok_func;
  44.   gpointer ok_data;
  45.   GFunc    cancel_func;
  46.   gpointer cancel_data;
  47.  
  48.   gdouble  gamma;
  49.   guchar  *lookup;
  50.  
  51.   GtkWidget *shell;
  52.   GtkWidget *spinner;
  53. };
  54.  
  55. static gpointer       gamma_new                       (int           type);
  56. static gpointer       gamma_clone                     (gpointer      cd_ID);
  57. static void           gamma_create_lookup_table       (GammaContext *context);
  58. static void           gamma_destroy                   (gpointer      cd_ID);
  59. static void           gamma_convert                   (gpointer      cd_ID,
  60.                                guchar       *buf,
  61.                                int           w,
  62.                                int           h,
  63.                                int           bpp,
  64.                                int           bpl);
  65. static void           gamma_load                      (gpointer      cd_ID,
  66.                                GimpParasite *state);
  67. static GimpParasite * gamma_save                      (gpointer      cd_ID);
  68. static void           gamma_configure_ok_callback     (GtkWidget    *widget,
  69.                                gpointer      data);
  70. static void           gamma_configure_cancel_callback (GtkWidget    *widget,
  71.                                gpointer      data);
  72. static void           gamma_configure                 (gpointer      cd_ID,
  73.                                GFunc         ok_func,
  74.                                gpointer      ok_data,
  75.                                GFunc         cancel_func,
  76.                                gpointer      cancel_data);
  77. static void           gamma_configure_cancel          (gpointer      cd_ID);
  78.  
  79. static GimpColorDisplayMethods methods = 
  80. {
  81.   NULL,
  82.   gamma_new,
  83.   gamma_clone,
  84.   gamma_convert,
  85.   gamma_destroy,
  86.   NULL,
  87.   gamma_load,
  88.   gamma_save,
  89.   gamma_configure,
  90.   gamma_configure_cancel
  91. };
  92.  
  93. static GimpModuleInfo info = 
  94. {
  95.   NULL,
  96.   N_("Gamma color display filter"),
  97.   "Manish Singh <yosh@gimp.org>",
  98.   "v0.2",
  99.   "(c) 1999, released under the GPL",
  100.   "October 14, 2000"
  101. };
  102.  
  103. G_MODULE_EXPORT GimpModuleStatus
  104. module_init (GimpModuleInfo **inforet)
  105. {
  106. #ifndef __EMX__ 
  107.   if (gimp_color_display_register (COLOR_DISPLAY_NAME, &methods))
  108. #else
  109.   if (mod_color_display_register (COLOR_DISPLAY_NAME, &methods))
  110. #endif
  111.     {
  112.       *inforet = &info;
  113.       return GIMP_MODULE_OK;
  114.     }
  115.   else
  116.     return GIMP_MODULE_UNLOAD;
  117. }
  118.  
  119. G_MODULE_EXPORT void
  120. module_unload (void  *shutdown_data,
  121.            void (*completed_cb) (void *),
  122.            void  *completed_data)
  123. {
  124. #ifndef __EMX__
  125.   gimp_color_display_unregister (COLOR_DISPLAY_NAME);
  126. #else
  127.   mod_color_display_unregister (COLOR_DISPLAY_NAME);
  128. #endif
  129. }
  130.  
  131.  
  132. static gpointer
  133. gamma_new (int type)
  134. {
  135.   int i;
  136.   GammaContext *context;
  137.  
  138.   context = g_new0 (GammaContext, 1);
  139.   context->gamma = 1.0;
  140.   context->lookup = g_new (guchar, 256);
  141.  
  142.   for (i = 0; i < 256; i++)
  143.     context->lookup[i] = i;
  144.  
  145.   return context;
  146. }
  147.  
  148. static gpointer
  149. gamma_clone (gpointer cd_ID)
  150. {
  151.   GammaContext *src_context = cd_ID;
  152.   GammaContext *context;
  153.  
  154.   context = gamma_new (0);
  155.   context->gamma = src_context->gamma;
  156.   
  157.   memcpy (context->lookup, src_context->lookup, sizeof (guchar) * 256);
  158.  
  159.   return context;
  160. }
  161.  
  162. static void
  163. gamma_create_lookup_table (GammaContext *context)
  164. {
  165.   gdouble one_over_gamma;
  166.   gdouble ind;
  167.   gint    i;
  168.  
  169.   if (context->gamma == 0.0)
  170.     context->gamma = 1.0;
  171.  
  172.   one_over_gamma = 1.0 / context->gamma;
  173.  
  174.   for (i = 0; i < 256; i++)
  175.     {
  176.       ind = (double) i / 255.0;
  177.       context->lookup[i] = (guchar) (gint) (255 * pow (ind, one_over_gamma));
  178.     }
  179. }
  180.  
  181. static void
  182. gamma_destroy (gpointer cd_ID)
  183. {
  184.   GammaContext *context = cd_ID;
  185.  
  186.   if (context->shell)
  187.     {
  188.       dialog_unregister (context->shell);
  189.       gtk_widget_destroy (context->shell);
  190.     }
  191.  
  192.   g_free (context->lookup);
  193.   g_free (context);
  194. }
  195.  
  196. static void
  197. gamma_convert (gpointer  cd_ID,
  198.                guchar   *buf,
  199.            gint      width,
  200.            gint      height,
  201.            gint      bpp,
  202.            gint      bpl)
  203. {
  204.   guchar *lookup = ((GammaContext *) cd_ID)->lookup;
  205.   gint    i, j = height;
  206.  
  207.   /* You will not be using the entire buffer most of the time. 
  208.    * Hence, the simplistic code for this is as follows:
  209.    *
  210.    * for (j = 0; j < height; j++)
  211.    *   {
  212.    *     for (i = 0; i < width * bpp; i++)
  213.    *       buf[i] = lookup[buf[i]];
  214.    *     buf += bpl;
  215.    *   }
  216.    */
  217.  
  218.   width *= bpp;
  219.   bpl -= width;
  220.  
  221.   while (j--)
  222.     {
  223.       i = width;
  224.       while (i--)
  225.     {
  226.       *buf = lookup[*buf];
  227.       buf++;
  228.     }
  229.       buf += bpl;
  230.     }
  231. }
  232.  
  233. static void
  234. gamma_load (gpointer      cd_ID,
  235.             GimpParasite *state)
  236. {
  237.   GammaContext *context = cd_ID;
  238.  
  239. #if G_BYTE_ORDER == G_BIG_ENDIAN
  240.   memcpy (&context->gamma, gimp_parasite_data (state), sizeof (gdouble));
  241. #else
  242.   guint32 buf[2], *data = gimp_parasite_data (state);
  243.  
  244.   buf[0] = g_ntohl (data[1]);
  245.   buf[1] = g_ntohl (data[0]);
  246.  
  247.   memcpy (&context->gamma, buf, sizeof (gdouble));
  248. #endif
  249.  
  250.   gamma_create_lookup_table (context);
  251. }
  252.  
  253. static GimpParasite *
  254. gamma_save (gpointer cd_ID)
  255. {
  256.   GammaContext *context = cd_ID;
  257.   guint32 buf[2];
  258.  
  259.   memcpy (buf, &context->gamma, sizeof (double));
  260.  
  261. #if G_BYTE_ORDER == G_LITTLE_ENDIAN
  262.   {
  263.     guint32 tmp = g_htonl (buf[0]);
  264.     buf[0] = g_htonl (buf[1]);
  265.     buf[1] = tmp;
  266.   }
  267. #endif
  268.  
  269.   return gimp_parasite_new ("Display/Gamma", GIMP_PARASITE_PERSISTENT,
  270.                 sizeof (double), &buf);
  271. }
  272.  
  273. static void
  274. gamma_configure_ok_callback (GtkWidget *widget,
  275.                  gpointer   data)
  276. {
  277.   GammaContext *context = data;
  278.  
  279.   context->gamma =
  280.     gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (context->spinner));
  281.   gamma_create_lookup_table (context);
  282.  
  283.   dialog_unregister (context->shell);
  284.   gtk_widget_destroy (GTK_WIDGET (context->shell));
  285.   context->shell = NULL;
  286.  
  287.   if (context->ok_func)
  288.     context->ok_func (context, context->ok_data);
  289. }
  290.  
  291. static void
  292. gamma_configure_cancel_callback (GtkWidget *widget,
  293.                  gpointer   data)
  294. {
  295.   GammaContext *context = data;
  296.  
  297.   dialog_unregister (context->shell);
  298.   gtk_widget_destroy (GTK_WIDGET (context->shell));
  299.   context->shell = NULL;
  300.  
  301.   if (context->cancel_func)
  302.     context->cancel_func (context, context->cancel_data);
  303. }
  304.  
  305. static void
  306. gamma_configure (gpointer cd_ID,
  307.          GFunc    ok_func,
  308.          gpointer ok_data,
  309.          GFunc    cancel_func,
  310.          gpointer cancel_data)
  311. {
  312.   GammaContext *context = cd_ID;
  313.   GtkWidget *hbox;
  314.   GtkWidget *label;
  315.   GtkObject *adjustment;
  316.  
  317.   if (!context->shell)
  318.     {
  319.       context->ok_func = ok_func;
  320.       context->ok_data = ok_data;
  321.       context->cancel_func = cancel_func;
  322.       context->cancel_data = cancel_data;
  323.  
  324.       context->shell =
  325.     gimp_dialog_new (_("Gamma"), "gamma",
  326.              gimp_standard_help_func, "modules/gamma.html",
  327.              GTK_WIN_POS_MOUSE,
  328.              FALSE, TRUE, FALSE,
  329.  
  330.              _("OK"), gamma_configure_ok_callback,
  331.              cd_ID, NULL, NULL, TRUE, FALSE,
  332.              _("Cancel"), gamma_configure_cancel_callback,
  333.              cd_ID, NULL, NULL, FALSE, TRUE,
  334.  
  335.              NULL);
  336.  
  337.       dialog_register (context->shell);
  338.  
  339.       hbox = gtk_hbox_new (FALSE, 2);
  340.       gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
  341.       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (context->shell)->vbox),
  342.               hbox, FALSE, FALSE, 0);
  343.  
  344.       label = gtk_label_new ( _("Gamma:"));
  345.       gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  346.       gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
  347.  
  348.       adjustment = gtk_adjustment_new (context->gamma, 0.01, 10.0, 0.01, 0.1, 0.0);
  349.       context->spinner = gtk_spin_button_new (GTK_ADJUSTMENT (adjustment),
  350.                           0.1, 3);
  351.       gtk_widget_set_usize (context->spinner, 100, 0);
  352.       gtk_box_pack_start (GTK_BOX (hbox), context->spinner, FALSE, FALSE, 0);
  353.     }
  354.  
  355.   gtk_widget_show_all (context->shell);
  356. }
  357.  
  358. static void
  359. gamma_configure_cancel (gpointer cd_ID)
  360. {
  361.   GammaContext *context = cd_ID;
  362.  
  363.   if (context->shell)
  364.     {
  365.       dialog_unregister (context->shell);
  366.       gtk_widget_destroy (context->shell);
  367.       context->shell = NULL;
  368.     }
  369.  
  370.   if (context->cancel_func)
  371.     context->cancel_func (context, context->cancel_data);
  372. }
  373.