cdisplay_highcontrast.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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. #include <string.h>
  20. #include <gtk/gtk.h>
  21. #include "app/dialog_handler.h"
  22. #include "gimpmodregister.h"
  23. #include <libgimp/gimpcolordisplay.h>
  24. #include <libgimp/gimpmodule.h>
  25. #include <libgimp/gimpparasite.h>
  26. #include <libgimp/gimpui.h>
  27. #include <libgimp/gimpmath.h>
  28. #include "libgimp/gimpintl.h"
  29. #define COLOR_DISPLAY_NAME _("High Contrast")
  30. typedef struct _ContrastContext ContrastContext;
  31. struct _ContrastContext
  32. {
  33. GFunc ok_func;
  34. gpointer ok_data;
  35. GFunc cancel_func;
  36. gpointer cancel_data;
  37. gdouble contrast;
  38. guchar *lookup;
  39. GtkWidget *shell;
  40. GtkWidget *spinner;
  41. };
  42. static gpointer contrast_new (gint type);
  43. static gpointer contrast_clone (gpointer cd_ID);
  44. static void contrast_create_lookup_table (ContrastContext *context);
  45. static void contrast_destroy (gpointer cd_ID);
  46. static void contrast_convert (gpointer cd_ID,
  47. guchar *buf,
  48. gint w,
  49. gint h,
  50. gint bpp,
  51. gint bpl);
  52. static void contrast_load (gpointer cd_ID,
  53. GimpParasite *state);
  54. static GimpParasite * contrast_save (gpointer cd_ID);
  55. static void contrast_configure_ok_callback (GtkWidget *widget,
  56. gpointer data);
  57. static void contrast_configure_cancel_callback (GtkWidget *widget,
  58. gpointer data);
  59. static void contrast_configure (gpointer cd_ID,
  60. GFunc ok_func,
  61. gpointer ok_data,
  62. GFunc cancel_func,
  63. gpointer cancel_data);
  64. static void contrast_configure_cancel (gpointer cd_ID);
  65. static GimpColorDisplayMethods methods =
  66. {
  67. NULL,
  68. contrast_new,
  69. contrast_clone,
  70. contrast_convert,
  71. contrast_destroy,
  72. NULL,
  73. contrast_load,
  74. contrast_save,
  75. contrast_configure,
  76. contrast_configure_cancel
  77. };
  78. static GimpModuleInfo info =
  79. {
  80. NULL,
  81. N_("High Contrast color display filter"),
  82. "Jay Cox <jaycox@earthlink.net>",
  83. "v0.2",
  84. "(c) 2000, released under the GPL",
  85. "October 14, 2000"
  86. };
  87. G_MODULE_EXPORT GimpModuleStatus
  88. module_init (GimpModuleInfo **inforet)
  89. {
  90. #ifndef __EMX__
  91. if (gimp_color_display_register (COLOR_DISPLAY_NAME, &methods))
  92. #else
  93. if (mod_color_display_register (COLOR_DISPLAY_NAME, &methods))
  94. #endif
  95. {
  96. *inforet = &info;
  97. return GIMP_MODULE_OK;
  98. }
  99. else
  100. return GIMP_MODULE_UNLOAD;
  101. }
  102. G_MODULE_EXPORT void
  103. module_unload (void *shutdown_data,
  104. void (*completed_cb) (void *),
  105. void *completed_data)
  106. {
  107. #ifndef __EMX__
  108. gimp_color_display_unregister (COLOR_DISPLAY_NAME);
  109. #else
  110. mod_color_display_unregister (COLOR_DISPLAY_NAME);
  111. #endif
  112. }
  113. static gpointer
  114. contrast_new (gint type)
  115. {
  116. ContrastContext *context;
  117. context = g_new0 (ContrastContext, 1);
  118. context->contrast = 4.0;
  119. context->lookup = g_new (guchar, 256);
  120. contrast_create_lookup_table (context);
  121. return context;
  122. }
  123. static gpointer
  124. contrast_clone (gpointer cd_ID)
  125. {
  126. ContrastContext *src_context = cd_ID;
  127. ContrastContext *context;
  128. context = contrast_new (0);
  129. context->contrast = src_context->contrast;
  130. memcpy (context->lookup, src_context->lookup, sizeof (guchar) * 256);
  131. return context;
  132. }
  133. static void
  134. contrast_create_lookup_table (ContrastContext *context)
  135. {
  136. gint i;
  137. if (context->contrast == 0.0)
  138. context->contrast = 1.0;
  139. for (i = 0; i < 256; i++)
  140. {
  141. context->lookup[i]
  142. = (guchar) (int)(255 * .5 * (1 + sin(context->contrast*2*G_PI*i/255.0)));
  143. }
  144. }
  145. static void
  146. contrast_destroy (gpointer cd_ID)
  147. {
  148. ContrastContext *context = cd_ID;
  149. if (context->shell)
  150. {
  151. dialog_unregister (context->shell);
  152. gtk_widget_destroy (context->shell);
  153. }
  154. g_free (context->lookup);
  155. g_free (context);
  156. }
  157. static void
  158. contrast_convert (gpointer cd_ID,
  159. guchar *buf,
  160. gint width,
  161. gint height,
  162. gint bpp,
  163. gint bpl)
  164. {
  165. guchar *lookup = ((ContrastContext *) cd_ID)->lookup;
  166. gint i, j = height;
  167. /* You will not be using the entire buffer most of the time.
  168. * Hence, the simplistic code for this is as follows:
  169. *
  170. * for (j = 0; j < height; j++)
  171. * {
  172. * for (i = 0; i < width * bpp; i++)
  173. * buf[i] = lookup[buf[i]];
  174. * buf += bpl;
  175. * }
  176. */
  177. width *= bpp;
  178. bpl -= width;
  179. while (j--)
  180. {
  181. i = width;
  182. while (i--)
  183. {
  184. *buf = lookup[*buf];
  185. buf++;
  186. }
  187. buf += bpl;
  188. }
  189. }
  190. static void
  191. contrast_load (gpointer cd_ID,
  192. GimpParasite *state)
  193. {
  194. ContrastContext *context = cd_ID;
  195. #if G_BYTE_ORDER == G_BIG_ENDIAN
  196. memcpy (&context->contrast, gimp_parasite_data (state), sizeof (gdouble));
  197. #else
  198. guint32 buf[2], *data = gimp_parasite_data (state);
  199. buf[0] = g_ntohl (data[1]);
  200. buf[1] = g_ntohl (data[0]);
  201. memcpy (&context->contrast, buf, sizeof (gdouble));
  202. #endif
  203. contrast_create_lookup_table (context);
  204. }
  205. static GimpParasite *
  206. contrast_save (gpointer cd_ID)
  207. {
  208. ContrastContext *context = cd_ID;
  209. guint32 buf[2];
  210. memcpy (buf, &context->contrast, sizeof (gdouble));
  211. #if G_BYTE_ORDER == G_LITTLE_ENDIAN
  212. {
  213. guint32 tmp = g_htonl (buf[0]);
  214. buf[0] = g_htonl (buf[1]);
  215. buf[1] = tmp;
  216. }
  217. #endif
  218. return gimp_parasite_new ("Display/Contrast", GIMP_PARASITE_PERSISTENT,
  219. sizeof (gdouble), &buf);
  220. }
  221. static void
  222. contrast_configure_ok_callback (GtkWidget *widget,
  223. gpointer data)
  224. {
  225. ContrastContext *context = data;
  226. context->contrast = gtk_spin_button_get_value_as_float (GTK_SPIN_BUTTON (context->spinner));
  227. contrast_create_lookup_table (context);
  228. dialog_unregister (context->shell);
  229. gtk_widget_destroy (GTK_WIDGET (context->shell));
  230. context->shell = NULL;
  231. if (context->ok_func)
  232. context->ok_func (context, context->ok_data);
  233. }
  234. static void
  235. contrast_configure_cancel_callback (GtkWidget *widget,
  236. gpointer data)
  237. {
  238. ContrastContext *context = data;
  239. dialog_unregister (context->shell);
  240. gtk_widget_destroy (GTK_WIDGET (context->shell));
  241. context->shell = NULL;
  242. if (context->cancel_func)
  243. context->cancel_func (context, context->cancel_data);
  244. }
  245. static void
  246. contrast_configure (gpointer cd_ID,
  247. GFunc ok_func,
  248. gpointer ok_data,
  249. GFunc cancel_func,
  250. gpointer cancel_data)
  251. {
  252. ContrastContext *context = cd_ID;
  253. GtkWidget *hbox;
  254. GtkWidget *label;
  255. GtkObject *adjustment;
  256. if (!context->shell)
  257. {
  258. context->ok_func = ok_func;
  259. context->ok_data = ok_data;
  260. context->cancel_func = cancel_func;
  261. context->cancel_data = cancel_data;
  262. context->shell =
  263. gimp_dialog_new (_("High Contrast"), "high contrast",
  264. gimp_standard_help_func, "modules/highcontrast.html",
  265. GTK_WIN_POS_MOUSE,
  266. FALSE, TRUE, FALSE,
  267. _("OK"), contrast_configure_ok_callback,
  268. cd_ID, NULL, NULL, TRUE, FALSE,
  269. _("Cancel"), contrast_configure_cancel_callback,
  270. cd_ID, NULL, NULL, FALSE, TRUE,
  271. NULL);
  272. dialog_register (context->shell);
  273. hbox = gtk_hbox_new (FALSE, 2);
  274. gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
  275. gtk_box_pack_start (GTK_BOX (GTK_DIALOG (context->shell)->vbox),
  276. hbox, FALSE, FALSE, 0);
  277. label = gtk_label_new ( _("Contrast Cycles:"));
  278. gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
  279. gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
  280. adjustment = gtk_adjustment_new (context->contrast, 1.0, 20.0, 0.5, 1.0, 0.0);
  281. context->spinner = gtk_spin_button_new (GTK_ADJUSTMENT (adjustment),
  282. 0.1, 3);
  283. gtk_widget_set_usize (context->spinner, 100, 0);
  284. gtk_box_pack_start (GTK_BOX (hbox), context->spinner, FALSE, FALSE, 0);
  285. }
  286. gtk_widget_show_all (context->shell);
  287. }
  288. static void
  289. contrast_configure_cancel (gpointer cd_ID)
  290. {
  291. ContrastContext *context = cd_ID;
  292. if (context->shell)
  293. {
  294. dialog_unregister (context->shell);
  295. gtk_widget_destroy (context->shell);
  296. context->shell = NULL;
  297. }
  298. if (context->cancel_func)
  299. context->cancel_func (context, context->cancel_data);
  300. }