Changes to translatable messages
[gimp-plugins-ambulance:gimp-plugin-astronomy.git] / src / artificial_stars.c
1 /***************************************************************************
2  *   Copyright (C) 2006-2008 by Georg Hennig                               *
3  *   georg.hennig@web.de                                                   *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 /*
22 gimp artificial stars plug-in
23 (C) Georg Hennig <georg.hennig@web.de>
24 Creates an artificial star distribution (background stars, object stars -
25 distributed randomly, with a radial dependency, or as a globular
26 cluster, and foreground stars.
27 */
28
29 #include "config.h"
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <time.h>
35
36 #include <libgimp/gimp.h>
37 #include <libgimp/gimpui.h>
38 #include <gtk/gtk.h>
39
40 #include <gsl/gsl_math.h>
41 #include <gsl/gsl_rng.h>
42 #include <gsl/gsl_randist.h>
43
44 #include "artificial_stars_temperature.h"
45
46 #include "plugin-intl.h"
47
48 #define PLUG_IN_NAME "gimp-plugin-astro-artificial-stars"
49 #define PLUG_IN_VERSION "0.7"
50 #define PLUG_IN_DATE "09.2012"
51
52 enum PSF
53 {
54         PSF_DELTA_PEAK = 0,
55         PSF_GAUSS,
56         PSF_GAUSS_4_DIFFRACTIONS,
57         PSF_GAUSS_6_DIFFRACTIONS,
58         PSF_GAUSS_12_DIFFRACTIONS
59 };
60
61 enum DENSITY
62 {
63         DENSITY_RANDOM = 0,
64         DENSITY_GAUSS,
65         DENSITY_PLUMMER
66 };
67
68 /*
69 parameters
70 */
71 typedef struct
72 {
73         gint32 psf;
74         gdouble sigma_psf;
75         gdouble diffraction_percentage;
76         gdouble diffraction_angle;
77         gdouble diffraction_length;
78         gdouble diffraction_color;
79         gint32 noise;
80         gint32 background;
81         gdouble burnout;
82         gdouble shininess;
83
84         gboolean split_layers;
85         gboolean object_mask;
86
87         guint32 random_seed;
88         gboolean random_seed_bool;
89
90         gint32 background_stars;
91         gint32 object_stars;
92         gint32 foreground_stars;
93
94         gdouble background_brightness_mean;
95         gdouble object_brightness_mean;
96         gdouble foreground_brightness_mean;
97
98         gdouble background_brightness_sigma;
99         gdouble object_brightness_sigma;
100         gdouble foreground_brightness_sigma;
101
102         gint32 background_color_mean;
103         gint32 object_color_mean;
104         gint32 foreground_color_mean;
105
106         gint32 background_color_sigma;
107         gint32 object_color_sigma;
108         gint32 foreground_color_sigma;
109
110         gint32 object_x;
111         gint32 object_y;
112
113         gint32 object_density;
114         gint32 object_radius;
115
116         gboolean show_preview;
117 } tparameter;
118
119
120 static tparameter parameters =
121 {
122         PSF_GAUSS,
123         1.6,
124         0.5,
125         30.0,
126         1.0,
127         1.0,
128         20,
129         10,
130         0.5,
131         1.5,
132
133 /* split layers, object mask */
134         FALSE,
135         FALSE,
136
137 /* random seed */
138         0,
139         FALSE,
140
141 /* number */
142         1000,
143         500,
144         5,
145
146 /* brightness */
147         40,
148         90,
149         150,
150
151 /* brightness sigma */
152         30,
153         50,
154         100,
155
156 /* color */
157         7500,
158         7500,
159         7500,
160
161 /* color sigma */
162         1000,
163         1000,
164         1000,
165
166 /* x, y */
167         0,
168         0,
169
170 /* density, radius */
171         DENSITY_RANDOM,
172         20,
173
174         TRUE
175 };
176
177 /*
178 Prototypes
179 */
180 gint32 background_stars_number = 0;
181 gdouble *background_stars = NULL;
182 gint32 object_stars_number = 0;
183 gdouble *object_stars = NULL;
184 gint32 foreground_stars_number = 0;
185 gdouble *foreground_stars = NULL;
186 gint32 all_stars_number = 0;
187 gdouble *all_stars = NULL;
188
189 gdouble brightness_star_norm = 0.;
190 gdouble brightness_star_diffraction = 0.;
191
192 void star_new( gdouble **list, gint32 *list_number, const gint32 list_number_new );
193 void star_free( gdouble **list, gint32 *list_number );
194 void star_add( gdouble **list, const gint32 list_number, const gint32 list_position,
195         const gdouble x, const gdouble y, const gdouble brightness, const gdouble color );
196 void star_get( gdouble **list, const gint32 list_position,
197         gdouble *x, gdouble *y, gdouble *brightness, gdouble *color );
198
199 /*
200 communication to the GIMP
201 */
202 static void query( void );
203
204 static void run( const gchar *name, gint nparams, const GimpParam *param,
205         gint *nreturn_vals, GimpParam **return_vals );
206
207 /*
208 create stars
209 */
210 void create_star_distribution();
211 void create_background_star_distribution();
212 void create_object_star_distribution();
213 void create_foreground_star_distribution();
214
215 void find_star_norm();
216 void find_star_norm_sort();
217
218 void create_stars_psf( gdouble *star_distribution, gint32 x_start, gint32 y_start,
219         gint32 x_size, gint32 y_size, gdouble **list, const gint32 list_number, const gboolean show_progress );
220 void create_stars_noise( gdouble *star_distribution, gint32 x_size, gint32 y_size, const gboolean show_progress );
221
222 static void create_stars();
223
224 static void create_stars_selection( GimpPixelRgn *region_destination,
225         const gboolean draw_background_stars, const gboolean draw_object_stars, const gboolean draw_foreground_stars,
226         const gboolean show_progress );
227
228 static void recalculation_necessary();
229 static void recalculation_done();
230
231 /*
232 user interface
233 */
234 GtkWidget *preview;
235 GtkWidget *progress_bar;
236
237 GtkWidget *recalculate_button;
238 gboolean recalculating = FALSE;
239 gboolean cancel_recalculation = FALSE;
240
241 gboolean distribution_dirty = TRUE;
242 gboolean dialog_closed = FALSE;
243
244 GtkWidget *background_number_spin;
245 GtkWidget *background_brightness_spin, *background_brightness_sigma_spin;
246 GtkWidget *background_color_spin, *background_color_sigma_spin;
247
248 GtkWidget *object_number_spin;
249 GtkWidget *object_brightness_spin, *object_brightness_sigma_spin;
250 GtkWidget *object_color_spin, *object_color_sigma_spin;
251 GtkWidget *object_center_x_spin, *object_center_y_spin;
252 GtkWidget *object_density_combo;
253 GtkObject *object_radius_adj;
254
255 GtkWidget *foreground_number_spin;
256 GtkWidget *foreground_brightness_spin, *foreground_brightness_sigma_spin;
257 GtkWidget *foreground_color_spin, *foreground_color_sigma_spin;
258
259 void reporter( const gchar *string, const gdouble fraction );
260
261 static gint dialog();
262
263
264 /*
265 Variables
266 */
267
268 /*
269 PLUG_IN_INFO
270 */
271 GimpPlugInInfo PLUG_IN_INFO =
272 {
273         NULL, /* init_proc  */
274         NULL, /* quit_proc  */
275         query,/* query_proc */
276         run   /* run_proc   */
277 };
278
279 gint32 image_id;
280
281 /*
282 procedures
283 */
284 MAIN()
285
286 /*
287 communication to the GIMP
288 */
289 static void query( void )
290 {
291         static GimpParamDef params[] =
292         {
293                 { GIMP_PDB_INT32, "run_mode", "Interactive,non-interactive" },
294                 { GIMP_PDB_IMAGE, "image_id", "Input image" },
295                 { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" },
296                 { GIMP_PDB_INT32, "psf", "Point spread function (0,1,2,3,4)" },
297                 { GIMP_PDB_FLOAT, "sigma", "Sigma of psf gauss function [px]" },
298                 { GIMP_PDB_FLOAT, "diffraction_percentage", "Diffraction lines of % stars" },
299                 { GIMP_PDB_FLOAT, "diffraction_angle", "Angle of diffraction lines [deg]" },
300                 { GIMP_PDB_FLOAT, "diffraction_length", "Length of diffraction lines [a.u.]" },
301                 { GIMP_PDB_FLOAT, "diffraction_color", "Color interference of diffraction lines [a.u.]" },
302                 { GIMP_PDB_INT32, "noise", "Noise in % of sqrt(N)" },
303                 { GIMP_PDB_INT32, "background", "Background pixel value [absolute value]" },
304                 { GIMP_PDB_FLOAT, "burnout", "Burn out % stars" },
305                 { GIMP_PDB_FLOAT, "shininess", "Enlarge burnt out stars [a.u.]" },
306                 { GIMP_PDB_INT32, "split_layers", "Split background, object and foreground stars to layers" },
307                 { GIMP_PDB_INT32, "object_mask", "Create a mask using object stars" },
308                 { GIMP_PDB_INT32, "random_seed", "Seed number" },
309                 { GIMP_PDB_INT32, "random_seed_bool", "Use a random seed number" },
310                 { GIMP_PDB_INT32, "background_stars", "Number of background stars" },
311                 { GIMP_PDB_INT32, "object_stars", "Number of object stars" },
312                 { GIMP_PDB_INT32, "foreground_stars", "Number of foreground stars" },
313                 { GIMP_PDB_FLOAT, "background_brightness_mean", "Mean value of brightness of background stars [relative units]" },
314                 { GIMP_PDB_FLOAT, "object_brightness_mean", "Mean value of brightness of object stars [relative units]" },
315                 { GIMP_PDB_FLOAT, "foreground_brightness_mean", "Mean value of brightness of foreground stars [relative units]" },
316                 { GIMP_PDB_FLOAT, "background_brightness_sigma", "Sigma of brightness of background stars" },
317                 { GIMP_PDB_FLOAT, "object_brightness_sigma", "Sigma of brightness of object stars" },
318                 { GIMP_PDB_FLOAT, "foreground_brightness_sigma", "Sigma of brightness of foreground stars" },
319                 { GIMP_PDB_INT32, "background_color_mean", "Mean value of color of background stars [K]" },
320                 { GIMP_PDB_INT32, "object_color_mean", "Mean value of color of object stars [K]" },
321                 { GIMP_PDB_INT32, "foreground_color_mean", "Mean value of color of foreground stars [K]" },
322                 { GIMP_PDB_INT32, "background_color_sigma", "Sigma of color of background stars" },
323                 { GIMP_PDB_INT32, "object_color_sigma", "Sigma of color of object stars" },
324                 { GIMP_PDB_INT32, "foreground_color_sigma", "Sigma of color of foreground stars" },
325                 { GIMP_PDB_INT32, "object_x", "Center of object star distribution - x coordinate [px]" },
326                 { GIMP_PDB_INT32, "object_y", "Center of object star distribution - y coordinate [px]" },
327                 { GIMP_PDB_INT32, "object_density", "Object distribution (0,1,2)" },
328                 { GIMP_PDB_INT32, "object_radius", "Radius of object distribution" },
329                 { GIMP_PDB_INT32, "show_preview", "Show preview" }
330         };
331
332         /*  Initialize i18n support  */
333         bindtextdomain( GETTEXT_PACKAGE, gimp_locale_directory() );
334 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
335         bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
336 #endif
337         textdomain( GETTEXT_PACKAGE );
338
339         static GimpParamDef *return_vals  = NULL;
340         static int nparams = sizeof( params )/sizeof( params[0] );
341         static int nreturn_vals = 0;
342
343         gimp_install_procedure(PLUG_IN_NAME,
344                 _("Create an artificial star distribution"),
345                 _("This plug-in creates an artificial star distribution. "),
346                 "Georg Hennig <georg.hennig@web.de>",
347                 "Georg Hennig <georg.hennig@web.de>",
348                 "2008, 2012",
349                 _("Artificial Stars"),
350                 "RGB*",
351                 GIMP_PLUGIN,
352                 nparams,
353                 nreturn_vals,
354                 params,
355                 return_vals );
356
357         gimp_plugin_menu_register(PLUG_IN_NAME, _("<Image>/Filters/Astronomy") );
358 }
359
360 static void run( const gchar *name, gint nparams, const GimpParam  *param,
361         gint *nreturn_vals, GimpParam **return_vals )
362 {
363         static GimpParam values[1];
364         GimpPDBStatusType status;
365         GimpRunMode run_mode;
366
367         status = GIMP_PDB_SUCCESS;
368         run_mode = param[0].data.d_int32;
369         *nreturn_vals = 1;
370         *return_vals = values;
371
372         /*  Initialize i18n support  */
373         bindtextdomain( GETTEXT_PACKAGE, gimp_locale_directory() );
374 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
375         bind_textdomain_codeset( GETTEXT_PACKAGE, "UTF-8" );
376 #endif
377         textdomain( GETTEXT_PACKAGE );
378
379         values[0].type = GIMP_PDB_STATUS;
380         values[0].data.d_status = status;
381
382         image_id = param[1].data.d_image;
383
384         switch( run_mode )
385         {
386                 case GIMP_RUN_INTERACTIVE:
387                         gimp_get_data( PLUG_IN_NAME, &parameters );
388
389                         if ( !dialog( param[1].data.d_image, gimp_drawable_get( param[2].data.d_drawable ) ) )
390                         {
391                                 return;
392                         }
393
394                         gimp_set_data( PLUG_IN_NAME, &parameters, sizeof( tparameter ) );
395                         break;
396                 case GIMP_RUN_NONINTERACTIVE:
397                         if ( nparams != 37 )
398                         {
399                                 status = GIMP_PDB_CALLING_ERROR;
400                         }
401                         else
402                         {
403                                 image_id = param[1].data.d_image;
404
405                                 parameters.psf = param[3].data.d_int32;
406                                 parameters.sigma_psf = param[4].data.d_float;
407                                 parameters.diffraction_percentage = param[5].data.d_float;
408                                 parameters.diffraction_angle = param[6].data.d_float;
409                                 parameters.diffraction_length = param[7].data.d_float;
410                                 parameters.diffraction_color = param[8].data.d_float;
411                                 parameters.noise = param[9].data.d_int32;
412                                 parameters.background = param[10].data.d_int32;
413                                 parameters.burnout = param[11].data.d_float;
414                                 parameters.shininess = param[12].data.d_float;
415                                 parameters.split_layers = param[13].data.d_int32;
416                                 parameters.object_mask = param[14].data.d_int32;
417                                 parameters.random_seed = param[15].data.d_int32;
418                                 parameters.random_seed_bool = param[16].data.d_int32;
419                                 parameters.background_stars = param[17].data.d_int32;
420                                 parameters.object_stars = param[18].data.d_int32;
421                                 parameters.foreground_stars = param[19].data.d_int32;
422                                 parameters.background_brightness_mean = param[20].data.d_float;
423                                 parameters.object_brightness_mean = param[21].data.d_float;
424                                 parameters.foreground_brightness_mean = param[22].data.d_float;
425                                 parameters.background_brightness_sigma = param[23].data.d_float;
426                                 parameters.object_brightness_sigma = param[24].data.d_float;
427                                 parameters.foreground_brightness_sigma = param[25].data.d_float;
428                                 parameters.background_color_mean = param[26].data.d_int32;
429                                 parameters.object_color_mean = param[27].data.d_int32;
430                                 parameters.foreground_color_mean = param[28].data.d_int32;
431                                 parameters.background_color_sigma = param[29].data.d_int32;
432                                 parameters.object_color_sigma = param[30].data.d_int32;
433                                 parameters.foreground_color_sigma = param[31].data.d_int32;
434                                 parameters.object_x = param[32].data.d_int32;
435                                 parameters.object_y = param[33].data.d_int32;
436                                 parameters.object_density = param[34].data.d_int32;
437                                 parameters.object_radius = param[35].data.d_int32;
438                                 parameters.show_preview = param[36].data.d_int32;
439                         }
440                         break;
441                 case GIMP_RUN_WITH_LAST_VALS:
442                         gimp_get_data( PLUG_IN_NAME, &parameters );
443                         image_id = param[1].data.d_image;
444
445                         break;
446                 default:
447                         status = GIMP_PDB_CALLING_ERROR;
448                         break;
449         }
450
451         if( status == GIMP_PDB_SUCCESS )
452         {
453                 dialog_closed = TRUE;
454                 if ( distribution_dirty )
455                 {
456
457                         GtkWidget *message_dialog = gtk_message_dialog_new( NULL,
458                                 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
459                                 _( "Do you want to recalculate the star distribution before actually drawing the stars?" ) );
460                         gint response = gtk_dialog_run( GTK_DIALOG( message_dialog ) );
461                         gtk_widget_destroy( message_dialog );
462
463                         if ( response == GTK_RESPONSE_YES ) create_star_distribution();
464                 }
465                 create_stars();
466         }
467
468         values[0].data.d_status = status;
469 }
470
471 void star_new( gdouble **list, gint32 *list_number, const gint32 list_number_new )
472 {
473         *list = malloc( list_number_new * sizeof(gdouble) * 4 );
474
475         *list_number = list_number_new;
476 }
477
478 void star_free( gdouble **list, gint32 *list_number )
479 {
480         if ( !*list ) return;
481
482         if ( *list_number == 0 ) return;
483
484         free( *list );
485         *list = NULL;
486         *list_number = 0;
487 }
488
489 void star_add( gdouble **list, const gint32 list_number, const gint32 list_position,
490         const gdouble x, const gdouble y, const gdouble brightness, const gdouble color )
491 {
492         if ( list_position >= list_number ) return;
493
494         (*list)[list_position*4+0] = x;
495         (*list)[list_position*4+1] = y;
496         (*list)[list_position*4+2] = brightness;
497         (*list)[list_position*4+3] = color;
498 }
499
500 void star_get( gdouble **list, const gint32 list_position,
501         gdouble *x, gdouble *y, gdouble *brightness, gdouble *color )
502 {
503         if ( x ) *x = (*list)[list_position*4+0];
504         if ( y ) *y = (*list)[list_position*4+1];
505         if ( brightness ) *brightness = (*list)[list_position*4+2];
506         if ( color ) *color = (*list)[list_position*4+3];
507 }
508
509 inline gdouble gauss( const gdouble x, const gdouble y, const gdouble A, const gdouble x0, const gdouble y0,
510         const gdouble sigma_x, const gdouble sigma_y )
511 {
512         /* z = A * exp(-0.5*(x-x0)^2/sigma_x^2) * exp(-0.5*(y-y0)^2/sigma_y^2) + b */
513         return A * exp( -0.5*(x-x0)*(x-x0)/(sigma_x*sigma_x) ) * exp( -0.5*(y-y0)*(y-y0)/(sigma_y*sigma_y) );
514 }
515
516 void create_star_distribution()
517 {
518         star_free( &background_stars, &background_stars_number );
519         star_free( &object_stars, &object_stars_number );
520         star_free( &foreground_stars, &foreground_stars_number );
521
522         star_new( &background_stars, &background_stars_number, parameters.background_stars );
523         star_new( &object_stars, &object_stars_number, parameters.object_stars );
524         star_new( &foreground_stars, &foreground_stars_number, parameters.foreground_stars );
525
526         if ( !cancel_recalculation )
527         {
528                 reporter( _("Creating background star distribution"), 0. );
529                 create_background_star_distribution();
530         }
531
532         if ( !cancel_recalculation )
533         {
534                 reporter( _("Creating object star distribution"), 0. );
535                 create_object_star_distribution();
536         }
537
538         if ( !cancel_recalculation )
539         {
540                 reporter( _("Creating foreground star distribution"), 0. );
541                 create_foreground_star_distribution();
542         }
543
544         if ( !cancel_recalculation )
545         {
546                 find_star_norm_sort();
547
548                 recalculation_done();
549
550                 recalculating = FALSE;
551                 cancel_recalculation = TRUE;
552                 gtk_button_set_label( GTK_BUTTON( recalculate_button ), _("Recalculate distribution") );
553                 gimp_preview_invalidate( GIMP_PREVIEW( preview ) );
554         }
555
556         reporter( "", 0. );
557 }
558
559 int comp( const void *ptr1, const void *ptr2 )
560 {
561         const gdouble *p_1 = (gdouble*)ptr1;
562         const gdouble *p_2 = (gdouble*)ptr2;
563
564         if ( ( p_2[2] - p_1[2] ) > 0. ) return 1;
565         if ( ( p_2[2] - p_1[2] ) < 0. ) return -1;
566         return 0;
567 }
568
569 void find_star_norm_sort()
570 {
571         reporter( _("Sorting stars by brightness"), 0. );
572
573         star_free( &all_stars, &all_stars_number );
574
575         /* Determine the normalize value */
576         star_new( &all_stars, &all_stars_number, background_stars_number + object_stars_number + foreground_stars_number );
577         if ( all_stars_number == 0 ) return;
578
579         gdouble x, y, brightness, color;
580
581         gint32 i;
582         for ( i=0; i<background_stars_number; i++ )
583         {
584                 star_get( &background_stars, i, &x, &y, &brightness, &color );
585
586                 star_add( &all_stars, all_stars_number, i, x, y, brightness, color );
587         }
588         for ( i=0; i<object_stars_number; i++ )
589         {
590                 star_get( &object_stars, i, &x, &y, &brightness, &color );
591
592                 star_add( &all_stars, all_stars_number, i+background_stars_number, x, y, brightness, color );
593         }
594         for ( i=0; i<foreground_stars_number; i++ )
595         {
596                 star_get( &foreground_stars, i, &x, &y, &brightness, &color );
597
598                 star_add( &all_stars, all_stars_number, i+background_stars_number+object_stars_number, x, y, brightness, color );
599         }
600
601         qsort( all_stars, all_stars_number, 4 * sizeof( gdouble ), comp );
602
603         find_star_norm();
604
605         reporter( "", 0. );
606 }
607
608 void find_star_norm()
609 {
610         if ( all_stars_number == 0 ) return;
611
612         gdouble brightness;
613
614         star_get( &all_stars, (gint32)((parameters.burnout*all_stars_number)/100),
615                 NULL, NULL, &brightness, NULL );
616
617         brightness_star_norm = brightness;
618
619         star_get( &all_stars, (gint32)((parameters.diffraction_percentage*all_stars_number)/100),
620                 NULL, NULL, &brightness, NULL );
621
622         brightness_star_diffraction = brightness;
623 }
624
625 void create_background_star_distribution()
626 {
627         const gsl_rng_type *T;
628         gsl_rng *r;
629
630         gsl_rng_env_setup();
631
632         T = gsl_rng_default;
633         r = gsl_rng_alloc( T );
634
635         gsl_rng_set( r, parameters.random_seed/*time( NULL )*/ );
636
637         gdouble x, y, brightness, color;
638
639         gint i;
640         for ( i=0; i<parameters.background_stars; i++ )
641         {
642                 if ( cancel_recalculation ) break;
643
644                 x = gimp_image_width( image_id )*gsl_rng_uniform( r );
645                 y = gimp_image_height( image_id )*gsl_rng_uniform( r );
646
647                 brightness = parameters.background_brightness_mean + gsl_ran_gaussian( r, parameters.background_brightness_sigma );
648                 color = parameters.background_color_mean + gsl_ran_gaussian( r, parameters.background_color_sigma );
649
650                 star_add( &background_stars, background_stars_number, i, x, y, brightness, color );
651
652                 if ( i%(1+parameters.background_stars/100) ) reporter( "", (gdouble)(i+1)/parameters.background_stars );
653         }
654
655         gsl_rng_free( r );
656 }
657
658 void create_object_star_distribution()
659 {
660         const gsl_rng_type *T;
661         gsl_rng *r;
662
663         gsl_rng_env_setup();
664
665         T = gsl_rng_default;
666         r = gsl_rng_alloc( T );
667
668         gsl_rng_set( r, parameters.random_seed+10/*time( NULL )*/ );
669
670         gdouble x, y, brightness, color;
671         gdouble radius, angle1, angle2;
672
673         gint i;
674
675         switch( parameters.object_density )
676         {
677                 case DENSITY_RANDOM:
678                 {
679                         for ( i=0; i<parameters.object_stars; i++ )
680                         {
681                                 if ( cancel_recalculation ) break;
682
683                                 x = gimp_image_width( image_id )*gsl_rng_uniform( r );
684                                 y = gimp_image_height( image_id )*gsl_rng_uniform( r );
685
686                                 brightness = -1.;
687                                 while ( brightness < 0. ) brightness = parameters.object_brightness_mean + gsl_ran_gaussian( r, parameters.object_brightness_sigma );
688                                 color = parameters.object_color_mean + gsl_ran_gaussian( r, parameters.object_color_sigma );
689
690                                 star_add( &object_stars, object_stars_number, i, x, y, brightness, color );
691
692                                 if ( i%(1+parameters.object_stars/100) ) reporter( "", (gdouble)(i+1)/parameters.object_stars );
693                         }
694
695                         break;
696                 }
697                 case DENSITY_GAUSS:
698                 {
699                         for ( i=0; i<parameters.object_stars; i++ )
700                         {
701                                 if ( cancel_recalculation ) break;
702
703                                 radius = abs( gsl_ran_gaussian( r, parameters.object_radius * GSL_MIN( gimp_image_width( image_id ), gimp_image_height( image_id ) / 100 ) ) );
704                                 angle1 = gsl_rng_uniform( r ) * 2 * M_PI;
705
706                                 x = parameters.object_x + radius * cos( angle1 );
707                                 y = parameters.object_y + radius * sin( angle1 );
708
709                                 brightness = -1.;
710                                 while ( brightness < 0. ) brightness = parameters.object_brightness_mean + gsl_ran_gaussian( r, parameters.object_brightness_sigma );
711                                 color = parameters.object_color_mean + gsl_ran_gaussian( r, parameters.object_color_sigma );
712
713                                 star_add( &object_stars, object_stars_number, i, x, y, brightness, color );
714
715                                 if ( i%(1+parameters.object_stars/100) ) reporter( "", (gdouble)(i+1)/parameters.object_stars );
716                         }
717
718                         break;
719                 }
720                 case DENSITY_PLUMMER:
721                 {
722                         for ( i=0; i<parameters.object_stars; i++ )
723                         {
724                                 if ( cancel_recalculation ) break;
725
726                                 do
727                                 {
728                                         /* 20: arbitrary radius, where P(random*radius)->0, here P(random*radius)<0.1% */
729                                         radius = gsl_rng_uniform( r ) * 20;
730                                 }
731                                 while ( 5.38 * radius * radius / pow( 1. + radius * radius, 2.5 ) < gsl_rng_uniform( r ) );
732
733                                 angle1 = gsl_rng_uniform( r ) * 2 * M_PI;
734
735                                 do
736                                 {
737                                         angle2 = gsl_rng_uniform( r ) * M_PI;
738                                 }
739                                 while ( sin( angle2 ) <= gsl_rng_uniform( r ) );
740
741                                 x = parameters.object_x + radius * ( (gdouble)( parameters.object_radius * GSL_MIN( gimp_image_width( image_id ), gimp_image_height( image_id ) ) ) / ( 100 * 20 ) ) * sin( angle2 ) * cos( angle1 ) ;
742                                 y = parameters.object_y + radius * ( (gdouble)( parameters.object_radius * GSL_MIN( gimp_image_width( image_id ), gimp_image_height( image_id ) ) ) / ( 100 * 20 ) ) * sin( angle2 ) * sin( angle1 );
743
744                                 brightness = -1.;
745                                 while ( brightness < 0. ) brightness = parameters.object_brightness_mean + gsl_ran_gaussian( r, parameters.object_brightness_sigma );
746                                 color = parameters.object_color_mean + gsl_ran_gaussian( r, parameters.object_color_sigma );
747
748                                 star_add( &object_stars, object_stars_number, i, x, y, brightness, color );
749
750                                 if ( i%(1+parameters.object_stars/100) ) reporter( "", (gdouble)(i+1)/parameters.object_stars );
751                         }
752
753                         break;
754                 }
755                 default:
756                         break;
757         }
758
759         gsl_rng_free( r );
760 }
761
762 void create_foreground_star_distribution()
763 {
764         const gsl_rng_type *T;
765         gsl_rng *r;
766
767         gsl_rng_env_setup();
768
769         T = gsl_rng_default;
770         r = gsl_rng_alloc( T );
771
772         gsl_rng_set( r, parameters.random_seed+20/*time( NULL )*/ );
773
774         gdouble x, y, brightness, color;
775
776         gint i;
777         for ( i=0; i<parameters.foreground_stars; i++ )
778         {
779                 if ( cancel_recalculation ) break;
780
781                 x = gimp_image_width( image_id )*gsl_rng_uniform( r );
782                 y = gimp_image_height( image_id )*gsl_rng_uniform( r );
783
784                 brightness = parameters.foreground_brightness_mean + gsl_ran_gaussian( r, parameters.foreground_brightness_sigma );
785                 color = parameters.foreground_color_mean + gsl_ran_gaussian( r, parameters.foreground_color_sigma );
786
787                 star_add( &foreground_stars, foreground_stars_number, i, x, y, brightness, color );
788
789                 if ( i%(1+parameters.foreground_stars/100) ) reporter( "", (gdouble)(i+1)/parameters.foreground_stars );
790         }
791
792         gsl_rng_free( r );
793 }
794
795 void create_stars_psf( gdouble *star_distribution, gint32 x_start, gint32 y_start,
796         gint32 x_size, gint32 y_size, gdouble **list, const gint32 list_number, const gboolean show_progress )
797 {
798         gdouble x, y;
799         gdouble brightness, color;
800         gdouble r, g, b;
801
802         gint32 i, x_it, y_it;
803
804         if ( parameters.psf == PSF_DELTA_PEAK )
805         {
806                 for ( i=0; i<list_number; i++ )
807                 {
808                         star_get( list, i, &x, &y, &brightness, &color );
809
810                         if ( (gint32)x >= x_start &&
811                                 (gint32)y >= y_start &&
812                                 (gint32)x < x_start+x_size &&
813                                 (gint32)y < y_start+y_size )
814                         {
815                                 temperature_to_rgb_relative( color, &r, &g, &b );
816
817                                 star_distribution[3*((gint32)(y-y_start)*x_size+(gint32)(x-x_start))+0] =
818                                         GSL_MAX(
819                                                 brightness * r,
820                                                 star_distribution[3*((gint32)(y-y_start)*x_size+(gint32)(x-x_start))+0]
821                                         );
822
823                                 star_distribution[3*((gint32)(y-y_start)*x_size+(gint32)(x-x_start))+1] =
824                                         GSL_MAX(
825                                                 brightness * g,
826                                                 star_distribution[3*((gint32)(y-y_start)*x_size+(gint32)(x-x_start))+1]
827                                         );
828
829                                 star_distribution[3*((gint32)(y-y_start)*x_size+(gint32)(x-x_start))+2] =
830                                         GSL_MAX(
831                                                 brightness * b,
832                                                 star_distribution[3*((gint32)(y-y_start)*x_size+(gint32)(x-x_start))+2]
833                                         );
834                         }
835
836                         if ( show_progress && i % (1+list_number/100) ) gimp_progress_update( (gdouble)(i) / list_number );
837                 }
838         }
839         else if ( parameters.psf == PSF_GAUSS || parameters.psf == PSF_GAUSS_4_DIFFRACTIONS ||
840                 parameters.psf == PSF_GAUSS_6_DIFFRACTIONS || parameters.psf == PSF_GAUSS_12_DIFFRACTIONS )
841         {
842                 gdouble draw_width;
843                 gdouble sigma_new;
844                 gdouble brightness_new;
845
846                 for ( i=0; i<list_number; i++ )
847                 {
848                         star_get( list, i, &x, &y, &brightness, &color );
849                         temperature_to_rgb_relative( color, &r, &g, &b );
850
851                         sigma_new = parameters.sigma_psf;
852                         brightness_new = brightness;
853                         if ( brightness - brightness_star_norm > 0. )
854                         {
855                                 sigma_new += 2 * sigma_new * parameters.shininess * ( brightness - brightness_star_norm ) / brightness_star_norm;
856                                 brightness_new -= brightness_new * 16 * pow( parameters.shininess, 0.2 ) * ( brightness - brightness_star_norm ) / ( brightness_star_norm * brightness_star_norm );
857                         }
858                         draw_width = 4*sigma_new;
859
860                         if ( (gint32)(x+draw_width) >= x_start &&
861                                 (gint32)(y+draw_width) >= y_start &&
862                                 (gint32)(x-draw_width) < x_start+x_size &&
863                                 (gint32)(y-draw_width) < y_start+y_size )
864                         {
865                                 for ( x_it=(gint32)(x-draw_width); x_it<=(gint32)(x+draw_width); x_it++ )
866                                 {
867                                         for ( y_it=(gint32)(y-draw_width); y_it<=(gint32)(y+draw_width); y_it++ )
868                                         {
869                                                 if ( x_it >= x_start &&
870                                                         y_it >= y_start &&
871                                                         x_it < x_start+x_size &&
872                                                         y_it < y_start+y_size )
873                                                 {
874                                                         star_distribution[3*((y_it-y_start)*x_size+(x_it-x_start))+0] =
875                                                                 GSL_MAX(
876                                                                         r * gauss( x_it, y_it, brightness, x, y, sigma_new, sigma_new ),
877                                                                         star_distribution[3*((y_it-y_start)*x_size+(x_it-x_start))+0]
878                                                                 );
879
880                                                         star_distribution[3*((y_it-y_start)*x_size+(x_it-x_start))+1] =
881                                                                 GSL_MAX(
882                                                                         g * gauss( x_it, y_it, brightness, x, y, sigma_new, sigma_new ),
883                                                                         star_distribution[3*((y_it-y_start)*x_size+(x_it-x_start))+1]
884                                                                 );
885
886                                                         star_distribution[3*((y_it-y_start)*x_size+(x_it-x_start))+2] =
887                                                                 GSL_MAX(
888                                                                         b * gauss( x_it, y_it, brightness, x, y, sigma_new, sigma_new ),
889                                                                         star_distribution[3*((y_it-y_start)*x_size+(x_it-x_start))+2]
890                                                                 );
891                                                 }
892                                         }
893                                 }
894                         }
895
896                         if ( parameters.psf == PSF_GAUSS_4_DIFFRACTIONS ||
897                                 parameters.psf == PSF_GAUSS_6_DIFFRACTIONS ||
898                                 parameters.psf == PSF_GAUSS_12_DIFFRACTIONS )
899                         {
900
901                                 gint32 radius_it, angle_it, offset;
902                                 gdouble x_pos, y_pos, radius, x_offset, y_offset;
903                                 gdouble brightness_new_new;
904                                 gdouble radius_half;
905
906                                 const gint32 oversample = 5;
907
908                                 gdouble angle_start = M_PI*parameters.diffraction_angle/180;
909
910                                 const gint32 number_of_diffractions = ( parameters.psf == PSF_GAUSS_4_DIFFRACTIONS ) ? 4 :
911                                         ( parameters.psf == PSF_GAUSS_6_DIFFRACTIONS ) ? 6 : 12;
912                                 const gdouble multiplier = ( parameters.psf == PSF_GAUSS_4_DIFFRACTIONS ) ? 1. :
913                                         ( parameters.psf == PSF_GAUSS_6_DIFFRACTIONS ) ? 0.6 : 0.3;
914
915
916                                 if ( brightness - brightness_star_diffraction > 0. )
917                                 {
918                                         radius_half = -1.;
919
920                                         for ( radius_it=1; radius_it<multiplier*parameters.diffraction_length*oversample*24*sigma_new; radius_it++ )
921                                         {
922                                                 for ( angle_it=0; angle_it<number_of_diffractions; angle_it++ )
923                                                 {
924                                                         for ( offset=floor(-sigma_new*oversample); offset<=ceil(sigma_new*oversample); offset++ )
925                                                         {
926                                                                 x_pos = radius_it*cos(angle_it*2.*M_PI/number_of_diffractions+angle_start)/oversample;
927                                                                 y_pos = radius_it*sin(angle_it*2.*M_PI/number_of_diffractions+angle_start)/oversample;
928
929                                                                 x_offset = offset*cos(angle_it*2.*M_PI/number_of_diffractions+angle_start-M_PI/2)/oversample;
930                                                                 y_offset = offset*sin(angle_it*2.*M_PI/number_of_diffractions+angle_start-M_PI/2)/oversample;
931
932                                                                 if ( (gint32)((x_pos+x_offset)+x) >= x_start &&
933                                                                         (gint32)((y_pos+y_offset)+y) >= y_start &&
934                                                                         (gint32)((x_pos+x_offset)+x) < x_start+x_size &&
935                                                                         (gint32)((y_pos+y_offset)+y) < y_start+y_size )
936                                                                 {
937
938 /*
939 gnuplot> param=1.0
940 gnuplot> half=130
941 gnuplot> plot [1:600][0:255] "artificial_star_spike" using 1:2 smooth csplines, "artificial_star_spike" using 1:3 smooth csplines, "artificial_star_spike" using 1:4 smooth csplines, (450./sqrt(param))*exp(-x/(3*27./sqrt(param)))+28, (450./sqrt(param))*exp(-x/(3*27./sqrt(param)))+0.5*(1./sqrt(param))*27*half*(450./sqrt(param))*sin(1.3*sqrt(param)*(x-half)/27+pi)/((x+1)**2)+28
942 */
943
944                                                                         radius = sqrt( (x_pos+x_offset)*(x_pos+x_offset) + (y_pos+y_offset)*(y_pos+y_offset) );
945
946                                                                         brightness_new_new = CLAMP(r*(brightness/sqrt(1./r))*exp(-radius/(multiplier*3*parameters.diffraction_length*sigma_new/sqrt(1./r))),0.,r*brightness_star_norm);
947
948                                                                         if ( brightness_new_new < 0.5*brightness_star_norm )
949                                                                         {
950                                                                                 if ( radius_half < 0. ) radius_half = radius;
951
952                                                                                 brightness_new_new +=
953                                                                                         0.5*(1.-exp(-radius/(8*sigma_new)))*parameters.diffraction_color*brightness_new_new*sin(0.25*(radius-radius_half)/parameters.sigma_psf+1.0*M_PI);
954                                                                         }
955
956                                                                         brightness_new_new *=
957                                                                                 0.6*exp(-0.5*((gdouble)(offset*offset)/(oversample*oversample))/(0.1*parameters.sigma_psf*parameters.sigma_psf)) + 
958                                                                                 0.4*exp((fabs(offset)/(10*oversample))/(4*parameters.sigma_psf*parameters.sigma_psf))*
959                                                                                 exp(-0.5*((gdouble)(offset*offset)/(oversample*oversample))/(parameters.sigma_psf*parameters.sigma_psf));
960
961                                                                         star_distribution[3*((gint32)((y_pos+y_offset)+y-y_start)*x_size+(gint32)((x_pos+x_offset)+x-x_start))+0] =
962                                                                                 GSL_MAX(
963                                                                                         brightness_new_new,
964                                                                                         star_distribution[3*((gint32)((y_pos+y_offset)+y-y_start)*x_size+(gint32)((x_pos+x_offset)+x-x_start))+0]
965                                                                                 );
966
967                                                                         brightness_new_new = CLAMP(g*(brightness/sqrt(1./g))*exp(-radius/(multiplier*3*parameters.diffraction_length*sigma_new/sqrt(1./g))),0.,g*brightness_star_norm);
968
969                                                                         if ( brightness_new_new < 0.5*brightness_star_norm )
970                                                                         {
971                                                                                 if ( radius_half < 0. ) radius_half = radius;
972
973                                                                                 brightness_new_new += 
974                                                                                         0.5*(1.-exp(-radius/(8*sigma_new)))*parameters.diffraction_color*brightness_new_new*sin(0.25*(radius-radius_half)/parameters.sigma_psf+1.5*M_PI);
975                                                                         }
976
977                                                                         brightness_new_new *=
978                                                                                 0.6*exp(-0.5*((gdouble)(offset*offset)/(oversample*oversample))/(0.1*parameters.sigma_psf*parameters.sigma_psf)) + 
979                                                                                 0.4*exp((fabs(offset)/(10*oversample))/(4*parameters.sigma_psf*parameters.sigma_psf))*
980                                                                                 exp(-0.5*((gdouble)(offset*offset)/(oversample*oversample))/(parameters.sigma_psf*parameters.sigma_psf));
981
982                                                                         star_distribution[3*((gint32)((y_pos+y_offset)+y-y_start)*x_size+(gint32)((x_pos+x_offset)+x-x_start))+1] =
983                                                                                 GSL_MAX(
984                                                                                         brightness_new_new,
985                                                                                         star_distribution[3*((gint32)((y_pos+y_offset)+y-y_start)*x_size+(gint32)((x_pos+x_offset)+x-x_start))+1]
986                                                                                 );
987
988                                                                         brightness_new_new = CLAMP(b*(brightness/sqrt(1./b))*exp(-radius/(multiplier*3*parameters.diffraction_length*sigma_new/sqrt(1./b))),0.,b*brightness_star_norm);
989
990                                                                         if ( brightness_new_new < 0.5*brightness_star_norm )
991                                                                         {
992                                                                                 if ( radius_half < 0. ) radius_half = radius;
993
994                                                                                         brightness_new_new +=
995                                                                                                 0.5*(1.-exp(-radius/(8*sigma_new)))*parameters.diffraction_color*brightness_new_new*sin(0.25*(radius-radius_half)/parameters.sigma_psf+2.0*M_PI);
996                                                                         }
997
998                                                                         brightness_new_new *=
999                                                                                 0.6*exp(-0.5*((gdouble)(offset*offset)/(oversample*oversample))/(0.1*parameters.sigma_psf*parameters.sigma_psf)) + 
1000                                                                                 0.4*exp((fabs(offset)/(10*oversample))/(4*parameters.sigma_psf*parameters.sigma_psf))*
1001                                                                                 exp(-0.5*((gdouble)(offset*offset)/(oversample*oversample))/(parameters.sigma_psf*parameters.sigma_psf));
1002
1003                                                                         star_distribution[3*((gint32)((y_pos+y_offset)+y-y_start)*x_size+(gint32)((x_pos+x_offset)+x-x_start))+2] =
1004                                                                                 GSL_MAX(
1005                                                                                         brightness_new_new,
1006                                                                                         star_distribution[3*((gint32)((y_pos+y_offset)+y-y_start)*x_size+(gint32)((x_pos+x_offset)+x-x_start))+2]
1007                                                                                 );
1008                                                                 }
1009                                                         }
1010                                                 }
1011                                         }
1012                                 }
1013                         }
1014
1015                         if ( show_progress && i % (1+list_number/100) ) gimp_progress_update( (gdouble)(i) / list_number );
1016                 }
1017         }
1018 }
1019
1020 void create_stars_noise( gdouble *star_distribution, gint32 x_size, gint32 y_size, const gboolean show_progress )
1021 {
1022         const gsl_rng_type *T;
1023         gsl_rng *r;
1024
1025         gsl_rng_env_setup();
1026
1027         T = gsl_rng_default;
1028         r = gsl_rng_alloc( T );
1029
1030         gsl_rng_set( r, parameters.random_seed+30/*time( NULL )*/ );
1031
1032         gint32 i;
1033         for ( i=0; i<3*x_size*y_size; i++ )
1034         {
1035                 if ( 255*star_distribution[i]/brightness_star_norm < 255 )
1036                         star_distribution[i] += gsl_ran_gaussian( r, parameters.noise*sqrt(star_distribution[i])/100 );
1037
1038                 if ( show_progress && i % (1+3*x_size*y_size/100) )
1039                         gimp_progress_update( (gdouble)(i) / 3*x_size*y_size );
1040         }
1041
1042         gsl_rng_free( r );
1043 }
1044
1045 /*
1046 Create stars into destination
1047 */
1048 static void create_stars_selection( GimpPixelRgn *region_destination,
1049         const gboolean draw_background_stars, const gboolean draw_object_stars, const gboolean draw_foreground_stars,
1050         const gboolean show_progress )
1051 {
1052         gint32 x, y;
1053         gint32 i;
1054
1055         /* create the stars before actually drawing them */
1056         gdouble *star_distribution;
1057         star_distribution = g_malloc( sizeof(gdouble)*3*region_destination->w*region_destination->h );
1058
1059         reporter( "artificial_stars: Creating background...", -1.0 );
1060         if ( show_progress ) gimp_progress_init( _("Creating background...") );
1061         /* Background first */
1062         if ( draw_background_stars )
1063         {
1064                 for ( i=0; i<3*region_destination->w*region_destination->h; i++ )
1065                 {
1066                         star_distribution[i] = (gdouble)parameters.background * brightness_star_norm / 255;
1067
1068                         if ( show_progress && i % (1+3*region_destination->w*region_destination->h/100) )
1069                                 gimp_progress_update( (gdouble)(i) / 3*region_destination->w*region_destination->h );
1070                 }
1071         }
1072         else
1073         {
1074                 for( i=0; i<3*region_destination->w*region_destination->h; i++ )
1075                 {
1076                         star_distribution[i] = 0.;
1077
1078                         if ( show_progress && i % (1+3*region_destination->w*region_destination->h/100) )
1079                                 gimp_progress_update( (gdouble)(i) / 3*region_destination->w*region_destination->h );
1080                 }
1081         }
1082
1083         /* Background stars */
1084         if ( draw_background_stars )
1085         {
1086                 reporter( "artificial_stars: Creating background stars...", -1.0 );
1087                 if ( show_progress ) gimp_progress_init( _("Creating background stars...") );
1088
1089                 create_stars_psf( star_distribution, region_destination->x, region_destination->y,
1090                         region_destination->w, region_destination->h, &background_stars, background_stars_number, show_progress );
1091         }
1092
1093         /* Object stars */
1094         if ( draw_object_stars )
1095         {
1096                 reporter( "artificial_stars: Creating object stars...", -1.0 );
1097                 if ( show_progress ) gimp_progress_init( _("Creating object stars...") );
1098
1099                 create_stars_psf( star_distribution, region_destination->x, region_destination->y,
1100                         region_destination->w, region_destination->h, &object_stars, object_stars_number, show_progress );
1101         }
1102
1103         /* Foreground stars */
1104         if ( draw_foreground_stars )
1105         {
1106                 reporter( "artificial_stars: Creating foreground stars...", -1.0 );
1107                 if ( show_progress ) gimp_progress_init( _("Creating foreground stars...") );
1108
1109                 create_stars_psf( star_distribution, region_destination->x, region_destination->y,
1110                         region_destination->w, region_destination->h, &foreground_stars, foreground_stars_number, show_progress );
1111         }
1112
1113         /* Noise */
1114         if ( parameters.noise > 0 )
1115         {
1116                 reporter( "artificial_stars: Creating noise...", -1.0 );
1117                 if ( show_progress ) gimp_progress_init( _("Creating noise...") );
1118
1119                 create_stars_noise( star_distribution, region_destination->w, region_destination->h, show_progress );
1120         }
1121
1122         reporter( "artificial_stars: Writing normalized values to buffer...", -1.0 );
1123         if ( show_progress ) gimp_progress_init( _("Writing normalized values to buffer...") );
1124
1125         guchar *buffer;
1126         buffer = g_malloc( sizeof(guchar)*region_destination->bpp*region_destination->w*region_destination->h );
1127         for ( y=0; y<region_destination->h; y++ )
1128         {
1129                 for ( x=0; x<region_destination->w; x++ )
1130                 {
1131                         for ( i=0; i<3; i++ )
1132                         {
1133                                 buffer[region_destination->bpp*(y*region_destination->w+x)+i] =
1134                                         CLAMP( 255 * star_distribution[3*(y*region_destination->w+x)+i] / brightness_star_norm, 0, 255 );
1135                         }
1136                         if ( region_destination->bpp > 3 )
1137                                 buffer[region_destination->bpp*(y*region_destination->w+x)+region_destination->bpp-1] = 255;
1138                 }
1139
1140                 if ( show_progress && y % (1+region_destination->h/100) )
1141                         gimp_progress_update( (gdouble)(y) / region_destination->h );
1142         }
1143
1144         reporter( "artificial_stars: Setting buffer to image...", -1.0 );
1145         gimp_pixel_rgn_set_rect( region_destination, buffer, region_destination->x, region_destination->y,
1146                 region_destination->w, region_destination->h );
1147
1148         if ( show_progress ) gimp_progress_end();
1149
1150         g_free( star_distribution );
1151         g_free( buffer );
1152 }
1153
1154 /*
1155 create stars
1156 */
1157 static void create_stars()
1158 {
1159         gimp_image_undo_group_start( image_id );
1160
1161         gint32 layer_destination;
1162         GimpPixelRgn region_destination;
1163         if ( parameters.split_layers )
1164         {
1165                 layer_destination = gimp_layer_new( image_id, _("Artificial background stars"), gimp_image_width( image_id ),
1166                         gimp_image_height( image_id ), GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE );
1167
1168                 gimp_image_add_layer( image_id, layer_destination, 0 );
1169
1170                 gimp_pixel_rgn_init( &region_destination, gimp_drawable_get( layer_destination ), 0, 0,
1171                         gimp_drawable_width( layer_destination ), gimp_drawable_height( layer_destination ), TRUE, TRUE );
1172
1173                 create_stars_selection( &region_destination, TRUE, FALSE, FALSE, TRUE );
1174
1175                 gimp_drawable_flush( gimp_drawable_get( layer_destination ) );
1176                 gimp_drawable_merge_shadow( layer_destination, TRUE );
1177                 gimp_drawable_update( layer_destination, 0, 0, gimp_drawable_width( layer_destination ),
1178                 gimp_drawable_height( layer_destination ) );
1179
1180                 layer_destination = gimp_layer_new( image_id, _("Artificial object stars"), gimp_image_width( image_id ),
1181                         gimp_image_height( image_id ), GIMP_RGB_IMAGE, 100, GIMP_LIGHTEN_ONLY_MODE );
1182
1183                 gimp_image_add_layer( image_id, layer_destination, 0 );
1184
1185                 gimp_pixel_rgn_init( &region_destination, gimp_drawable_get( layer_destination ), 0, 0,
1186                         gimp_drawable_width( layer_destination ), gimp_drawable_height( layer_destination ), TRUE, TRUE );
1187
1188                 create_stars_selection( &region_destination, FALSE, TRUE, FALSE, TRUE );
1189
1190                 gimp_drawable_flush( gimp_drawable_get( layer_destination ) );
1191                 gimp_drawable_merge_shadow( layer_destination, TRUE );
1192                 gimp_drawable_update( layer_destination, 0, 0, gimp_drawable_width( layer_destination ),
1193                 gimp_drawable_height( layer_destination ) );
1194
1195                 layer_destination = gimp_layer_new( image_id, _("Artificial foreground stars"), gimp_image_width( image_id ),
1196                         gimp_image_height( image_id ), GIMP_RGB_IMAGE, 100, GIMP_LIGHTEN_ONLY_MODE );
1197
1198                 gimp_image_add_layer( image_id, layer_destination, 0 );
1199
1200                 gimp_pixel_rgn_init( &region_destination, gimp_drawable_get( layer_destination ), 0, 0,
1201                         gimp_drawable_width( layer_destination ), gimp_drawable_height( layer_destination ), TRUE, TRUE );
1202
1203                 create_stars_selection( &region_destination, FALSE, FALSE, TRUE, TRUE );
1204
1205                 gimp_drawable_flush( gimp_drawable_get( layer_destination ) );
1206                 gimp_drawable_merge_shadow( layer_destination, TRUE );
1207                 gimp_drawable_update( layer_destination, 0, 0, gimp_drawable_width( layer_destination ),
1208                 gimp_drawable_height( layer_destination ) );
1209         }
1210         else
1211         {
1212                 layer_destination = gimp_layer_new( image_id, _("Artificial stars"), gimp_image_width( image_id ),
1213                         gimp_image_height( image_id ), GIMP_RGB_IMAGE, 100, GIMP_NORMAL_MODE );
1214
1215                 gimp_image_add_layer( image_id, layer_destination, 0 );
1216
1217                 gimp_pixel_rgn_init( &region_destination, gimp_drawable_get( layer_destination ), 0, 0,
1218                         gimp_drawable_width( layer_destination ), gimp_drawable_height( layer_destination ), TRUE, TRUE );
1219
1220                 create_stars_selection( &region_destination, TRUE, TRUE, TRUE, TRUE );
1221
1222                 gimp_drawable_flush( gimp_drawable_get( layer_destination ) );
1223                 gimp_drawable_merge_shadow( layer_destination, TRUE );
1224                 gimp_drawable_update( layer_destination, 0, 0, gimp_drawable_width( layer_destination ),
1225                 gimp_drawable_height( layer_destination ) );
1226         }
1227
1228         star_free( &background_stars, &background_stars_number );
1229         star_free( &object_stars, &object_stars_number );
1230         star_free( &foreground_stars, &foreground_stars_number );
1231
1232         gimp_image_undo_group_end( image_id );
1233
1234         gimp_displays_flush();
1235 }
1236
1237
1238 /*
1239 GUI
1240 */
1241
1242 /* Preview callback */
1243 static void preview_callback( GimpPreview *preview, gpointer *data )
1244 {
1245         GimpDrawable *drawable = gimp_drawable_preview_get_drawable( GIMP_DRAWABLE_PREVIEW( preview ) );
1246
1247         gint32 x_pos, y_pos, x_size, y_size;
1248         gimp_preview_get_position( preview, &x_pos, &y_pos );
1249         gimp_preview_get_size( preview, &x_size, &y_size );
1250
1251         GimpPixelRgn region_destination;
1252         gimp_pixel_rgn_init( &region_destination, drawable, x_pos, y_pos, x_size, y_size, TRUE, TRUE );
1253
1254         create_stars_selection( &region_destination, TRUE, TRUE, TRUE, FALSE );
1255
1256         gimp_drawable_flush( drawable );
1257         gimp_drawable_update( drawable->drawable_id, 0, 0, drawable->width, drawable->height );
1258
1259         /* Read from shadow tiles ("FALSE, TRUE") */
1260         gimp_pixel_rgn_init( &region_destination, drawable, 0, 0, drawable->width, drawable->height, FALSE, TRUE );
1261         gimp_drawable_preview_draw_region( GIMP_DRAWABLE_PREVIEW( preview ), &region_destination );
1262 }
1263
1264 static void spin_background_stars( GtkWidget *spin )
1265 {
1266         parameters.background_stars = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1267 }
1268
1269 static void spin_background_brightness_mean( GtkWidget *spin )
1270 {
1271         parameters.background_brightness_mean = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1272 }
1273
1274 static void spin_background_brightness_sigma( GtkWidget *spin )
1275 {
1276         parameters.background_brightness_sigma = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1277 }
1278
1279 static void spin_background_color_mean( GtkWidget *spin )
1280 {
1281         parameters.background_color_mean = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1282 }
1283
1284 static void spin_background_color_sigma( GtkWidget *spin )
1285 {
1286         parameters.background_color_sigma = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1287 }
1288
1289 static void spin_object_stars( GtkWidget *spin )
1290 {
1291         parameters.object_stars = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1292 }
1293
1294 static void spin_object_brightness_mean( GtkWidget *spin )
1295 {
1296         parameters.object_brightness_mean = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1297 }
1298
1299 static void spin_object_brightness_sigma( GtkWidget *spin )
1300 {
1301         parameters.object_brightness_sigma = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1302 }
1303
1304 static void spin_object_color_mean( GtkWidget *spin )
1305 {
1306         parameters.object_color_mean = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1307 }
1308
1309 static void spin_object_color_sigma( GtkWidget *spin )
1310 {
1311         parameters.object_color_sigma = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1312 }
1313
1314 static void spin_object_x( GtkWidget *spin )
1315 {
1316         parameters.object_x = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1317 }
1318
1319 static void spin_object_y( GtkWidget *spin )
1320 {
1321         parameters.object_y = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1322 }
1323
1324 static void spin_foreground_stars( GtkWidget *spin )
1325 {
1326         parameters.foreground_stars = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1327 }
1328
1329 static void spin_foreground_brightness_mean( GtkWidget *spin )
1330 {
1331         parameters.foreground_brightness_mean = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1332 }
1333
1334 static void spin_foreground_brightness_sigma( GtkWidget *spin )
1335 {
1336         parameters.foreground_brightness_sigma = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1337 }
1338
1339 static void spin_foreground_color_mean( GtkWidget *spin )
1340 {
1341         parameters.foreground_color_mean = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1342 }
1343
1344 static void spin_foreground_color_sigma( GtkWidget *spin )
1345 {
1346         parameters.foreground_color_sigma = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1347 }
1348
1349 static void spin_random_seed( GtkWidget *spin )
1350 {
1351         parameters.random_seed = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
1352 }
1353
1354 static void split_layers_toggled( GtkWidget *check )
1355 {
1356         parameters.split_layers = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check ) );
1357 }
1358
1359 static void object_mask_toggled( GtkWidget *check )
1360 {
1361         parameters.object_mask = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( check ) );
1362 }
1363
1364 static void recalculate_distribution_clicked( GtkWidget *button )
1365 {
1366         if ( !recalculating )
1367         {
1368                 recalculating = TRUE;
1369                 cancel_recalculation = FALSE;
1370
1371                 gtk_button_set_label( GTK_BUTTON( recalculate_button ), _("Cancel recalculation") );
1372
1373                 create_star_distribution();
1374         }
1375         else
1376         {
1377                 recalculating = FALSE;
1378                 cancel_recalculation = TRUE;
1379
1380                 gtk_button_set_label( GTK_BUTTON( recalculate_button ), _("Recalculate distribution") );
1381         }
1382 }
1383
1384 static void recalculation_necessary()
1385 {
1386         distribution_dirty = TRUE;
1387
1388         GdkColor color;
1389         color.red = 55000;
1390         color.green = 12000;
1391         color.blue = 15000;
1392         gtk_widget_modify_bg( recalculate_button, GTK_STATE_NORMAL, &color );
1393         gtk_widget_modify_bg( recalculate_button, GTK_STATE_PRELIGHT, &color );
1394         gtk_widget_modify_bg( recalculate_button, GTK_STATE_ACTIVE, &color );
1395 }
1396
1397 static void recalculation_done()
1398 {
1399         distribution_dirty = FALSE;
1400
1401         gtk_widget_modify_bg( recalculate_button, GTK_STATE_NORMAL, NULL );
1402         gtk_widget_modify_bg( recalculate_button, GTK_STATE_PRELIGHT, NULL );
1403         gtk_widget_modify_bg( recalculate_button, GTK_STATE_ACTIVE, NULL );
1404 }
1405
1406 static void standard_hd_clicked( GtkWidget *button )
1407 {
1408         gdouble number_percentage = (gdouble)(gimp_image_width( image_id )*gimp_image_height( image_id ))/3.3e6;
1409
1410         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), (gint32)40000*number_percentage );
1411         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), 0. );
1412         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), 15. );
1413         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), 7000 );
1414         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), 1000 );
1415
1416         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), (gint32)5000*number_percentage );
1417         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), 45. );
1418         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), 30. );
1419         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), 7000 );
1420         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), 1000 );
1421         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), gimp_image_width( image_id )/2 );
1422         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), gimp_image_height( image_id )/2 );
1423         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), DENSITY_RANDOM );
1424
1425         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), (gint32)2000*number_percentage );
1426         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), 80. );
1427         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), 35. );
1428         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), 7500 );
1429         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), 1000 );
1430 }
1431
1432 static void standard_ld_clicked( GtkWidget *button )
1433 {
1434         gdouble number_percentage = (gdouble)(gimp_image_width( image_id )*gimp_image_height( image_id ))/3.3e6;
1435
1436         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), (gint32)2500*number_percentage );
1437         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), 15. );
1438         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), 10. );
1439         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), 7000 );
1440         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), 1000 );
1441
1442         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), (gint32)500*number_percentage );
1443         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), 45. );
1444         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), 30. );
1445         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), 7000 );
1446         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), 1000 );
1447         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), gimp_image_width( image_id )/2 );
1448         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), gimp_image_height( image_id )/2 );
1449         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), DENSITY_RANDOM );
1450
1451         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), (gint32)15*number_percentage );
1452         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), 90. );
1453         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), 40. );
1454         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), 7500 );
1455         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), 1000 );
1456 }
1457
1458 static void globular_hd_clicked( GtkWidget *button )
1459 {
1460         gdouble number_percentage = (gdouble)(gimp_image_width( image_id )*gimp_image_height( image_id ))/3.3e6;
1461
1462         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), (gint32)5000*number_percentage );
1463         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), 0. );
1464         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), 45. );
1465         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), 7500 );
1466         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), 1000 );
1467
1468         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), (gint32)50000*number_percentage );
1469         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), 100. );
1470         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), 40. );
1471         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), 6500 );
1472         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), 800 );
1473         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), gimp_image_width( image_id )/2 );
1474         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), gimp_image_height( image_id )/2 );
1475         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), DENSITY_PLUMMER );
1476         gtk_spin_button_set_value( GTK_SPIN_BUTTON( GIMP_SCALE_ENTRY_SPINBUTTON( object_radius_adj ) ), 50 );
1477
1478         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), (gint32)1000*number_percentage );
1479         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), 90. );
1480         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), 60. );
1481         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), 7500 );
1482         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), 1000 );
1483 }
1484
1485 static void globular_ld_clicked( GtkWidget *button )
1486 {
1487         gdouble number_percentage = (gdouble)(gimp_image_width( image_id )*gimp_image_height( image_id ))/3.3e6;
1488
1489         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), (gint32)5000*number_percentage );
1490         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), 0. );
1491         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), 45. );
1492         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), 7500 );
1493         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), 1000 );
1494
1495         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), (gint32)10000*number_percentage );
1496         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), 100. );
1497         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), 40. );
1498         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), 6500 );
1499         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), 800 );
1500         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), gimp_image_width( image_id )/2 );
1501         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), gimp_image_height( image_id )/2 );
1502         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), DENSITY_PLUMMER );
1503         gtk_spin_button_set_value( GTK_SPIN_BUTTON( GIMP_SCALE_ENTRY_SPINBUTTON( object_radius_adj ) ), 15 );
1504
1505         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), (gint32)1000*number_percentage );
1506         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), 90. );
1507         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), 60. );
1508         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), 7500 );
1509         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), 1000 );
1510 }
1511
1512 static void open_hd_clicked( GtkWidget *button )
1513 {
1514         gdouble number_percentage = (gdouble)(gimp_image_width( image_id )*gimp_image_height( image_id ))/3.3e6;
1515
1516         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), (gint32)40000*number_percentage );
1517         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), 0. );
1518         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), 25. );
1519         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), 7200 );
1520         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), 1000 );
1521
1522         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), (gint32)1200*number_percentage );
1523         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), 80. );
1524         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), 35. );
1525         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), 7100 );
1526         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), 500 );
1527         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), gimp_image_width( image_id )/2 );
1528         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), gimp_image_height( image_id )/2 );
1529         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), DENSITY_GAUSS );
1530         gtk_spin_button_set_value( GTK_SPIN_BUTTON( GIMP_SCALE_ENTRY_SPINBUTTON( object_radius_adj ) ), 6 );
1531
1532         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), (gint32)2000*number_percentage );
1533         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), 100. );
1534         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), 40. );
1535         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), 7200 );
1536         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), 1000 );
1537 }
1538
1539 static void open_ld_clicked( GtkWidget *button )
1540 {
1541         gdouble number_percentage = (gdouble)(gimp_image_width( image_id )*gimp_image_height( image_id ))/3.3e6;
1542
1543         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), (gint32)40000*number_percentage );
1544         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), 0. );
1545         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), 25. );
1546         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), 7200 );
1547         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), 1000 );
1548
1549         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), (gint32)300*number_percentage );
1550         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), 110. );
1551         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), 30. );
1552         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), 7100 );
1553         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), 500 );
1554         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), gimp_image_width( image_id )/2 );
1555         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), gimp_image_height( image_id )/2 );
1556         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), DENSITY_PLUMMER );
1557         gtk_spin_button_set_value( GTK_SPIN_BUTTON( GIMP_SCALE_ENTRY_SPINBUTTON( object_radius_adj ) ), 180 );
1558
1559         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), (gint32)2000*number_percentage );
1560         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), 100. );
1561         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), 40. );
1562         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), 7200 );
1563         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), 1000 );
1564 }
1565
1566 void reporter( const gchar *string, const gdouble fraction )
1567 {
1568         if ( strcmp( string, "" ) == 0 )
1569         {
1570                 if ( fraction == 0. )
1571                 {
1572                         if ( dialog_closed )
1573                         {
1574                                 gimp_progress_init( string );
1575                         }
1576                         else
1577                         {
1578                                 gtk_progress_bar_set_text( GTK_PROGRESS_BAR( progress_bar ), string );
1579                                 gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( progress_bar ), fraction );
1580                                 gtk_main_iteration_do( FALSE );
1581                         }
1582                 }
1583                 else if ( fraction > 0. && fraction <= 1. )
1584                 {
1585                         if ( dialog_closed )
1586                         {
1587                                 gimp_progress_update( fraction );
1588                         }
1589                         else
1590                         {
1591                                 gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( progress_bar ), fraction );
1592                                 gtk_main_iteration_do( FALSE );
1593                         }
1594                 }
1595         }
1596         else
1597         {
1598                 if ( fraction >= 0. && fraction <= 1. )
1599                 {
1600                         if ( dialog_closed )
1601                         {
1602                                 gimp_progress_init( string );
1603                                 gimp_progress_update( fraction );
1604                         }
1605                         else
1606                         {
1607                                 gtk_progress_bar_set_text( GTK_PROGRESS_BAR( progress_bar ), string );
1608                                 gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR( progress_bar ), fraction );
1609                                 gtk_main_iteration_do( FALSE );
1610                         }
1611                 }
1612                 else
1613                 {
1614                         printf( "artificial_stars: %s\n", string );
1615                 }
1616         }
1617 }
1618
1619 /*
1620 main dialog
1621 */
1622 static gint dialog( gint32 image_id, GimpDrawable *drawable )
1623 {
1624         GtkWidget *dlg;
1625         GtkWidget *notebook;
1626         GtkWidget *main_hbox;
1627         GtkWidget *left_vbox;
1628         GtkWidget *right_vbox;
1629         GtkWidget *label;
1630         GtkWidget *button;
1631         GtkWidget *object_box;
1632         GtkWidget *check_box;
1633         GtkWidget *random_seed;
1634         GtkWidget *frame;
1635         GtkWidget *table;
1636         GtkObject *adj;
1637
1638   gimp_ui_init( PLUG_IN_NAME, TRUE );
1639
1640         dlg = gimp_dialog_new( _("Artificial Stars"), "astro_artificial_stars", NULL, 0,
1641                 gimp_standard_help_func, PLUG_IN_NAME,
1642                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1643                 GTK_STOCK_OK, GTK_RESPONSE_OK,
1644                 NULL );
1645
1646 /* General layout */
1647         main_hbox = gtk_hbox_new( FALSE, 8 );
1648         gtk_container_set_border_width( GTK_CONTAINER( main_hbox ), 8 );
1649         gtk_container_add( GTK_CONTAINER( GTK_DIALOG( dlg )->vbox ), main_hbox );
1650
1651         left_vbox = gtk_vbox_new( FALSE, 8 );
1652         gtk_container_set_border_width( GTK_CONTAINER( left_vbox ), 8 );
1653         gtk_box_pack_start( GTK_BOX( main_hbox ), left_vbox, FALSE, FALSE, 0 );
1654
1655 /*      GtkWidget *vertical_line = gtk_vseparator_new();
1656         gtk_box_pack_start( GTK_BOX( main_hbox ), vertical_line, FALSE, FALSE, 0 );
1657         gtk_widget_show( vertical_line ); */
1658
1659         right_vbox = gtk_vbox_new( FALSE, 8 );
1660         gtk_container_set_border_width( GTK_CONTAINER( right_vbox ), 8 );
1661         gtk_box_pack_start( GTK_BOX( main_hbox ), right_vbox, FALSE, FALSE, 0 );
1662
1663 /* Preview (left side) */
1664
1665         preview = gimp_drawable_preview_new( drawable, &parameters.show_preview );
1666         gtk_box_pack_start( GTK_BOX( left_vbox ), preview, FALSE, FALSE, 0 );
1667         gtk_widget_show( preview );
1668
1669         g_signal_connect( preview, "invalidated", G_CALLBACK( preview_callback ), NULL );
1670
1671 /* Star distribution (left side) */
1672
1673         frame = gimp_frame_new( _("Star Distribution") );
1674         gtk_box_pack_start( GTK_BOX( left_vbox ), frame, FALSE, FALSE, 0 );
1675         gtk_widget_show( frame );
1676
1677         table = gtk_table_new( 3, 1, FALSE );
1678         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
1679         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
1680         gtk_container_add( GTK_CONTAINER( frame ), table );
1681         gtk_widget_show( table );
1682
1683         recalculate_button = gtk_button_new_with_label( _("Recalculate distribution") );
1684         gtk_table_attach( GTK_TABLE( table ), recalculate_button, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0 );
1685
1686         recalculation_necessary();
1687
1688         gtk_widget_show( recalculate_button );
1689         g_signal_connect( recalculate_button, "clicked", G_CALLBACK( recalculate_distribution_clicked ), NULL );
1690
1691         progress_bar = gtk_progress_bar_new();
1692         gtk_widget_set_size_request( progress_bar, -1, 24 );
1693         gtk_table_attach( GTK_TABLE( table ), progress_bar, 0, 1, 1, 2, GTK_FILL, 0, 0, 0 );
1694         gtk_widget_show( progress_bar );
1695         gtk_progress_bar_set_orientation( GTK_PROGRESS_BAR( progress_bar ), GTK_PROGRESS_LEFT_TO_RIGHT );
1696
1697         random_seed = gimp_random_seed_new( &parameters.random_seed, &parameters.random_seed_bool );
1698         gtk_table_attach( GTK_TABLE( table ), random_seed, 0, 1, 2, 3, GTK_FILL, 0, 0, 0 );
1699         gtk_widget_show( random_seed );
1700         g_signal_connect( GIMP_RANDOM_SEED_SPINBUTTON( random_seed ), "value_changed", G_CALLBACK( spin_random_seed ), NULL );
1701         g_signal_connect_swapped( GIMP_RANDOM_SEED_SPINBUTTON( random_seed ), "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1702
1703 /* Sample Distributions */
1704
1705         frame = gimp_frame_new( _("Sample Distributions") );
1706         gtk_box_pack_start( GTK_BOX( left_vbox ), frame, FALSE, FALSE, 0 );
1707         gtk_widget_show( frame );
1708
1709         table = gtk_table_new( 2, 3, FALSE );
1710         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
1711         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
1712         gtk_container_add( GTK_CONTAINER( frame ), table );
1713         gtk_widget_show( table );
1714
1715         button = gtk_button_new_with_label( _("Standard (HD)") );
1716         gtk_table_attach( GTK_TABLE( table ), button, 0, 1, 0, 1, GTK_FILL, 0, 0, 0 );
1717         gtk_widget_show( button );
1718         g_signal_connect( button, "clicked", G_CALLBACK( standard_hd_clicked ), NULL );
1719         g_signal_connect_swapped( button, "clicked", G_CALLBACK( recalculation_necessary ), NULL );
1720
1721         button = gtk_button_new_with_label( _("Standard (LD)") );
1722         gtk_table_attach( GTK_TABLE( table ), button, 0, 1, 1, 2, GTK_FILL, 0, 0, 0 );
1723         gtk_widget_show( button );
1724         g_signal_connect( button, "clicked", G_CALLBACK( standard_ld_clicked ), NULL );
1725         g_signal_connect_swapped( button, "clicked", G_CALLBACK( recalculation_necessary ), NULL );
1726
1727         button = gtk_button_new_with_label( _("Globular cluster (HD)") );
1728         gtk_table_attach( GTK_TABLE( table ), button, 1, 2, 0, 1, GTK_FILL, 0, 0, 0 );
1729         gtk_widget_show( button );
1730         g_signal_connect( button, "clicked", G_CALLBACK( globular_hd_clicked ), NULL );
1731         g_signal_connect_swapped( button, "clicked", G_CALLBACK( recalculation_necessary ), NULL );
1732
1733         button = gtk_button_new_with_label( _("Globular cluster (LD)") );
1734         gtk_table_attach( GTK_TABLE( table ), button, 1, 2, 1, 2, GTK_FILL, 0, 0, 0 );
1735         gtk_widget_show( button );
1736         g_signal_connect( button, "clicked", G_CALLBACK( globular_ld_clicked ), NULL );
1737         g_signal_connect_swapped( button, "clicked", G_CALLBACK( recalculation_necessary ), NULL );
1738
1739         button = gtk_button_new_with_label( _("Open cluster (HD)") );
1740         gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 0, 1, GTK_FILL, 0, 0, 0 );
1741         gtk_widget_show( button );
1742         g_signal_connect( button, "clicked", G_CALLBACK( open_hd_clicked ), NULL );
1743         g_signal_connect_swapped( button, "clicked", G_CALLBACK( recalculation_necessary ), NULL );
1744
1745         button = gtk_button_new_with_label( _("Open cluster (LD)") );
1746         gtk_table_attach( GTK_TABLE( table ), button, 2, 3, 1, 2, GTK_FILL, 0, 0, 0 );
1747         gtk_widget_show( button );
1748         g_signal_connect( button, "clicked", G_CALLBACK( open_ld_clicked ), NULL );
1749         g_signal_connect_swapped( button, "clicked", G_CALLBACK( recalculation_necessary ), NULL );
1750
1751
1752
1753 /*  Create notebook  */
1754         notebook = gtk_notebook_new ();
1755         gtk_box_pack_start (GTK_BOX (main_hbox), notebook, FALSE, FALSE, 0);
1756         gtk_widget_show (notebook);
1757
1758 /*  Distribution options page  */
1759         right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
1760         gtk_container_set_border_width (GTK_CONTAINER (right_vbox), 12);
1761         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), right_vbox,
1762                             gtk_label_new_with_mnemonic (_("_Distribution Options")));
1763         gtk_widget_show (right_vbox);
1764
1765         frame = gimp_frame_new( _("Background Stars") );
1766         gtk_box_pack_start( GTK_BOX( right_vbox ), frame, FALSE, FALSE, 0 );
1767         gtk_widget_show( frame );
1768
1769         table = gtk_table_new( 3, 4, FALSE );
1770         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
1771         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
1772         gtk_container_add( GTK_CONTAINER( frame ), table );
1773         gtk_widget_show( table );
1774
1775         label = gtk_label_new( _("Amount:") );
1776         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1777         background_number_spin = gtk_spin_button_new_with_range( 0, 40000, 1 );
1778         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_number_spin ), parameters.background_stars );
1779         g_signal_connect( background_number_spin, "value_changed", G_CALLBACK( spin_background_stars ), NULL );
1780         g_signal_connect_swapped( background_number_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1781         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0 );
1782         gtk_widget_show( label );
1783         gtk_table_attach( GTK_TABLE( table ), background_number_spin, 1, 2, 0, 1, GTK_FILL, 0, 0, 0 );
1784         gtk_widget_show( background_number_spin );
1785
1786         label = gtk_label_new( _("Brightness mean:") );
1787         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1788         background_brightness_spin = gtk_spin_button_new_with_range( 0, 1000, 0.1 );
1789         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_spin ), parameters.background_brightness_mean );
1790         g_signal_connect( background_brightness_spin, "value_changed", G_CALLBACK( spin_background_brightness_mean ), NULL );
1791         g_signal_connect_swapped( background_brightness_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1792         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0 );
1793         gtk_widget_show( label );
1794         gtk_table_attach( GTK_TABLE( table ), background_brightness_spin, 1, 2, 1, 2, GTK_FILL, 0, 0, 0 );
1795         gtk_widget_show( background_brightness_spin );
1796
1797         label = gtk_label_new( _("Brightness sigma:") );
1798         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1799         background_brightness_sigma_spin = gtk_spin_button_new_with_range( 0, 500, 0.1 );
1800         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_brightness_sigma_spin ), parameters.background_brightness_sigma );
1801         g_signal_connect( background_brightness_sigma_spin, "value_changed", G_CALLBACK( spin_background_brightness_sigma ), NULL );
1802         g_signal_connect_swapped( background_brightness_sigma_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1803         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0 );
1804         gtk_widget_show( label );
1805         gtk_table_attach( GTK_TABLE( table ), background_brightness_sigma_spin, 3, 4, 1, 2, GTK_FILL, 0, 0, 0 );
1806         gtk_widget_show( background_brightness_sigma_spin );
1807
1808         label = gtk_label_new( _("Color mean:") );
1809         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1810         background_color_spin = gtk_spin_button_new_with_range( 1000, 100000, 1 );
1811         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_spin ), parameters.background_color_mean );
1812         g_signal_connect( background_color_spin, "value_changed", G_CALLBACK( spin_background_color_mean ), NULL );
1813         g_signal_connect_swapped( background_color_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1814         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0 );
1815         gtk_widget_show( label );
1816         gtk_table_attach( GTK_TABLE( table ), background_color_spin, 1, 2, 2, 3, GTK_FILL, 0, 0, 0 );
1817         gtk_widget_show( background_color_spin );
1818
1819         label = gtk_label_new( _("Color sigma:") );
1820         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1821         background_color_sigma_spin = gtk_spin_button_new_with_range( 1, 10000, 1 );
1822         gtk_spin_button_set_value( GTK_SPIN_BUTTON( background_color_sigma_spin ), parameters.background_color_sigma );
1823         g_signal_connect( background_color_sigma_spin, "value_changed", G_CALLBACK( spin_background_color_sigma ), NULL );
1824         g_signal_connect_swapped( background_color_sigma_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1825         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 2, 3, GTK_FILL, 0, 0, 0 );
1826         gtk_widget_show( label );
1827         gtk_table_attach( GTK_TABLE( table ), background_color_sigma_spin, 3, 4, 2, 3, GTK_FILL, 0, 0, 0 );
1828         gtk_widget_show( background_color_sigma_spin );
1829
1830
1831         frame = gimp_frame_new( _("Object Stars") );
1832         gtk_box_pack_start( GTK_BOX( right_vbox ), frame, FALSE, FALSE, 0 );
1833         gtk_widget_show( frame );
1834
1835         object_box = gtk_vbox_new( FALSE, 8 );
1836         gtk_container_set_border_width( GTK_CONTAINER( object_box ), 0 );
1837         gtk_container_add( GTK_CONTAINER( frame ), object_box );
1838
1839         table = gtk_table_new( 3, 4, FALSE );
1840         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
1841         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
1842         gtk_box_pack_start( GTK_BOX( object_box ), table, FALSE, FALSE, 0 );
1843         gtk_widget_show( table );
1844
1845         label = gtk_label_new( _("Amount:") );
1846         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1847         object_number_spin = gtk_spin_button_new_with_range( 0, 100000, 1 );
1848         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_number_spin ), parameters.object_stars );
1849         g_signal_connect( object_number_spin, "value_changed", G_CALLBACK( spin_object_stars ), NULL );
1850         g_signal_connect_swapped( object_number_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1851         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0 );
1852         gtk_widget_show( label );
1853         gtk_table_attach( GTK_TABLE( table ), object_number_spin, 1, 2, 0, 1, GTK_FILL, 0, 0, 0 );
1854         gtk_widget_show( object_number_spin );
1855
1856         label = gtk_label_new( _("Brightness mean:") );
1857         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1858         object_brightness_spin = gtk_spin_button_new_with_range( 0, 1000, 0.1 );
1859         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_spin ), parameters.object_brightness_mean );
1860         g_signal_connect( object_brightness_spin, "value_changed", G_CALLBACK( spin_object_brightness_mean ), NULL );
1861         g_signal_connect_swapped( object_brightness_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1862         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0 );
1863         gtk_widget_show( label );
1864         gtk_table_attach( GTK_TABLE( table ), object_brightness_spin, 1, 2, 1, 2, GTK_FILL, 0, 0, 0 );
1865         gtk_widget_show( object_brightness_spin );
1866
1867         label = gtk_label_new( _("Brightness sigma:") );
1868         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1869         object_brightness_sigma_spin = gtk_spin_button_new_with_range( 0, 500, 0.1 );
1870         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_brightness_sigma_spin ), parameters.object_brightness_sigma );
1871         g_signal_connect( object_brightness_sigma_spin, "value_changed", G_CALLBACK( spin_object_brightness_sigma ), NULL );
1872         g_signal_connect_swapped( object_brightness_sigma_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1873         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0 );
1874         gtk_widget_show( label );
1875         gtk_table_attach( GTK_TABLE( table ), object_brightness_sigma_spin, 3, 4, 1, 2, GTK_FILL, 0, 0, 0 );
1876         gtk_widget_show( object_brightness_sigma_spin );
1877
1878         label = gtk_label_new( _("Color mean:") );
1879         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1880         object_color_spin = gtk_spin_button_new_with_range( 1000, 40000, 1 );
1881         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_spin ), parameters.object_color_mean );
1882         g_signal_connect( object_color_spin, "value_changed", G_CALLBACK( spin_object_color_mean ), NULL );
1883         g_signal_connect_swapped( object_color_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1884         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0 );
1885         gtk_widget_show( label );
1886         gtk_table_attach( GTK_TABLE( table ), object_color_spin, 1, 2, 2, 3, GTK_FILL, 0, 0, 0 );
1887         gtk_widget_show( object_color_spin );
1888
1889         label = gtk_label_new( _("Color sigma:") );
1890         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1891         object_color_sigma_spin = gtk_spin_button_new_with_range( 1, 10000, 1 );
1892         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_color_sigma_spin ), parameters.object_color_sigma );
1893         g_signal_connect( object_color_sigma_spin, "value_changed", G_CALLBACK( spin_object_color_sigma ), NULL );
1894         g_signal_connect_swapped( object_color_sigma_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1895         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 2, 3, GTK_FILL, 0, 0, 0 );
1896         gtk_widget_show( label );
1897         gtk_table_attach( GTK_TABLE( table ), object_color_sigma_spin, 3, 4, 2, 3, GTK_FILL, 0, 0, 0 );
1898         gtk_widget_show( object_color_sigma_spin );
1899
1900         if ( parameters.object_x == 0 ) parameters.object_x = gimp_image_width( image_id )/2;
1901         label = gtk_label_new( _("Object center: X:") );
1902         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1903         object_center_x_spin = gtk_spin_button_new_with_range( 0, gimp_image_width( image_id ), 1 );
1904         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_x_spin ), parameters.object_x );
1905         g_signal_connect( object_center_x_spin, "value_changed", G_CALLBACK( spin_object_x ), NULL );
1906         g_signal_connect_swapped( object_center_x_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1907         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 3, 4, GTK_FILL, 0, 0, 0 );
1908         gtk_widget_show( label );
1909         gtk_table_attach( GTK_TABLE( table ), object_center_x_spin, 1, 2, 3, 4, GTK_FILL, 0, 0, 0 );
1910         gtk_widget_show( object_center_x_spin );
1911
1912         if ( parameters.object_y == 0 ) parameters.object_y = gimp_image_height( image_id )/2;
1913         label = gtk_label_new( _("Y:") );
1914         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1915         object_center_y_spin = gtk_spin_button_new_with_range( 0, gimp_image_height( image_id ), 1 );
1916         gtk_spin_button_set_value( GTK_SPIN_BUTTON( object_center_y_spin ), parameters.object_y );
1917         g_signal_connect( object_center_y_spin, "value_changed", G_CALLBACK( spin_object_y ), NULL );
1918         g_signal_connect_swapped( object_center_y_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1919         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 3, 4, GTK_FILL, 0, 0, 0 );
1920         gtk_widget_show( label );
1921         gtk_table_attach( GTK_TABLE( table ), object_center_y_spin, 3, 4, 3, 4, GTK_FILL, 0, 0, 0 );
1922         gtk_widget_show( object_center_y_spin );
1923
1924         table = gtk_table_new( 2, 3, FALSE );
1925         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
1926         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
1927         gtk_box_pack_start( GTK_BOX( object_box ), table, FALSE, FALSE, 0 );
1928         gtk_widget_show( table );
1929
1930         label = gtk_label_new( _("Density profile:") );
1931         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1932         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
1933         gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT );
1934         gtk_widget_show( label );
1935
1936         object_density_combo = gimp_int_combo_box_new(
1937                 _("Random"), DENSITY_RANDOM,
1938                 _("Gauss"), DENSITY_GAUSS,
1939                 _("Plummer"), DENSITY_PLUMMER,
1940                 NULL );
1941         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( object_density_combo ), parameters.object_density );
1942         gimp_int_combo_box_connect( GIMP_INT_COMBO_BOX( object_density_combo ), parameters.object_density,
1943                 G_CALLBACK( gimp_int_combo_box_get_active ), &parameters.object_density );
1944         gimp_int_combo_box_connect( GIMP_INT_COMBO_BOX( object_density_combo ), parameters.object_density,
1945                 G_CALLBACK( recalculation_necessary ), NULL );
1946         gtk_table_attach( GTK_TABLE( table ), object_density_combo, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
1947         gtk_widget_show( object_density_combo );
1948
1949         object_radius_adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 2,
1950                 _("Radius parameter:"), 125, 75,
1951                 parameters.object_radius, 0, 200, 1, 5, 0,
1952                 TRUE, 0, 0, _("Radius of object in % of the image (unused for random distribution)"), NULL );
1953         g_signal_connect( object_radius_adj, "value_changed", G_CALLBACK( gimp_int_adjustment_update ),
1954                 &parameters.object_radius );
1955         g_signal_connect_swapped( object_radius_adj, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1956
1957         gtk_widget_show( object_box );
1958
1959
1960         frame = gimp_frame_new( _("Foreground Stars") );
1961         gtk_box_pack_start( GTK_BOX( right_vbox ), frame, FALSE, FALSE, 0 );
1962         gtk_widget_show( frame );
1963
1964         table = gtk_table_new( 2, 6, FALSE );
1965         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
1966         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
1967         gtk_container_add( GTK_CONTAINER( frame ), table );
1968         gtk_widget_show( table );
1969
1970         label = gtk_label_new( _("Amount:") );
1971         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1972         foreground_number_spin = gtk_spin_button_new_with_range( 0, 10000, 1 );
1973         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_number_spin ), parameters.foreground_stars );
1974         g_signal_connect( foreground_number_spin, "value_changed", G_CALLBACK( spin_foreground_stars ), NULL );
1975         g_signal_connect_swapped( foreground_number_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1976         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, GTK_FILL, 0, 0, 0 );
1977         gtk_widget_show( label );
1978         gtk_table_attach( GTK_TABLE( table ), foreground_number_spin, 1, 2, 0, 1, GTK_FILL, 0, 0, 0 );
1979         gtk_widget_show( foreground_number_spin );
1980
1981         label = gtk_label_new( _("Brightness mean:") );
1982         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1983         foreground_brightness_spin = gtk_spin_button_new_with_range( 0, 1000, 0.1 );
1984         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_spin ), parameters.foreground_brightness_mean );
1985         g_signal_connect( foreground_brightness_spin, "value_changed", G_CALLBACK( spin_foreground_brightness_mean ), NULL );
1986         g_signal_connect_swapped( foreground_brightness_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1987         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 1, 2, GTK_FILL, 0, 0, 0 );
1988         gtk_widget_show( label );
1989         gtk_table_attach( GTK_TABLE( table ), foreground_brightness_spin, 1, 2, 1, 2, GTK_FILL, 0, 0, 0 );
1990         gtk_widget_show( foreground_brightness_spin );
1991
1992         label = gtk_label_new( _("Brightness sigma:") );
1993         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
1994         foreground_brightness_sigma_spin = gtk_spin_button_new_with_range( 0, 500, 0.1 );
1995         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_brightness_sigma_spin ), parameters.foreground_brightness_sigma );
1996         g_signal_connect( foreground_brightness_sigma_spin, "value_changed", G_CALLBACK( spin_foreground_brightness_sigma ), NULL );
1997         g_signal_connect_swapped( foreground_brightness_sigma_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
1998         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 1, 2, GTK_FILL, 0, 0, 0 );
1999         gtk_widget_show( label );
2000         gtk_table_attach( GTK_TABLE( table ), foreground_brightness_sigma_spin, 3, 4, 1, 2, GTK_FILL, 0, 0, 0 );
2001         gtk_widget_show( foreground_brightness_sigma_spin );
2002
2003         label = gtk_label_new( _("Color mean:") );
2004         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2005         foreground_color_spin = gtk_spin_button_new_with_range( 1000, 40000, 1 );
2006         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_spin ), parameters.foreground_color_mean );
2007         g_signal_connect( foreground_color_spin, "value_changed", G_CALLBACK( spin_foreground_color_mean ), NULL );
2008         g_signal_connect_swapped( foreground_color_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
2009         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 2, 3, GTK_FILL, 0, 0, 0 );
2010         gtk_widget_show( label );
2011         gtk_table_attach( GTK_TABLE( table ), foreground_color_spin, 1, 2, 2, 3, GTK_FILL, 0, 0, 0 );
2012         gtk_widget_show( foreground_color_spin );
2013
2014         label = gtk_label_new( _("Color sigma:") );
2015         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2016         foreground_color_sigma_spin = gtk_spin_button_new_with_range( 1, 10000, 1 );
2017         gtk_spin_button_set_value( GTK_SPIN_BUTTON( foreground_color_sigma_spin ), parameters.foreground_color_sigma );
2018         g_signal_connect( foreground_color_sigma_spin, "value_changed", G_CALLBACK( spin_foreground_color_sigma ), NULL );
2019         g_signal_connect_swapped( foreground_color_sigma_spin, "value_changed", G_CALLBACK( recalculation_necessary ), NULL );
2020         gtk_table_attach( GTK_TABLE( table ), label, 2, 3, 2, 3, GTK_FILL, 0, 0, 0 );
2021         gtk_widget_show( label );
2022         gtk_table_attach( GTK_TABLE( table ), foreground_color_sigma_spin, 3, 4, 2, 3, GTK_FILL, 0, 0, 0 );
2023         gtk_widget_show( foreground_color_sigma_spin );
2024
2025 /* Rendering options */
2026
2027         right_vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
2028         gtk_container_set_border_width (GTK_CONTAINER (right_vbox), 12);
2029         gtk_notebook_append_page (GTK_NOTEBOOK (notebook), right_vbox,
2030                             gtk_label_new_with_mnemonic (_("R_endering")));
2031         gtk_widget_show (right_vbox);
2032
2033         frame = gimp_frame_new( _("Options") );
2034         gtk_box_pack_start( GTK_BOX( right_vbox ), frame, FALSE, FALSE, 0 );
2035         gtk_widget_show( frame );
2036
2037         table = gtk_table_new( 12, 3, FALSE );
2038         gtk_table_set_col_spacings( GTK_TABLE( table ), 6 );
2039         gtk_table_set_row_spacings( GTK_TABLE( table ), 2 );
2040         gtk_container_add( GTK_CONTAINER( frame ), table );
2041         gtk_widget_show( table );
2042
2043         label = gtk_label_new( _("PSF:") );
2044         gtk_table_attach( GTK_TABLE( table ), label, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
2045         gtk_misc_set_alignment( GTK_MISC( label ), 0, 0.5 );
2046         gtk_widget_show( label );
2047
2048         GtkWidget *psf = gimp_int_combo_box_new(
2049                 _("Delta peak"), PSF_DELTA_PEAK,
2050                 _("Gauss"), PSF_GAUSS,
2051                 _("Gauss with 4 diffraction lines"), PSF_GAUSS_4_DIFFRACTIONS,
2052                 _("Gauss with 6 diffraction lines"), PSF_GAUSS_6_DIFFRACTIONS,
2053                 _("Gauss with 12 diffraction lines"), PSF_GAUSS_12_DIFFRACTIONS,
2054                 NULL );
2055         gimp_int_combo_box_set_active( GIMP_INT_COMBO_BOX( psf ), parameters.psf );
2056         gimp_int_combo_box_connect( GIMP_INT_COMBO_BOX( psf ), parameters.psf,
2057                 G_CALLBACK( gimp_int_combo_box_get_active ), &parameters.psf );
2058         g_signal_connect_swapped( psf, "changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2059
2060         gtk_table_attach( GTK_TABLE( table ), psf, 1, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 0, 0);
2061         gtk_widget_show( psf );
2062
2063         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 1,
2064                 _("Sigma:"), 185, 75,
2065                 parameters.sigma_psf, 0.1, 10., 0.1, 5, 3,
2066                 TRUE, 0, 0, _("Sigma of gauss function in px"), NULL );
2067         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2068                 &parameters.sigma_psf );
2069         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2070
2071         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 2,
2072                 _("Stars with diffraction lines:"), 185, 75,
2073                 parameters.diffraction_percentage, 0.0, 100.0, 0.01, 5, 2,
2074                 TRUE, 0, 0, _("Percentage of stars that have diffraction lines"), NULL );
2075         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2076                 &parameters.diffraction_percentage );
2077         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( find_star_norm ), NULL );
2078         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2079
2080         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 3,
2081                 _("Diffraction angle:"), 185, 75,
2082                 parameters.diffraction_angle, 0.0, 90., 0.1, 5, 1,
2083                 TRUE, 0, 0, _("Angle of diffraction lines in degrees"), NULL );
2084         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2085                 &parameters.diffraction_angle );
2086         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2087
2088         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 4,
2089                 _("Diffraction length:"), 185, 75,
2090                 parameters.diffraction_length, 0.0, 10.0, 0.1, 5, 1,
2091                 TRUE, 0, 0, _("Length of diffraction lines"), NULL );
2092         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2093                 &parameters.diffraction_length );
2094         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2095
2096         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 5,
2097                 _("Diffraction color:"), 185, 75,
2098                 parameters.diffraction_color, 0.0, 2.0, 0.1, 5, 1,
2099                 TRUE, 0, 0, _("Diffraction lines usually show a color variation"), NULL );
2100         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2101                 &parameters.diffraction_color );
2102         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2103
2104         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 6,
2105                 _("Noise:"), 185, 75,
2106                 parameters.noise, 0, 200, 1, 5, 0,
2107                 TRUE, 0, 0, _("Noise in % of sqrt(N) = photon noise"), NULL );
2108         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_int_adjustment_update ),
2109                 &parameters.noise );
2110         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2111
2112         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 7,
2113                 _("Background:"), 185, 75,
2114                 parameters.background, 0, 100, 1, 5, 0,
2115                 TRUE, 0, 0, _("Background pixel value offset"), NULL );
2116         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_int_adjustment_update ),
2117                 &parameters.background );
2118         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2119
2120         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 8,
2121                 _("Burn out:"), 185, 75,
2122                 parameters.burnout, 0.00, 100.00, 0.01, 5, 2,
2123                 TRUE, 0, 0, _("% of stars that burn out (0=normalize to brightest star, 100=to darkest one)"), NULL );
2124         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2125                 &parameters.burnout );
2126         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( find_star_norm ), NULL );
2127         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2128
2129         adj = gimp_scale_entry_new( GTK_TABLE( table ), 0, 9,
2130                 _("Shininess:"), 185, 75,
2131                 parameters.shininess, 0.0, 2.0, 0.1, 5, 1,
2132                 TRUE, 0, 0, _("Burnt out stars have larger sigma"), NULL );
2133         g_signal_connect( adj, "value_changed", G_CALLBACK( gimp_double_adjustment_update ),
2134                 &parameters.shininess );
2135         g_signal_connect_swapped( adj, "value_changed", G_CALLBACK( gimp_preview_invalidate ), preview );
2136
2137         check_box = gtk_check_button_new_with_label( _("Split foreground, object and background to layers") );
2138         gtk_table_attach_defaults( GTK_TABLE( table ), check_box, 0, 2, 10, 11 );
2139         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check_box ), parameters.split_layers );
2140         g_signal_connect( check_box, "toggled", G_CALLBACK( split_layers_toggled ), NULL );
2141         g_signal_connect_swapped( check_box, "toggled", G_CALLBACK( gimp_preview_invalidate ), preview );
2142         gtk_widget_show( check_box );
2143
2144         check_box = gtk_check_button_new_with_label( _("Create an illumination mask") );
2145         gtk_table_attach_defaults( GTK_TABLE( table ), check_box, 0, 2, 11, 12 );
2146         gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( check_box ), parameters.object_mask );
2147         g_signal_connect( check_box, "toggled", G_CALLBACK( object_mask_toggled ), NULL );
2148         g_signal_connect_swapped( check_box, "toggled", G_CALLBACK( gimp_preview_invalidate ), preview );
2149 /*      gtk_widget_show( check_box ); */
2150
2151
2152         gtk_widget_show( left_vbox );
2153         gtk_widget_show( right_vbox );
2154         gtk_widget_show( main_hbox );
2155         gtk_widget_show( dlg );
2156
2157         gboolean run = ( gimp_dialog_run( GIMP_DIALOG( dlg ) ) == GTK_RESPONSE_OK );
2158
2159         gtk_widget_destroy( dlg );
2160
2161         return run;
2162 }