home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / plug-ins / common / checkerboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-24  |  9.7 KB  |  410 lines

  1. /*
  2.  * This is a plug-in for the GIMP.
  3.  *
  4.  * Copyright (C) 1997 Brent Burton & the Edward Blevins
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  19.  *
  20.  */
  21.  
  22. #include "config.h"
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26.  
  27. #include <gtk/gtk.h>
  28.  
  29. #include <libgimp/gimp.h>
  30. #include <libgimp/gimpui.h>
  31.  
  32. #include "libgimp/stdplugins-intl.h"
  33.  
  34.  
  35. /* Variables set in dialog box */
  36. typedef struct data
  37. {
  38.   gint mode;
  39.   gint size;
  40. } CheckVals;
  41.  
  42. typedef struct
  43. {
  44.   gint run;
  45. } CheckInterface;
  46.  
  47. static CheckInterface cint =
  48. {
  49.   FALSE
  50. };
  51.  
  52. static void      query  (void);
  53. static void      run    (gchar    *name,
  54.              gint      nparams,
  55.              GimpParam   *param,
  56.              gint     *nreturn_vals,
  57.              GimpParam  **return_vals);
  58.  
  59. static void      check   (GimpDrawable *drawable);
  60. static gint      inblock (gint       pos,
  61.               gint       size);
  62.  
  63. static gint      check_dialog      (void);
  64. static void      check_ok_callback (GtkWidget *widget,
  65.                     gpointer   data);
  66.  
  67. GimpPlugInInfo PLUG_IN_INFO =
  68. {
  69.   NULL,  /* init_proc  */
  70.   NULL,  /* quit_proc  */
  71.   query, /* query_proc */
  72.   run,   /* run_proc   */
  73. };
  74.  
  75. static CheckVals cvals =
  76. {
  77.    0,
  78.    10
  79. };
  80.  
  81. MAIN ()
  82.  
  83. static void
  84. query (void)
  85. {
  86.   static GimpParamDef args[] =
  87.   {
  88.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  89.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  90.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
  91.     { GIMP_PDB_INT32, "check_mode", "Regular or Physcobilly" },
  92.     { GIMP_PDB_INT32, "check_size", "Size of the checks" }
  93.   };
  94.   static gint nargs = sizeof (args) / sizeof (args[0]);
  95.  
  96.   gimp_install_procedure ("plug_in_checkerboard",
  97.               "Adds a checkerboard pattern to an image",
  98.               "More here later",
  99.               "Brent Burton & the Edward Blevins",
  100.               "Brent Burton & the Edward Blevins",
  101.               "1997",
  102.               N_("<Image>/Filters/Render/Pattern/Checkerboard..."),
  103.               "RGB*, GRAY*",
  104.               GIMP_PLUGIN,
  105.               nargs, 0,
  106.               args, NULL);
  107. }
  108.  
  109. static void
  110. run    (gchar    *name,
  111.     gint      nparams,
  112.     GimpParam   *param,
  113.     gint     *nreturn_vals,
  114.     GimpParam  **return_vals)
  115. {
  116.   static GimpParam values[1];
  117.   GimpDrawable *drawable;
  118.   GimpRunModeType run_mode;
  119.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
  120.  
  121.   INIT_I18N_UI();
  122.  
  123.   run_mode = param[0].data.d_int32;
  124.  
  125.   *nreturn_vals = 1;
  126.   *return_vals = values;
  127.  
  128.   values[0].type = GIMP_PDB_STATUS;
  129.   values[0].data.d_status = status;
  130.  
  131.   drawable = gimp_drawable_get (param[2].data.d_drawable);
  132.  
  133.   switch (run_mode)
  134.     {
  135.     case GIMP_RUN_INTERACTIVE:
  136.       gimp_get_data ("plug_in_checkerboard", &cvals);
  137.       if (! check_dialog())
  138.     {
  139.       gimp_drawable_detach (drawable);
  140.       return;
  141.     }
  142.       break;
  143.  
  144.     case GIMP_RUN_NONINTERACTIVE:
  145.       if (nparams != 5)
  146.     status = GIMP_PDB_CALLING_ERROR;
  147.       if (status == GIMP_PDB_SUCCESS)
  148.     {
  149.       cvals.mode = param[3].data.d_int32;
  150.       cvals.size = param[4].data.d_int32;
  151.     }
  152.       break;
  153.  
  154.     case GIMP_RUN_WITH_LAST_VALS:
  155.       gimp_get_data ("plug_in_checkerboard", &cvals);
  156.       break;
  157.  
  158.     default:
  159.       break;
  160.     }
  161.  
  162.   if (gimp_drawable_is_rgb (drawable->id) ||
  163.       gimp_drawable_is_gray (drawable->id))
  164.     {
  165.       gimp_progress_init (_("Adding Checkerboard..."));
  166.  
  167.       check (drawable);
  168.  
  169.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  170.     gimp_displays_flush ();
  171.  
  172.       if (run_mode == GIMP_RUN_INTERACTIVE)
  173.     gimp_set_data ("plug_in_checkerboard", &cvals, sizeof (CheckVals));
  174.     }
  175.   else
  176.     {
  177.       status = GIMP_PDB_EXECUTION_ERROR;
  178.     }
  179.  
  180.   values[0].data.d_status = status;
  181.  
  182.   gimp_drawable_detach (drawable);
  183. }
  184.  
  185.  
  186. static void
  187. check (GimpDrawable *drawable)
  188. {
  189.   GimpPixelRgn dest_rgn;
  190.   guchar *dest_row;
  191.   guchar *dest;
  192.   gint row, col;
  193.   gint progress, max_progress;
  194.   gint x1, y1, x2, y2, x, y;
  195.   guchar fg[4],bg[4];
  196.   gint bp;
  197.   gpointer pr;
  198.  
  199.   gimp_drawable_mask_bounds (drawable->id, &x1, &y1, &x2, &y2);
  200.   gimp_pixel_rgn_init (&dest_rgn, drawable,
  201.                x1, y1, (x2 - x1), (y2 - y1), TRUE, TRUE);
  202.  
  203.   progress = 0;
  204.   max_progress = (x2 - x1) * (y2 - y1);
  205.  
  206.   /* Get the foreground and background colors */
  207.  
  208.   switch ( gimp_drawable_type (drawable->id) )
  209.     {
  210.     case GIMP_RGBA_IMAGE:
  211.       fg[3] = 255;
  212.       bg[3] = 255;
  213.     case GIMP_RGB_IMAGE:
  214.       gimp_palette_get_foreground (&fg[0], &fg[1], &fg[2]);
  215.       gimp_palette_get_background (&bg[0], &bg[1], &bg[2]);
  216.       break;
  217.     case GIMP_GRAYA_IMAGE:
  218.       fg[1] = 255;
  219.       bg[1] = 255;
  220.     case GIMP_GRAY_IMAGE:
  221.       fg[0] = 255;
  222.       bg[0] = 0;
  223.       break;
  224.     default:
  225.       break;
  226.     }
  227.  
  228.   for (pr = gimp_pixel_rgns_register (1, &dest_rgn);
  229.        pr != NULL;
  230.        pr = gimp_pixel_rgns_process (pr))
  231.     {
  232.       y = dest_rgn.y;
  233.  
  234.       dest_row = dest_rgn.data;
  235.       for ( row = 0; row < dest_rgn.h; row++)
  236.     {
  237.       dest = dest_row;
  238.       x = dest_rgn.x;
  239.  
  240.       for (col = 0; col < dest_rgn.w; col++)
  241.         {
  242.           gint val, xp, yp;
  243.  
  244.           if (cvals.mode)
  245.         {
  246.           /* Psychobilly Mode */
  247.           val =
  248.             (inblock (x, cvals.size) == inblock (y, cvals.size)) ? 0 : 1;
  249.         }
  250.           else
  251.         {
  252.           /* Normal, regular checkerboard mode.
  253.            * Determine base factor (even or odd) of block
  254.            * this x/y position is in.
  255.            */
  256.           xp = x/cvals.size;
  257.           yp = y/cvals.size;
  258.           /* if both even or odd, color sqr */
  259.           val = ( (xp&1) == (yp&1) ) ? 0 : 1;
  260.         }
  261.           for (bp = 0; bp < dest_rgn.bpp; bp++)
  262.         dest[bp] = val ? fg[bp] : bg[bp];
  263.           dest += dest_rgn.bpp;
  264.           x++;
  265.         }
  266.       dest_row += dest_rgn.rowstride;
  267.       y++;
  268.     }
  269.       progress += dest_rgn.w * dest_rgn.h;
  270.       gimp_progress_update ((double) progress / (double) max_progress);
  271.     }
  272.   gimp_drawable_flush (drawable);
  273.   gimp_drawable_merge_shadow (drawable->id, TRUE);
  274.   gimp_drawable_update (drawable->id, x1, y1, (x2 - x1), (y2 - y1));
  275. }
  276.  
  277. static gint
  278. inblock (gint pos, 
  279.      gint size)
  280. {
  281.   static gint *in = NULL;        /* initialized first time */
  282.   gint i,j,k, len;
  283.  
  284.   /* avoid a FP exception */
  285.   if (size == 1)
  286.     size = 2;
  287.  
  288.   len = size*size;
  289.   /*
  290.    * Initialize the array; since we'll be called thousands of
  291.    * times with the same size value, precompute the array.
  292.    */
  293.   if (in == NULL)
  294.     {
  295.       in = g_new (gint, len);
  296.       if (in == NULL)
  297.     {
  298.       return 0;
  299.     }
  300.       else
  301.     {
  302.       int cell = 1;    /* cell value */
  303.       /*
  304.        * i is absolute index into in[]
  305.        * j is current number of blocks to fill in with a 1 or 0.
  306.        * k is just counter for the j cells.
  307.        */
  308.       i=0;
  309.       for (j=1; j<=size; j++ )
  310.         { /* first half */
  311.           for (k=0; k<j; k++ )
  312.         {
  313.           in[i++] = cell;
  314.         }
  315.           cell = !cell;
  316.         }
  317.       for ( j=size-1; j>=1; j--)
  318.         { /* second half */
  319.           for (k=0; k<j; k++ )
  320.         {
  321.           in[i++] = cell;
  322.         }
  323.           cell = !cell;
  324.         }
  325.     }
  326.     }
  327.  
  328.   /* place pos within 0..(len-1) grid and return the value. */
  329.   return in[ pos % (len-1) ];
  330. }
  331.  
  332. static gint
  333. check_dialog (void)
  334. {
  335.   GtkWidget *dlg;
  336.   GtkWidget *frame;
  337.   GtkWidget *vbox;
  338.   GtkWidget *toggle;
  339.   GtkWidget *table;
  340.   GtkObject *size_data;
  341.  
  342.   gimp_ui_init ("checkerboard", FALSE);
  343.  
  344.   dlg = gimp_dialog_new (_("Checkerboard"), "checkerboard",
  345.              gimp_standard_help_func, "filters/checkerboard.html",
  346.              GTK_WIN_POS_MOUSE,
  347.              FALSE, TRUE, FALSE,
  348.  
  349.              _("OK"), check_ok_callback,
  350.              NULL, NULL, NULL, TRUE, FALSE,
  351.              _("Cancel"), gtk_widget_destroy,
  352.              NULL, 1, NULL, FALSE, TRUE,
  353.  
  354.              NULL);
  355.  
  356.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  357.               GTK_SIGNAL_FUNC (gtk_main_quit),
  358.               NULL);
  359.  
  360.   /*  parameter settings  */
  361.   frame = gtk_frame_new (_("Parameter Settings"));
  362.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  363.   gtk_container_set_border_width (GTK_CONTAINER (frame), 6);
  364.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg)->vbox), frame, TRUE, TRUE, 0);
  365.  
  366.   vbox = gtk_vbox_new (FALSE, 4);
  367.   gtk_container_set_border_width (GTK_CONTAINER (vbox), 4);
  368.   gtk_container_add (GTK_CONTAINER (frame), vbox);
  369.  
  370.   toggle = gtk_check_button_new_with_label (_("Psychobilly"));
  371.   gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0);
  372.   gtk_signal_connect (GTK_OBJECT (toggle), "toggled",
  373.               GTK_SIGNAL_FUNC (gimp_toggle_button_update),
  374.               &cvals.mode);
  375.   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), cvals.mode);
  376.   gtk_widget_show (toggle);
  377.  
  378.   table = gtk_table_new (1, 3, FALSE);
  379.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  380.   gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
  381.   gtk_widget_show (table);
  382.  
  383.   size_data = gimp_scale_entry_new (GTK_TABLE (table), 0, 0,
  384.                     _("Check Size:"), 200, 0,
  385.                     cvals.size, 1, 400, 1, 10, 0,
  386.                     TRUE, 0, 0,
  387.                     NULL, NULL);
  388.   gtk_signal_connect (GTK_OBJECT (size_data), "value_changed",
  389.               GTK_SIGNAL_FUNC (gimp_int_adjustment_update),
  390.               &cvals.size);
  391.  
  392.   gtk_widget_show (vbox);
  393.   gtk_widget_show (frame);
  394.   gtk_widget_show (dlg);
  395.  
  396.   gtk_main ();
  397.   gdk_flush ();
  398.  
  399.   return cint.run;
  400. }
  401.  
  402. static void
  403. check_ok_callback (GtkWidget *widget,
  404.            gpointer   data)
  405. {
  406.   cint.run = TRUE;
  407.  
  408.   gtk_widget_destroy (GTK_WIDGET (data));
  409. }
  410.