PTdecode/CImg-1.3.0/examples/greycstoration4gimp.cpp

Wed, 05 Aug 2009 15:02:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Wed, 05 Aug 2009 15:02:31 +0100
changeset 13
a933b13e087f
parent 5
1204ebf9340d
permissions
-rwxr-xr-x

PTdecode: add support for uncompressed data (NOTE: *NOT* supported by the PT-2450DX)

     1 /*
     2  #
     3  #  File        : greycstoration4gimp.cpp
     4  #                ( C++ source file )
     5  #
     6  #  Description : GREYCstoration - A tool to denoise, inpaint and resize images.
     7  #                ( GIMP>=2.3.4 plug-in version )
     8  #                This file is a part of the CImg Library project.
     9  #                ( http://cimg.sourceforge.net )
    10  #
    11  #    The GREYCstoration algorithm is an implementation of diffusion tensor-directed
    12  #    diffusion PDE's for image regularization and interpolation, published in
    13  #
    14  #    "Fast Anisotropic Smoothing of Multi-Valued Images
    15  #    using Curvature-Preserving PDE's"
    16  #    (D. Tschumperle)
    17  #    International Journal of Computer Vision, May 2006.
    18  #    (see also http://www.greyc.ensicaen.fr/~dtschump/greycstoration)
    19  #
    20  #    "Vector-Valued Image Regularization with PDE's : A Common Framework
    21  #    for Different Applications"
    22  #    (D. Tschumperle, R. Deriche).
    23  #    IEEE Transactions on Pattern Analysis and Machine Intelligence,
    24  #    Vol 27, No 4, pp 506-517, April 2005.
    25  #
    26  #    Copyright  : Grzegorz Szwoch (Original GIMP plugin code)
    27  #                 David Tschumperle (GREYCstoration API)
    28  #                 Nikita Melnichenko (Bugs corrections)
    29  #                 Phillip Wood (Contribution)
    30  #
    31  #    Plug-in version: 1.1
    32  #    Version history:
    33  #         2008.12.05
    34  #        - Support for denoising in YCrCb color space (patch by Phillip Wood)
    35  #    2.9 (2008.06.09)
    36  #        - New version number, following the release number of CImg.
    37  #        - Non-interactive mode allowed (patch by Nikita Melnichenko).
    38  #        - Pdb description parameters re-ordered (patch by Nikita Melnichenko).
    39  #        - Bug correction when dealing with 16 bits image processed in the
    40  #          YUV color space.
    41  #    1.1 (2007.03.31)
    42  #        - Added support for GimpZoomPreview (optional)
    43  #        - Make plug-in work for 1 bpp images
    44  #        - Added button to reset parameters to the initial state
    45  #    1.0 (2007.03.09)
    46  #        - Initial release
    47  #
    48  #  License     : CeCILL v2.0
    49  #                ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
    50  #
    51  #  This software is governed by the CeCILL  license under French law and
    52  #  abiding by the rules of distribution of free software.  You can  use,
    53  #  modify and/ or redistribute the software under the terms of the CeCILL
    54  #  license as circulated by CEA, CNRS and INRIA at the following URL
    55  #  "http://www.cecill.info".
    56  #
    57  #  As a counterpart to the access to the source code and  rights to copy,
    58  #  modify and redistribute granted by the license, users are provided only
    59  #  with a limited warranty  and the software's author,  the holder of the
    60  #  economic rights,  and the successive licensors  have only  limited
    61  #  liability.
    62  #
    63  #  In this respect, the user's attention is drawn to the risks associated
    64  #  with loading,  using,  modifying and/or developing or reproducing the
    65  #  software by the user in light of its specific status of free software,
    66  #  that may mean  that it is complicated to manipulate,  and  that  also
    67  #  therefore means  that it is reserved for developers  and  experienced
    68  #  professionals having in-depth computer knowledge. Users are therefore
    69  #  encouraged to load and test the software's suitability as regards their
    70  #  requirements in conditions enabling the security of their systems and/or
    71  #  data to be ensured and,  more generally, to use and operate it in the
    72  #  same conditions as regards security.
    73  #
    74  #  The fact that you are presently reading this means that you have had
    75  #  knowledge of the CeCILL license and that you accept its terms.
    76  #
    77 */
    79 /* HOW TO COMPILE THIS PLUG-IN ?
    80  *------------------------------
    81  * g++ -o greycstoration4gimp greycstoration4gimp.cpp `gimptool-2.0 --cflags` `gimptool-2.0 --libs` -lpthread -O3
    82  * Then, copy the file 'greycstoration4gimp' into your GIMP plug-in directory.
    83  */
    85 //----------------------------------
    86 // Define static plug-in parameters
    87 //----------------------------------
    89 // Comment the line below if you don't want to use preview with zoom (zoom feature needs GIMP >= 2.3.4)
    90 #define ZOOMPREVIEW
    91 // Uncomment this line to get a rough estimate of how long the plug-in takes to run
    92 // #define TIMER
    94 // Size of image tiles (in  {0, 256, 512, 1024, 2048})
    95 #define TILESIZE 256
    97 // Size of tile borders (in [0-16]).
    98 #define TILEBORDER  4
   100 // Number of simultaneous computation threads (in [1-16]).
   101 // Note : GREYCstoration multi-threading is HIGHLY experimental and may not work on your
   102 //        computer. Please use it only if you checked that all is working correctly !
   103 #define NTHREADS 1
   105 //-----------------------------------------------------------------------
   106 // Include necessary headers for GIMP, GTK and CImg + GREYCstoration API
   107 //-----------------------------------------------------------------------
   108 #if cimg_OS!=2
   109 #include <pthread.h>
   110 #endif
   111 #define cimg_plugin "plugins/greycstoration.h"
   112 #define cimg_display_type 0
   113 #include <gtk/gtk.h>
   114 #include <libgimp/gimp.h>
   115 #include <libgimp/gimpui.h>
   116 #include "plugins/../CImg.h"
   117 using namespace cimg_library;
   119 //----------------------------------------------------------
   120 // Define algorithm parameters structure and default values
   121 //----------------------------------------------------------
   122 struct Parameters {
   123   bool patch_based;     // Select patch-based or non-patch method
   125   // Parameters for patch-based method
   126   gint     patch_size;  // Size of the patches
   127   gdouble  sigma_p;     // Sigma_p
   128   gdouble  sigma_s;     // Sigma_s
   129   gint     lookup_size; // Lookup size
   131   // Parameters for non-patch method
   132   gdouble  amplitude;   // Regularization amplitude
   133   gdouble  sharpness;   // Contour preservation for regularization (sharpness)
   134   gdouble  anisotropy;  // Regularization anisotropy
   135   gdouble  alpha;       // Noise scale
   136   gdouble  sigma;       // Geometry regularity
   137   gdouble  dl;          // Spatial integration step for regularization
   138   gdouble  da;          // Angular integration step for regulatization
   139   gdouble  gauss_prec;  // Precision of the gaussian function for regularization
   140   gint     interp;      // Interpolation type
   141   bool     fast_approx; // Use fast approximation for regularization
   142   gint     channels;    // Which channels to process
   143   gint     iterations;  // Number of regularization iterations
   144   gboolean update_preview;
   145 };
   147 const Parameters defaults_parameters = {
   148   false, // patch_based
   149   4,     // patch_size
   150   10.0f, // sigma_p
   151   15.0f, // sigma_s
   152   7,     // Lookup size
   153   60.0,  // amplitude
   154   0.7,   // sharpness
   155   0.3,   // anisotropy
   156   0.6,   // alpha
   157   1.1,   // sigma
   158   0.8,   // dl
   159   30.0,  // da
   160   2.0,   // gauss_prec
   161   0,     // interp
   162   true,  // fast_approx
   163   0,     // process RGB channels
   164   1,     // iterations
   165   true   // default is to update the preview
   166 };
   168 const gint nb_parameters = 20; // Number of parameters + 2
   170 //---------------------------
   171 // GIMP plug-in declarations
   172 //---------------------------
   173 typedef struct {
   174   gboolean  run;
   175 } Interface;
   177 // Plug-in functions
   178 static void query(void);
   179 static void run(const gchar*name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals);
   180 static void process(GimpPixelRgn *srcPTR, GimpPixelRgn *dstPTR, gint bytes, gint x1, gint x2, gint y1, gint y2, gboolean show_progress);
   181 static void callback_response(GtkWidget *widget, gint response_id, gpointer data);
   182 static void run_greycstoration(CImg<unsigned char>& img, const gboolean show_progress);
   183 static gboolean dialog(GimpDrawable *drawable);
   184 static void update_preview(GimpPreview *preview);
   186 // Plug-in global variables
   187 static gboolean runflag = FALSE;
   188 static Parameters params = defaults_parameters;
   189 GtkWidget *preview;
   190 GtkObject* adj_amplitude;
   191 GtkObject* adj_sharpness;
   192 GtkObject* adj_anisotropy;
   193 GtkObject* adj_alpha;
   194 GtkObject* adj_sigma;
   195 GtkObject* adj_dl;
   196 GtkObject* adj_da;
   197 GtkObject* adj_iterations;
   198 GtkObject* adj_patch_size;
   199 GtkObject* adj_sigma_s;
   200 GtkObject* adj_sigma_p;
   201 GtkObject* adj_lookup_size;
   202 GtkWidget* combo_interp;
   203 GtkWidget* combo_channels;
   204 GtkWidget* button_fast_approx;
   205 GtkWidget* button_patch_based;
   206 CImg<unsigned char> img;
   208 // Specific GIMP stuffs.
   209 GimpPlugInInfo PLUG_IN_INFO = { 0,0,query,run };  // { init_proc, quit_proc, query_proc, run_proc }
   210 MAIN ()
   211   static void query(void) {
   212   static GimpParamDef args[] = {
   213     {GIMP_PDB_INT32,    "run_mode", "Interactive, non-interactive"},
   214     {GIMP_PDB_IMAGE,    "image", "(unused)"},
   215     {GIMP_PDB_DRAWABLE, "drawable", "Drawable to draw on"},
   216     {GIMP_PDB_FLOAT,    "amplitude", "Regularization strength for one iteration"},
   217     {GIMP_PDB_FLOAT,    "sharpness", "Contour preservation for regularization"},
   218     {GIMP_PDB_FLOAT,    "anisotropy", "Regularization anisotropy"},
   219     {GIMP_PDB_FLOAT,    "alpha", "Noise scale"},
   220     {GIMP_PDB_FLOAT,    "sigma", "Geometry regularity"} ,
   221     {GIMP_PDB_FLOAT,    "dl", "Spatial integration step for regularization"} ,
   222     {GIMP_PDB_FLOAT,    "da", "Angular integration step for regulatization"},
   223     {GIMP_PDB_FLOAT,    "gauss_prec", "Precision of the gaussian function for regularization"},
   224     {GIMP_PDB_INT8,     "interp", "Interpolation type"},
   225     {GIMP_PDB_INT32,    "patch_based", "Use patch-based intead of non-patch method"},
   226     {GIMP_PDB_INT32,    "patch_size", "Size of the patches (for patch-based method)"},
   227     {GIMP_PDB_FLOAT,    "sigma_p", "Sigma_p (for patch-based method)"},
   228     {GIMP_PDB_FLOAT,    "sigma_s", "Sigma_s (for patch-based method)"},
   229     {GIMP_PDB_INT32,    "lookup_size", "Lookup size (for patch-based method)"},
   230     {GIMP_PDB_INT32,    "fast_approx", "Use fast approximation for regularization"},
   231     {GIMP_PDB_INT32,    "channels", "Channels to process"},
   232     {GIMP_PDB_INT32,    "iterations", "Iterations accuracy"}
   233   };
   234   gimp_install_procedure ("plug_in_greycstoration",
   235                           "GREYCstoration Denoising Plugin",
   236                           "GREYCstoration is an image regularization algorithm which is able to process"
   237                           " a color image by locally removing small variations of pixel intensities"
   238                           " while preserving significant global image features, such as edges and corners."
   239                           " This plugin uses image regularization for image denoising.",
   240                           "Grzegorz Szwoch & David Tschumperle",
   241                           "Grzegorz Szwoch & David Tschumperle",
   242                           "2008-06-02",
   243                           "_GREYCstoration...",
   244                           "RGB*, GRAY*",
   245                           GIMP_PLUGIN,G_N_ELEMENTS(args),0,args, NULL);
   246   gimp_plugin_menu_register ("plug_in_greycstoration", "<Image>/Filters/Enhance");
   247 }
   249 //------------------------------
   250 // GIMP plug-in 'run' function
   251 //------------------------------
   252 static void run(const gchar *name, gint nparams, const GimpParam *param, gint *nreturn_vals, GimpParam **return_vals) {
   253   name = 0;
   254   static GimpParam values[1];
   255   GimpPDBStatusType status = GIMP_PDB_SUCCESS;
   256   GimpDrawable *drawable;
   257   GimpRunMode run_mode;
   258 #ifdef TIMER
   259   GTimer *timer = g_timer_new ();
   260 #endif
   261   run_mode = (GimpRunMode)param[0].data.d_int32;
   262   *return_vals  = values;
   263   *nreturn_vals = 1;
   264   values[0].type = GIMP_PDB_STATUS;
   265   values[0].data.d_status = status;
   266   //INIT_I18N ();
   268   // Get drawable information
   269   drawable = gimp_drawable_get(param[2].data.d_drawable);
   271   // Make tile cache
   272   gimp_tile_cache_ntiles (2 * (drawable->width / gimp_tile_width () + 1));
   274   switch (run_mode) {
   275   case GIMP_RUN_INTERACTIVE:
   276     gimp_get_data ("plug_in_greycstoration", &params);    // Reset default values show preview unmodified
   277     if (!dialog(drawable)) return;
   278     break;
   279   case GIMP_RUN_NONINTERACTIVE:
   280     if (nparams != nb_parameters) { status = GIMP_PDB_CALLING_ERROR; }
   281     else {
   282       params.amplitude = param[3].data.d_float;
   283       params.sharpness = param[4].data.d_float;
   284       params.anisotropy = param[5].data.d_float;
   285       params.alpha = param[6].data.d_float;
   286       params.sigma = param[7].data.d_float;
   287       params.dl = param[8].data.d_float;
   288       params.da = param[9].data.d_float;
   289       params.gauss_prec = param[10].data.d_float;
   290       params.interp = param[11].data.d_int32;
   291       params.patch_based = param[12].data.d_int32;
   292       params.patch_size = param[13].data.d_int32;
   293       params.sigma_p = param[14].data.d_float;
   294       params.sigma_s = param[15].data.d_float;
   295       params.lookup_size = param[16].data.d_int32;
   296       params.fast_approx = param[17].data.d_int32;
   297       params.channels = param[18].data.d_int32;
   298       params.iterations = param[19].data.d_int32;
   299       if((params.amplitude<0.0) || (params.sharpness<0.0)) status = GIMP_PDB_CALLING_ERROR;
   300     }
   301     break;
   302   case GIMP_RUN_WITH_LAST_VALS:
   303     gimp_get_data ("plug_in_greycstoration", &params);
   304     break;
   305   default:
   306     break;
   307   }
   309   if(status==GIMP_PDB_SUCCESS) {
   310     drawable = gimp_drawable_get(param[2].data.d_drawable);
   312     // Process image
   313     GimpPixelRgn srcPR, destPR;
   314     gint         x1, y1, x2, y2;
   316     // Initialize pixel regions
   317     gimp_pixel_rgn_init(&srcPR,drawable,0,0,drawable->width,drawable->height,false,false);
   318     gimp_pixel_rgn_init(&destPR,drawable,0,0,drawable->width,drawable->height,true,true);
   320     // Get the input
   321     gimp_drawable_mask_bounds(drawable->drawable_id,&x1,&y1,&x2,&y2);
   323     // Process region
   324     process(&srcPR,&destPR,drawable->bpp,x1,x2,y1,y2,true);
   326     // Update image and clean
   327     gimp_drawable_flush(drawable);
   328     gimp_drawable_merge_shadow(drawable->drawable_id,true);
   329     gimp_drawable_update(drawable->drawable_id,x1,y1,x2-x1,y2-y1);
   330     gimp_displays_flush();
   332     // Set data for next use of filter
   333     gimp_set_data("plug_in_greycstoration",&params,sizeof(Parameters));
   334     gimp_drawable_detach(drawable);
   335     values[0].data.d_status = status;
   336   }
   338 #ifdef TIMER
   339   g_printerr("%f seconds\n",g_timer_elapsed(timer,0));
   340   g_timer_destroy(timer);
   341 #endif
   342 }
   344 //-----------------------------------
   345 // GIMP plug-in 'process' function
   346 //-----------------------------------
   347 static void process(GimpPixelRgn *srcPR, GimpPixelRgn *destPR, gint bytes, gint x1, gint x2, gint y1, gint y2, gboolean show_progress) {
   348   gint width  = x2 - x1;
   349   gint height = y2 - y1;
   350   guchar* row, *row_ptr;
   351   if (show_progress) gimp_progress_init("GREYCstoration Filter...");
   353   // Make CImg instance and fill it with image information
   354   const gint channels = (bytes<3)?1:3;
   355   img.assign(width,height,1,channels,0);
   356   row = g_new(guchar,width*bytes);
   357   cimg_forY(img,y) {
   358     gimp_pixel_rgn_get_row(srcPR,row,x1,y1+y,width);
   359     row_ptr = row;
   360     cimg_forX(img,x) { cimg_forV(img,k) img(x,y,k) = row_ptr[k]; row_ptr+=bytes; }
   361   }
   363   // run GREYCstoration processing
   364   run_greycstoration(img,show_progress);
   366   // Write processed image
   367   cimg_forY(img,y) {
   368     gimp_pixel_rgn_get_row(srcPR,row,x1,y1+y,width);
   369     row_ptr = row;
   370     cimg_forX(img,x) { cimg_forV(img,k) row_ptr[k] = img(x,y,k); row_ptr+=bytes; }
   371     gimp_pixel_rgn_set_row(destPR,row,x1,y1+y,width);
   372   }
   373   g_free(row);
   374 }
   376 //-----------------------------------------
   377 // Run GREYCstoration process on the image
   378 //-----------------------------------------
   379 static void run_greycstoration(CImg<unsigned char>& img, const gboolean show_progress) {
   380   guint crange_beg=0, crange_end = img.dimv()-1U;
   381   if (params.channels && img.dimv() > 1) { // Set up colour model and channel options
   382     img.RGBtoYCbCr();
   383     if (params.channels == 1) {
   384       crange_beg=1;
   385     } else {
   386       crange_end=0;
   387     }
   388   }
   389   CImg<unsigned char> img_range = img.get_shared_channels(crange_beg, crange_end);
   391   for (gint iter=0; iter<params.iterations; ++iter) {
   392     if (params.patch_based) img_range.greycstoration_patch_run(params.patch_size,
   393                                                          params.sigma_p,
   394                                                          params.sigma_s,
   395                                                          params.lookup_size,
   396                                                          params.fast_approx,
   397                                                          show_progress?TILESIZE:0,
   398                                                          TILEBORDER,
   399                                                          show_progress?NTHREADS:1);
   400     else img_range.greycstoration_run(params.amplitude,
   401                                 params.sharpness,
   402                                 params.anisotropy,
   403                                 params.alpha,
   404                                 params.sigma,
   405                                 1.0f,
   406                                 params.dl,
   407                                 params.da,
   408                                 params.gauss_prec,
   409                                 params.interp,
   410                                 params.fast_approx,
   411                                 show_progress?TILESIZE:0,
   412                                 TILEBORDER,
   413                                 show_progress?NTHREADS:1);
   414     gint tick = 0;
   415     do {
   416       cimg::wait(100);
   417       ++tick;
   418       if (tick==10 && show_progress) { // Update progress bar
   419         const float pr_iteration = img_range.greycstoration_progress();
   420         const unsigned int pr_global = (unsigned int)((iter*100 + pr_iteration) / params.iterations);
   421         gimp_progress_update(pr_global/100.0);
   422         tick = 0;
   423       }
   424     } while (img_range.greycstoration_is_running());
   425   }
   426   if (params.channels && img.dimv() > 1) { // Convert back to RGB if required
   427     img.YCbCrtoRGB();
   428   }
   429 }
   431 //----------------------
   432 // Update image preview
   433 //----------------------
   434 static void update_preview(GimpPreview *preview) {
   435 #ifdef ZOOMPREVIEW
   436   // Zoomable style preview
   437   //-------------------------
   438   gint width, height, bytes;
   439   guchar *src, *row_ptr;
   440   if (img.greycstoration_is_running()) img.greycstoration_stop();
   441   src = gimp_zoom_preview_get_source(GIMP_ZOOM_PREVIEW(preview),&width,&height,&bytes);
   442   const gint channels = (bytes<3)?1:3;
   443   img.assign(width,height,1,channels,0);
   444   row_ptr = src;
   445   cimg_forY(img,y) { cimg_forX(img,x) { cimg_forV(img,k) img(x,y,k) = row_ptr[k]; row_ptr += bytes; }}
   446   run_greycstoration(img,false);
   447   row_ptr = src;
   448   cimg_forY(img,y) { cimg_forX(img,x) { cimg_forV(img,k) row_ptr[k] = img(x,y,k); row_ptr += bytes; }}
   449   gimp_preview_draw_buffer(preview,src,width*bytes);
   450   g_free(src);
   452 #else
   453   // Old style preview (without zoom)
   454   //----------------------------------
   455   GimpDrawable *drawable;
   456   gint x, y, width, height;
   457   GimpPixelRgn srcPR, destPR;
   458   drawable = gimp_drawable_preview_get_drawable(GIMP_DRAWABLE_PREVIEW(preview));
   459   gimp_pixel_rgn_init(&srcPR,drawable,0,0,drawable->width,drawable->height,false,false);
   460   gimp_pixel_rgn_init(&destPR,drawable,0,0,drawable->width,drawable->height,true,true);
   461   gimp_preview_get_position(preview,&x,&y);
   462   gimp_preview_get_size(preview,&width,&height);
   463   if(img.greycstoration_is_running()) img.greycstoration_stop();
   464   process(&srcPR,&destPR,drawable->bpp,x,x+width,y,y+height,false);
   465   gimp_pixel_rgn_init(&destPR,drawable,x,y,width,height,false,true);
   466   gimp_drawable_preview_draw_region(GIMP_DRAWABLE_PREVIEW(preview),&destPR);
   467 #endif
   468 }
   470 //----------------------
   471 // Define dialog window
   472 //----------------------
   473 static gboolean dialog (GimpDrawable *drawable) {
   474   GtkWidget *dialog;
   475   GtkWidget *main_hbox;
   476   GtkWidget *table;
   478 #define SCALE_WIDTH   150
   479 #define ENTRY_WIDTH     4
   480 #define RESPONSE_RESET  1
   482   gimp_ui_init("greycstoration",true);
   483   runflag = false;
   484   dialog = gimp_dialog_new("GREYCstoration", "greycstoration",0,(GtkDialogFlags)0,gimp_standard_help_func,"plug-in-greycstoration",
   485                            GIMP_STOCK_RESET,RESPONSE_RESET,GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL,GTK_STOCK_OK,GTK_RESPONSE_OK,NULL);
   486   gtk_dialog_set_alternative_button_order(GTK_DIALOG(dialog),RESPONSE_RESET,GTK_RESPONSE_OK,GTK_RESPONSE_CANCEL,-1);
   488 #ifdef ZOOMPREVIEW
   489   gimp_window_set_transient(GTK_WINDOW (dialog));
   490 #endif
   492   g_signal_connect(dialog,"response",G_CALLBACK(callback_response),preview);
   493   g_signal_connect(dialog, "destroy",G_CALLBACK(gtk_main_quit),0);
   495   main_hbox = gtk_hbox_new(false,12);
   496   gtk_container_set_border_width(GTK_CONTAINER(main_hbox),12);
   497   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox),main_hbox);
   498   gtk_widget_show(main_hbox);
   500 #ifdef ZOOMPREVIEW
   501   preview = gimp_zoom_preview_new(drawable);
   502 #else
   503   preview = gimp_drawable_preview_new(drawable,&params.update_preview);
   504 #endif
   505   gtk_box_pack_start(GTK_BOX(main_hbox),preview,true,true,0);
   506   gtk_widget_show(preview);
   507   g_signal_connect(preview,"invalidated",G_CALLBACK(update_preview),0);
   509   table = gtk_table_new(3,3,false);
   510   gtk_table_set_col_spacings(GTK_TABLE(table),6);
   511   gtk_table_set_row_spacings(GTK_TABLE(table),6);
   512   gtk_box_pack_start(GTK_BOX(main_hbox),table,false,false,0);
   513   gtk_widget_show(table);
   515   // 'Amplitude' slider
   516   adj_amplitude = gimp_scale_entry_new(GTK_TABLE(table),0,0,"_Strength :",SCALE_WIDTH,ENTRY_WIDTH,
   517                                        params.amplitude,0.0,200.0,1,10,1,true,0,0,0,0);
   518   g_signal_connect(adj_amplitude,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.amplitude);
   519   g_signal_connect_swapped(adj_amplitude,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   521   // 'Sharpness' slider
   522   adj_sharpness = gimp_scale_entry_new(GTK_TABLE(table),0,1,"Contour preser_vation :",SCALE_WIDTH,ENTRY_WIDTH,
   523                                        params.sharpness,0.0,5.0,0.05,0.5,2,true,0,0,0,0);
   524   g_signal_connect(adj_sharpness,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.sharpness);
   525   g_signal_connect_swapped(adj_sharpness,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   527   // 'Anisotropy' slider
   528   adj_anisotropy = gimp_scale_entry_new(GTK_TABLE(table),0,2,"_Anisotropy :",SCALE_WIDTH,ENTRY_WIDTH,
   529                                         params.anisotropy,0.0,1.0,0.05,0.5,2,true,0,0,0,0);
   530   g_signal_connect(adj_anisotropy,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.anisotropy);
   531   g_signal_connect_swapped(adj_anisotropy,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   533   // 'Alpha' slider
   534   adj_alpha = gimp_scale_entry_new(GTK_TABLE(table),0,3,"_Noise scale :",SCALE_WIDTH,ENTRY_WIDTH,
   535                                    params.alpha,0.0,16.0,0.1,0.5, 1,true,0,0,0,0);
   536   g_signal_connect(adj_alpha,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.alpha);
   537   g_signal_connect_swapped(adj_alpha,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   539   // 'Sigma' slider
   540   adj_sigma = gimp_scale_entry_new(GTK_TABLE(table),0,4,"Geometry _regularity :",SCALE_WIDTH,ENTRY_WIDTH,
   541                                    params.sigma,0,8.0,0.1,0.5,2,true,0,0,0,0);
   542   g_signal_connect(adj_sigma,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.sigma);
   543   g_signal_connect_swapped(adj_sigma,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   545   // 'Spatial step' slider
   546   adj_dl = gimp_scale_entry_new(GTK_TABLE (table),0,5,"Spatial step :",SCALE_WIDTH,ENTRY_WIDTH,
   547                                 params.dl,0.1,1.0,0.01,0.1,2,true,0,0,0,0);
   548   g_signal_connect(adj_dl,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.dl);
   549   g_signal_connect_swapped(adj_dl,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   551   // 'Angular step' slider
   552   adj_da = gimp_scale_entry_new(GTK_TABLE(table),0,6,"Angu_lar step :",SCALE_WIDTH,ENTRY_WIDTH,
   553                                 params.da,1.0,90.0,1.0,10.0,1,true,0,0,0,0);
   554   g_signal_connect(adj_da,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.da);
   555   g_signal_connect_swapped(adj_da,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   557   // 'Interpolation' choice
   558   combo_interp = gimp_int_combo_box_new("Nearest neighbor",0,"Linear",1,"Runge-Kutta",2,NULL);
   559   gimp_int_combo_box_set_active(GIMP_INT_COMBO_BOX(combo_interp),params.interp);
   560   gimp_table_attach_aligned(GTK_TABLE(table),0,8,"Interpolation _type :",0.0,0.5,combo_interp,2,false);
   561   g_signal_connect(combo_interp,"changed",G_CALLBACK(gimp_int_combo_box_get_active),&params.interp);
   562   g_signal_connect_swapped(combo_interp,"changed",G_CALLBACK(gimp_preview_invalidate),preview);
   564   // 'Patch-based' button
   565   button_patch_based = gtk_check_button_new_with_mnemonic("_Patch-based");
   566   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_patch_based),params.patch_based);
   567   gimp_table_attach_aligned(GTK_TABLE(table),0,9,"Patch-based :",0.0,0.5,button_patch_based,2,false);
   568   g_signal_connect(button_patch_based,"toggled",G_CALLBACK(gimp_toggle_button_update),&params.patch_based);
   569   g_signal_connect_swapped(button_patch_based,"toggled",G_CALLBACK(gimp_preview_invalidate),preview);
   571   // 'Patch size' slider
   572   adj_patch_size = gimp_scale_entry_new(GTK_TABLE(table),0,10,"Patch size :",SCALE_WIDTH,ENTRY_WIDTH,
   573                                         params.patch_size,1.0,9.0,1.0,1.0,0,true,0,0,0,0);
   574   g_signal_connect(adj_patch_size,"value_changed",G_CALLBACK(gimp_int_adjustment_update),&params.patch_size);
   575   g_signal_connect_swapped(adj_patch_size,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   577   // 'Sigma_p' slider
   578   adj_sigma_p = gimp_scale_entry_new(GTK_TABLE(table),0,11,"_Sigma-p :",SCALE_WIDTH,ENTRY_WIDTH,
   579                                      params.sigma_p,0.0,30.0,0.1,0.5,1,true,0,0,0,0);
   580   g_signal_connect(adj_sigma_p,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.sigma_p);
   581   g_signal_connect_swapped(adj_sigma_p,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   583   // 'Sigma_s' slider
   584   adj_sigma_s = gimp_scale_entry_new(GTK_TABLE(table),0,12,"_Sigma-s :",SCALE_WIDTH,ENTRY_WIDTH,
   585                                      params.sigma_s,0.0,30.0,0.1,0.5,1,true,0,0,0,0);
   586   g_signal_connect(adj_sigma_s,"value_changed",G_CALLBACK(gimp_double_adjustment_update),&params.sigma_s);
   587   g_signal_connect_swapped(adj_sigma_s,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   589   // 'Lookup size' slider
   590   adj_lookup_size = gimp_scale_entry_new(GTK_TABLE(table),0,13,"Lookup size :",SCALE_WIDTH,ENTRY_WIDTH,
   591                                          params.lookup_size,1.0,40.0,1.0,1.0,0,true,0,0,0,0);
   592   g_signal_connect(adj_lookup_size,"value_changed",G_CALLBACK(gimp_int_adjustment_update),&params.lookup_size);
   593   g_signal_connect_swapped(adj_lookup_size,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   595   // 'Fast approximation' button
   596   button_fast_approx = gtk_check_button_new_with_mnemonic("_Enable");
   597   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_fast_approx),params.fast_approx);
   598   gimp_table_attach_aligned(GTK_TABLE(table),0,14,"Approximation :",0.0,0.5,button_fast_approx,2,false);
   599   g_signal_connect(button_fast_approx,"toggled",G_CALLBACK(gimp_toggle_button_update),&params.fast_approx);
   600   g_signal_connect_swapped(button_fast_approx,"toggled",G_CALLBACK(gimp_preview_invalidate),preview);
   602   // 'Channels' choice
   603   combo_channels = gimp_int_combo_box_new("All",0,"Chroma",1,"Luminance",2,NULL);
   604   gimp_int_combo_box_set_active(GIMP_INT_COMBO_BOX(combo_channels),params.channels);
   605   gimp_table_attach_aligned(GTK_TABLE(table),0,15,"Channels",0.0,0.5,combo_channels,2,false);
   606   g_signal_connect(combo_channels,"changed",G_CALLBACK(gimp_int_combo_box_get_active),&params.channels);
   607   g_signal_connect_swapped(combo_channels,"changed",G_CALLBACK(gimp_preview_invalidate),preview);
   608   if (drawable->bpp < 3) gtk_widget_set_sensitive(combo_channels, FALSE);
   610   // 'Number of iterations' slider
   611   adj_iterations = gimp_scale_entry_new(GTK_TABLE(table),0,16,"Number of _iterations :",SCALE_WIDTH,ENTRY_WIDTH,
   612                                         params.iterations,1.0,30.0,1.0,1.0,0,true,0,0,0,0);
   613   g_signal_connect(adj_iterations,"value_changed",G_CALLBACK(gimp_int_adjustment_update),&params.iterations);
   614   g_signal_connect_swapped(adj_iterations,"value_changed",G_CALLBACK(gimp_preview_invalidate),preview);
   616   // Show dialog window
   617   gtk_widget_show (dialog);
   618   gtk_main ();
   620   return runflag;
   621 }
   623 static void callback_response(GtkWidget *widget, gint response_id, gpointer data) {
   624   data = 0;
   625   switch (response_id) {
   626   case RESPONSE_RESET: // Reset parameters to default values & update window
   627     params = defaults_parameters;
   628     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_amplitude), params.amplitude);
   629     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_sharpness), params.sharpness);
   630     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_anisotropy), params.anisotropy);
   631     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_alpha), params.alpha);
   632     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_sigma), params.sigma);
   633     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_dl), params.dl);
   634     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_da), params.da);
   635     gtk_adjustment_set_value(GTK_ADJUSTMENT(adj_iterations), params.iterations);
   636     gimp_int_combo_box_set_active(GIMP_INT_COMBO_BOX(combo_channels), params.channels);
   637     gimp_int_combo_box_set_active(GIMP_INT_COMBO_BOX(combo_interp), params.interp);
   638     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_fast_approx), params.fast_approx);
   639     gimp_preview_invalidate((GimpPreview*)preview);
   640     break;
   641   case GTK_RESPONSE_OK:
   642     runflag = TRUE;
   643     gtk_widget_destroy (widget);
   644     break;
   645   default:
   646     gtk_widget_destroy (widget);
   647     break;
   648   }
   649 }