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 / blur.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-10-15  |  19.4 KB  |  694 lines

  1. /****************************************************************************
  2.  * This is a plugin for the GIMP v 0.99.8 or later.  Documentation is
  3.  * available at http://www.rru.com/~meo/gimp/ .
  4.  *
  5.  * Copyright (C) 1997-98 Miles O'Neal  <meo@rru.com>  http://www.rru.com/~meo/
  6.  * Blur code Copyright (C) 1995 Spencer Kimball and Peter Mattis
  7.  * GUI based on GTK code from:
  8.  *    alienmap (Copyright (C) 1996, 1997 Daniel Cotting)
  9.  *    plasma   (Copyright (C) 1996 Stephen Norris),
  10.  *    oilify   (Copyright (C) 1996 Torsten Martinsen),
  11.  *    ripple   (Copyright (C) 1997 Brian Degenhardt) and
  12.  *    whirl    (Copyright (C) 1997 Federico Mena Quintero).
  13.  *
  14.  * This program is free software; you can redistribute it and/or modify
  15.  * it under the terms of the GNU General Public License as published by
  16.  * the Free Software Foundation; either version 2 of the License, or
  17.  * (at your option) any later version.
  18.  *
  19.  * This program is distributed in the hope that it will be useful,
  20.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.  * GNU General Public License for more details.
  23.  *
  24.  * You should have received a copy of the GNU General Public License
  25.  * along with this program; if not, write to the Free Software
  26.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  27.  *
  28.  ****************************************************************************/
  29.  
  30. /****************************************************************************
  31.  * Blur:
  32.  *
  33.  * blur version 2.0 (1 May 1998, MEO)
  34.  * history
  35.  *     2.0 -  1 May 1998 MEO
  36.  *         based on randomize 1.7
  37.  *
  38.  * Please send any patches or suggestions to the author: meo@rru.com .
  39.  * 
  40.  * Blur applies a 3x3 blurring convolution kernel to the specified drawable.
  41.  * 
  42.  * For each pixel in the selection or image,
  43.  * whether to change the pixel is decided by picking a
  44.  * random number, weighted by the user's "randomization" percentage.
  45.  * If the random number is in range, the pixel is modified.  For
  46.  * blurring, an average is determined from the current and adjacent
  47.  * pixels. *(Except for the random factor, the blur code came
  48.  * straight from the original S&P blur plug-in.)*
  49.  * 
  50.  * This works only with RGB and grayscale images.
  51.  * 
  52.  ****************************************************************************/
  53.  
  54. #ifdef HAVE_CONFIG_H
  55. #include "config.h"
  56. #endif
  57.  
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include <time.h>
  62.  
  63. #include <gtk/gtk.h>
  64.  
  65. #include <libgimp/gimp.h>
  66. #include <libgimp/gimpui.h>
  67.  
  68. #include "libgimp/stdplugins-intl.h"
  69.  
  70. /*********************************
  71.  *
  72.  *  PLUGIN-SPECIFIC CONSTANTS
  73.  *
  74.  ********************************/
  75.  
  76. /*
  77.  *  progress meter update frequency
  78.  */
  79. #define PROG_UPDATE_TIME ((row % 10) == 0)
  80.  
  81. #define PLUG_IN_NAME "plug_in_blur"
  82. #define BLUR_VERSION "Blur 2.0"
  83.  
  84. #define SEED_TIME 10
  85. #define SEED_USER 11
  86.  
  87. #define SCALE_WIDTH 100
  88.  
  89. /*********************************
  90.  *
  91.  *  PLUGIN-SPECIFIC STRUCTURES AND DATA
  92.  *
  93.  ********************************/
  94.  
  95. typedef struct
  96. {
  97.   gdouble blur_pct;     /* likelihood of randomization (as %age) */
  98.   gdouble blur_rcount;  /* repeat count */
  99.   gint    seed_type;    /* seed init. type - current time or user value */
  100.   gint    blur_seed;    /* seed value for rand() function */
  101. } BlurVals;
  102.  
  103. static BlurVals pivals =
  104. {
  105.   100.0,
  106.   1.0,
  107.   SEED_TIME,
  108.   0,
  109. };
  110.  
  111. typedef struct
  112. {
  113.   gint run;
  114. } BlurInterface;
  115.  
  116. static BlurInterface blur_int =
  117. {
  118.   FALSE     /*  have we run? */
  119. };
  120.  
  121.  
  122. /*********************************
  123.  *
  124.  *  LOCAL FUNCTIONS
  125.  *
  126.  ********************************/
  127.  
  128. static void query (void);
  129. static void run   (gchar   *name,
  130.            gint     nparams,
  131.            GimpParam  *param,
  132.            gint    *nreturn_vals,
  133.            GimpParam **return_vals);
  134.  
  135. GimpPlugInInfo PLUG_IN_INFO =
  136. {
  137.   NULL,  /* init_proc  */
  138.   NULL,  /* quit_proc  */
  139.   query, /* query_proc */
  140.   run,   /* run_proc   */
  141. };
  142.  
  143. static void blur (GimpDrawable *drawable);
  144.  
  145. static inline void blur_prepare_row (GimpPixelRgn *pixel_rgn,
  146.                      guchar    *data,
  147.                      gint       x,
  148.                      gint       y,
  149.                      gint       w);
  150.  
  151. static gint blur_dialog      (void);
  152. static void blur_ok_callback (GtkWidget *widget,
  153.                   gpointer   data);
  154.  
  155. /************************************ Guts ***********************************/
  156.  
  157. MAIN ()
  158.  
  159. /*********************************
  160.  *
  161.  *  query() - query_proc
  162.  *
  163.  *      called by the GIMP to learn about this plug-in
  164.  *
  165.  ********************************/
  166.  
  167. static void
  168. query (void)
  169. {
  170.   static GimpParamDef args_ni[] =
  171.   {
  172.     { GIMP_PDB_INT32, "run_mode", "non-interactive" },
  173.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  174.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }
  175.   };
  176.   static gint nargs_ni = sizeof(args_ni) / sizeof (args_ni[0]);
  177.  
  178.   static GimpParamDef args[] =
  179.   {
  180.     { GIMP_PDB_INT32, "run_mode", "Interactive, non-interactive" },
  181.     { GIMP_PDB_IMAGE, "image", "Input image (unused)" },
  182.     { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
  183.     { GIMP_PDB_FLOAT, "blur_pct", "Randomization percentage (1 - 100)" },
  184.     { GIMP_PDB_FLOAT, "blur_rcount", "Repeat count(1 - 100)" },
  185.     { GIMP_PDB_INT32, "seed_type", "Seed type (10 = current time, 11 = seed value)" },
  186.     { GIMP_PDB_INT32, "blur_seed", "Seed value (used only if seed type is 11)" }
  187.   };
  188.   static gint nargs = sizeof(args) / sizeof (args[0]);
  189.  
  190.   const gchar *blurb = "Apply a 3x3 blurring convolution kernel to the specified drawable.";
  191.   const gchar *help = "This plug-in randomly blurs the specified drawable, using a 3x3 blur.  You control the percentage of the pixels that are blurred and the number of times blurring is applied.  Indexed images are not supported.";
  192.   const gchar *author = "Miles O'Neal  <meo@rru.com>  http://www.rru.com/~meo/";
  193.   const gchar *copyrights = "Miles O'Neal, Spencer Kimball, Peter Mattis, Torsten Martinsen, Brian Degenhardt, Federico Mena Quintero, Stephen Norris, Daniel Cotting";
  194.   const gchar *copyright_date = "1995-1998";
  195.  
  196.   gimp_install_procedure ("plug_in_blur_randomize",
  197.               (gchar *) blurb,
  198.               (gchar *) help,
  199.               (gchar *) author,
  200.               (gchar *) copyrights,
  201.               (gchar *) copyright_date,
  202.               N_("<Image>/Filters/Blur/Blur..."),
  203.               "RGB*, GRAY*",
  204.               GIMP_PLUGIN,
  205.               nargs, 0,
  206.               args, NULL);
  207.  
  208.   gimp_install_procedure (PLUG_IN_NAME,
  209.               (gchar *) blurb,
  210.               (gchar *) help,
  211.               (gchar *) author,
  212.               (gchar *) copyrights,
  213.               (gchar *) copyright_date,
  214.               NULL,
  215.               "RGB*, GRAY*",
  216.               GIMP_PLUGIN,
  217.               nargs_ni, 0,
  218.               args_ni, NULL);
  219. }
  220.  
  221. /*********************************
  222.  *
  223.  *  run() - main routine
  224.  *
  225.  *  This handles the main interaction with the GIMP itself,
  226.  *  and invokes the routine that actually does the work.
  227.  *
  228.  ********************************/
  229.  
  230. static void
  231. run (gchar   *name, 
  232.      gint     nparams, 
  233.      GimpParam  *param, 
  234.      gint    *nreturn_vals,
  235.      GimpParam **return_vals)
  236. {
  237.   GimpDrawable *drawable;
  238.   GimpRunModeType run_mode;
  239.   GimpPDBStatusType status = GIMP_PDB_SUCCESS;        /* assume the best! */
  240.   gchar prog_label[32];
  241.   static GimpParam values[1];
  242.  
  243.   INIT_I18N_UI();
  244.  
  245.   /*
  246.    *  Get the specified drawable, do standard initialization.
  247.    */
  248.   run_mode = param[0].data.d_int32;
  249.   drawable = gimp_drawable_get(param[2].data.d_drawable);
  250.  
  251.   values[0].type = GIMP_PDB_STATUS;
  252.   values[0].data.d_status = status;
  253.   *nreturn_vals = 1;
  254.   *return_vals = values;
  255.   /*
  256.    *  Make sure the drawable type is appropriate.
  257.    */
  258.   if (gimp_drawable_is_rgb (drawable->id) ||
  259.       gimp_drawable_is_gray (drawable->id))
  260.     {
  261.       switch (run_mode)
  262.     {
  263.       /*
  264.        *  If we're running interactively, pop up the dialog box.
  265.        */
  266.     case GIMP_RUN_INTERACTIVE:
  267.       gimp_get_data (PLUG_IN_NAME, &pivals);
  268.       if (!blur_dialog ())        /* return on Cancel */
  269.         return;
  270.       break;
  271.  
  272.       /*
  273.        *  If we're not interactive (probably scripting), we
  274.        *  get the parameters from the param[] array, since
  275.        *  we don't use the dialog box.  Make sure all
  276.        *  parameters have legitimate values.
  277.        */
  278.     case GIMP_RUN_NONINTERACTIVE:
  279.       if ((strcmp (name, "plug_in_blur_randomize") == 0) &&
  280.           (nparams == 7))
  281.         {
  282.           pivals.blur_pct    = (gdouble) param[3].data.d_float;
  283.           pivals.blur_pct    = (gdouble) MIN (100.0, pivals.blur_pct);
  284.           pivals.blur_pct    = (gdouble) MAX (1.0, pivals.blur_pct);
  285.           pivals.blur_rcount = (gdouble) param[4].data.d_float;
  286.           pivals.blur_rcount = (gdouble) MIN (100.0,pivals.blur_rcount);
  287.           pivals.blur_rcount = (gdouble) MAX (1.0, pivals.blur_rcount);
  288.           pivals.seed_type   = (gint) param[5].data.d_int32;
  289.           pivals.seed_type   = (gint) MIN (SEED_USER, param[5].data.d_int32);
  290.           pivals.seed_type   = (gint) MAX (SEED_TIME, param[5].data.d_int32);
  291.           pivals.blur_seed   = (gint) param[6].data.d_int32;
  292.         }
  293.       else if ((strcmp (name, PLUG_IN_NAME) == 0) &&
  294.            (nparams == 3))
  295.         {
  296.           pivals.blur_pct    = (gdouble) 100.0;
  297.           pivals.blur_rcount = (gdouble) 1.0;
  298.           pivals.seed_type   = SEED_TIME;
  299.           pivals.blur_seed   = 0;
  300.         }
  301.       else
  302.         {
  303.           status = GIMP_PDB_CALLING_ERROR;
  304.         }
  305.       break;
  306.  
  307.       /*
  308.        *  If we're running with the last set of values, get those values.
  309.        */
  310.     case GIMP_RUN_WITH_LAST_VALS:
  311.       gimp_get_data (PLUG_IN_NAME, &pivals);
  312.       break;
  313.  
  314.       /*
  315.        *  Hopefully we never get here!
  316.        */
  317.     default:
  318.       break;
  319.         }
  320.  
  321.       if (status == GIMP_PDB_SUCCESS)
  322.     {
  323.       /*
  324.        *  JUST DO IT!
  325.        */
  326.       strcpy (prog_label, BLUR_VERSION);
  327.       gimp_progress_init (prog_label);
  328.       gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width() + 1));
  329.       /*
  330.        *  Initialize the rand() function seed
  331.        */
  332.       if (pivals.seed_type == SEED_TIME)
  333.         pivals.blur_seed = time (NULL);
  334.  
  335.       srand (pivals.blur_seed);
  336.  
  337.       blur (drawable);
  338.       /*
  339.        *  If we ran interactively (even repeating) update the display.
  340.        */
  341.       if (run_mode != GIMP_RUN_NONINTERACTIVE)
  342.         {
  343.           gimp_displays_flush ();
  344.             }
  345.       /*
  346.        *  If we use the dialog popup, set the data for future use.
  347.        */
  348.       if (run_mode == GIMP_RUN_INTERACTIVE)
  349.         {
  350.           gimp_set_data (PLUG_IN_NAME, &pivals, sizeof (BlurVals));
  351.             }
  352.         }
  353.     }
  354.   else
  355.     {
  356.       /*
  357.        *  If we got the wrong drawable type, we need to complain.
  358.        */
  359.       status = GIMP_PDB_EXECUTION_ERROR;
  360.     }
  361.   /*
  362.    *  DONE!
  363.    *  Set the status where the GIMP can see it, and let go
  364.    *  of the drawable.
  365.    */
  366.   values[0].data.d_status = status;
  367.   gimp_drawable_detach (drawable);
  368. }
  369.  
  370. /*********************************
  371.  *
  372.  *  blur_prepare_row()
  373.  *
  374.  *  Get a row of pixels.  If the requested row
  375.  *  is off the edge, clone the edge row.
  376.  *
  377.  ********************************/
  378.  
  379. static inline void
  380. blur_prepare_row (GimpPixelRgn *pixel_rgn, 
  381.           guchar    *data, 
  382.           int        x, 
  383.           int        y, 
  384.           int        w)
  385. {
  386.   int b;
  387.  
  388.   if (y == 0)
  389.     {
  390.       gimp_pixel_rgn_get_row(pixel_rgn, data, x, (y + 1), w);
  391.     }
  392.   else if (y == pixel_rgn->h)
  393.     {
  394.       gimp_pixel_rgn_get_row(pixel_rgn, data, x, (y - 1), w);
  395.     }
  396.   else
  397.     {
  398.       gimp_pixel_rgn_get_row(pixel_rgn, data, x, y, w);
  399.     }
  400.   /*
  401.    *  Fill in edge pixels
  402.    */
  403.   for (b = 0; b < pixel_rgn->bpp; b++)
  404.     {
  405.       data[-(gint)pixel_rgn->bpp + b] = data[b];
  406.       data[w * pixel_rgn->bpp + b] = data[(w - 1) * pixel_rgn->bpp + b];
  407.     }
  408. }
  409.  
  410. /*********************************
  411.  *
  412.  *  blur()
  413.  *
  414.  *  Actually mess with the image.
  415.  *
  416.  ********************************/
  417.  
  418. static void
  419. blur (GimpDrawable *drawable)
  420. {
  421.   GimpPixelRgn srcPR, destPR, destPR2, *sp, *dp, *tp;
  422.   gint width, height;
  423.   gint bytes;
  424.   guchar *dest, *d;
  425.   guchar *prev_row, *pr;
  426.   guchar *cur_row, *cr;
  427.   guchar *next_row, *nr;
  428.   guchar *tmp;
  429.   gint row, col;
  430.   gint x1, y1, x2, y2;
  431.   gint cnt;
  432.   gint has_alpha, ind;
  433.  
  434.   /*
  435.    *  Get the input area. This is the bounding box of the selection in
  436.    *  the image (or the entire image if there is no selection). Only
  437.    *  operating on the input area is simply an optimization. It doesn't
  438.    *  need to be done for correct operation. (It simply makes it go
  439.    *  faster, since fewer pixels need to be operated on).
  440.    */
  441.   gimp_drawable_mask_bounds(drawable->id, &x1, &y1, &x2, &y2);
  442.   /*
  443.    *  Get the size of the input image. (This will/must be the same
  444.    *  as the size of the output image.  Also get alpha info.
  445.    */
  446.   width = drawable->width;
  447.   height = drawable->height;
  448.   bytes = drawable->bpp;
  449.   has_alpha = gimp_drawable_has_alpha(drawable->id);
  450.   /*
  451.    *  allocate row buffers
  452.    */
  453.   prev_row = g_new (guchar, (x2 - x1 + 2) * bytes);
  454.   cur_row  = g_new (guchar, (x2 - x1 + 2) * bytes);
  455.   next_row = g_new (guchar, (x2 - x1 + 2) * bytes);
  456.   dest     = g_new (guchar, (x2 - x1) * bytes);
  457.  
  458.   /*
  459.    *  initialize the pixel regions
  460.    */
  461.   gimp_pixel_rgn_init (&srcPR, drawable, 0, 0, width, height, FALSE, FALSE);
  462.   gimp_pixel_rgn_init (&destPR, drawable, 0, 0, width, height, TRUE, TRUE);
  463.   gimp_pixel_rgn_init (&destPR2, drawable, 0, 0, width, height, TRUE, TRUE);
  464.   sp = &srcPR;
  465.   dp = &destPR;
  466.   tp = NULL;
  467.  
  468.   pr = prev_row + bytes;
  469.   cr = cur_row + bytes;
  470.   nr = next_row + bytes;
  471.  
  472.   for (cnt = 1; cnt <= pivals.blur_rcount; cnt++)
  473.     {
  474.       /*
  475.        *  prepare the first row and previous row
  476.        */
  477.       blur_prepare_row(sp, pr, x1, y1 - 1, (x2 - x1));
  478.       blur_prepare_row(dp, cr, x1, y1, (x2 - x1));
  479.       /*
  480.        *  loop through the rows, applying the selected convolution
  481.        */
  482.       for (row = y1; row < y2; row++)
  483.     {
  484.       /*  prepare the next row  */
  485.       blur_prepare_row(sp, nr, x1, row + 1, (x2 - x1));
  486.  
  487.       d = dest;
  488.       ind = 0;
  489.       for (col = 0; col < (x2 - x1) * bytes; col++)
  490.         {
  491.           if (((rand() % 100)) <= (gint) pivals.blur_pct)
  492.         {
  493.           ind++;
  494.           if (ind==bytes || !(has_alpha))
  495.             {
  496.               /*
  497.                *  If no alpha channel,
  498.                *   or if there is one and this is it...
  499.                */
  500.               *d++ = ((gint) pr[col - bytes] + (gint) pr[col] +
  501.                   (gint) pr[col + bytes] +
  502.                   (gint) cr[col - bytes] + (gint) cr[col] +
  503.                   (gint) cr[col + bytes] +
  504.                   (gint) nr[col - bytes] + (gint) nr[col] +
  505.                   (gint) nr[col + bytes]) / 9;
  506.               ind = 0;
  507.                     }
  508.           else
  509.             {
  510.               /*
  511.                *  otherwise we have an alpha channel,
  512.                *   but this is a color channel
  513.                */
  514.               *d++ = ((gint)
  515.                   (((gdouble) (pr[col - bytes] * pr[col - ind]) 
  516.                 + (gdouble) (pr[col] * pr[col + bytes - ind])
  517.                 + (gdouble) (pr[col + bytes] * pr[col + 2*bytes - ind])
  518.                 + (gdouble) (cr[col - bytes] * cr[col - ind])
  519.                 + (gdouble) (cr[col] * cr[col + bytes - ind])
  520.                 + (gdouble) (cr[col + bytes] * cr[col + 2*bytes - ind])
  521.                 + (gdouble) (nr[col - bytes] * nr[col - ind])
  522.                 + (gdouble) (nr[col] * nr[col + bytes - ind]) 
  523.                 + (gdouble) (nr[col + bytes] * nr[col + 2*bytes - ind]))
  524.                              / ((gdouble) pr[col - ind]
  525.                 + (gdouble) pr[col + bytes - ind]
  526.                 + (gdouble) pr[col + 2*bytes - ind]
  527.                 + (gdouble) cr[col - ind]
  528.                 + (gdouble) cr[col + bytes - ind]
  529.                 + (gdouble) cr[col + 2*bytes - ind]
  530.                 + (gdouble) nr[col - ind]
  531.                 + (gdouble) nr[col + bytes - ind]
  532.                 + (gdouble) nr[col + 2*bytes - ind])));
  533.                     }
  534.           /*
  535.            *  Otherwise, this pixel was not selected for randomization,
  536.            *  so use the current value.
  537.            */
  538.                 }
  539.           else
  540.         {
  541.           *d++ = (gint) cr[col];
  542.                 }
  543.             }
  544.       /*
  545.        *  Save the modified row, shuffle the row pointers, and every
  546.        *  so often, update the progress meter.
  547.        */
  548.       gimp_pixel_rgn_set_row(dp, dest, x1, row, (x2 - x1));
  549.  
  550.       tmp = pr;
  551.       pr = cr;
  552.       cr = nr;
  553.       nr = tmp;
  554.  
  555.       if (PROG_UPDATE_TIME)
  556.         gimp_progress_update((double) row / (double) (y2 - y1));
  557.         }
  558.       /*
  559.        *  if we have more cycles to perform, swap the src and dest Pixel Regions
  560.        */
  561.       if (cnt < pivals.blur_rcount)
  562.     {
  563.       if (tp != NULL)
  564.         {
  565.           tp = dp;
  566.           dp = sp;
  567.           sp = tp;
  568.             }
  569.       else
  570.         {
  571.           tp = &srcPR;
  572.           sp = &destPR;
  573.           dp = &destPR2;
  574.             }
  575.         }
  576.     }
  577.   gimp_progress_update ((double) 100);
  578.   /*
  579.    *  update the blurred region
  580.    */
  581.   gimp_drawable_flush(drawable);
  582.   gimp_drawable_merge_shadow(drawable->id, TRUE);
  583.   gimp_drawable_update(drawable->id, x1, y1, (x2 - x1), (y2 - y1));
  584.   /*
  585.    *  clean up after ourselves.
  586.    */
  587.   g_free (prev_row);
  588.   g_free (cur_row);
  589.   g_free (next_row);
  590.   g_free (dest);
  591. }
  592.  
  593. /*********************************
  594.  *  GUI ROUTINES
  595.  ********************************/
  596.  
  597. static gint
  598. blur_dialog (void)
  599. {
  600.   GtkWidget *dlg;
  601.   GtkWidget *frame;
  602.   GtkWidget *table;
  603.   GtkWidget *seed_hbox;
  604.   GtkObject *adj;
  605.  
  606.   gimp_ui_init ("blur", FALSE);
  607.  
  608.   dlg = gimp_dialog_new (BLUR_VERSION, "blur",
  609.              gimp_standard_help_func, "filters/blur.html",
  610.              GTK_WIN_POS_MOUSE,
  611.              FALSE, TRUE, FALSE,
  612.  
  613.              _("OK"), blur_ok_callback,
  614.              NULL, NULL, NULL, TRUE, FALSE,
  615.              _("Cancel"), gtk_widget_destroy,
  616.              NULL, 1, NULL, FALSE, TRUE,
  617.  
  618.              NULL);
  619.  
  620.   gtk_signal_connect (GTK_OBJECT (dlg), "destroy",
  621.               GTK_SIGNAL_FUNC (gtk_main_quit),
  622.               NULL);
  623.  
  624.   gimp_help_init ();
  625.  
  626.   /*
  627.    *  Parameter settings
  628.    *
  629.    *  First set up the basic containers, label them, etc.
  630.    */
  631.   frame = gtk_frame_new (_("Parameter Settings"));
  632.   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN);
  633.   gtk_container_set_border_width (GTK_CONTAINER(frame), 6);
  634.   gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dlg)->vbox), frame, TRUE, TRUE, 0);
  635.  
  636.   table = gtk_table_new (3, 3, FALSE);
  637.   gtk_table_set_col_spacings (GTK_TABLE (table), 4);
  638.   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
  639.   gtk_container_set_border_width (GTK_CONTAINER (table), 4);
  640.   gtk_container_add (GTK_CONTAINER (frame), table);
  641.   gtk_widget_show (table);
  642.  
  643.   /*  Random Seed  */
  644.   seed_hbox = gimp_random_seed_new (&pivals.blur_seed,
  645.                     &pivals.seed_type,
  646.                     SEED_TIME, SEED_USER);
  647.   gimp_table_attach_aligned (GTK_TABLE (table), 0, 0,
  648.                              _("Random Seed:"), 1.0, 0.5,
  649.                              seed_hbox, 1, TRUE);
  650.  
  651.   /*
  652.    *  Randomization percentage label & scale (1 to 100)
  653.    */
  654.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 1,
  655.                   _("Randomization %:"), SCALE_WIDTH, 0,
  656.                   pivals.blur_pct, 1.0, 100.0, 1.0, 10.0, 0,
  657.                   TRUE, 0, 0,
  658.                   _("Percentage of pixels to be filtered"), NULL);
  659.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  660.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  661.               &pivals.blur_pct);
  662.  
  663.   /*
  664.    *  Repeat count label & scale (1 to 100)
  665.    */
  666.   adj = gimp_scale_entry_new (GTK_TABLE (table), 0, 2,
  667.                   _("Repeat:"), SCALE_WIDTH, 0,
  668.                   pivals.blur_rcount, 1.0, 100.0, 1.0, 10.0, 0,
  669.                   TRUE, 0, 0,
  670.                   _("Number of times to apply filter"), NULL);
  671.   gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
  672.               GTK_SIGNAL_FUNC (gimp_double_adjustment_update),
  673.               &pivals.blur_rcount);
  674.  
  675.   gtk_widget_show (frame);
  676.  
  677.   gtk_widget_show (dlg);
  678.  
  679.   gtk_main ();
  680.   gimp_help_free ();
  681.   gdk_flush ();
  682.  
  683.   return blur_int.run;
  684. }
  685.  
  686. static void
  687. blur_ok_callback (GtkWidget *widget, 
  688.           gpointer   data) 
  689. {
  690.   blur_int.run = TRUE;
  691.  
  692.   gtk_widget_destroy (GTK_WIDGET (data));
  693. }
  694.