gimp/plug-ins/gimpressionist/repaint.c

922 lines
26 KiB
C
Raw Normal View History

1999-08-26 22:29:37 +00:00
#include "config.h"
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-25 17:46:56 +00:00
1999-08-26 22:29:37 +00:00
#include <stdlib.h>
#include <string.h>
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-25 17:46:56 +00:00
1999-08-26 22:29:37 +00:00
#include <gtk/gtk.h>
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-25 17:46:56 +00:00
1999-08-26 22:29:37 +00:00
#include <libgimp/gimp.h>
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-25 17:46:56 +00:00
#include "gimpressionist.h"
#include "brush.h"
#include "orientation.h"
#include "placement.h"
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-25 17:46:56 +00:00
#include "ppmtool.h"
#include "preview.h"
#include "random.h"
#include "size.h"
#include "infile.h"
configure.in po-plug-ins/POTFILES.in plug-ins/common/Makefile.am 2000-01-25 Michael Natterer <mitch@gimp.org> * configure.in * po-plug-ins/POTFILES.in * plug-ins/common/Makefile.am * plug-ins/common/plugin-defs.pl * plug-ins/megawidget/*: removed. (There were only 3 functions left which were used by ~5 plugins, so I moved the resp. functions to the plugins). More preview stuff to come... * app/airbrush_blob.c * modules/colorsel_triangle.c * modules/colorsel_water.c: use G_PI instead of M_PI. * app/procedural_db.h * libgimp/gimpenums.h * plug-ins/script-fu/script-fu-constants.c * tools/pdbgen/enums.pl: new PDB return value STATUS_CANCEL which indicates that "Cancel" was pressed in a plugin dialog. (Useful only for file load/save plugins). * app/fileops.[ch] * app/menus.c: changes to handle STATUS_CANCEL correctly. Did some code cleanup in fileops.[ch]. Pop up a warning if File->Save failed. * app/plug_in.c: return_val[0] is of type PDB_STATUS, not PDB_INT32. * libgimp/gimpmath.h: new constant G_MAXRAND which equals to RAND_MAX if it exists or to G_MAXINT otherwise. * libgimp/gimpwidgets.[ch]: new function gimp_random_seed_new() which creates a spinbutton and a "Time" toggle. Call the function which does the "set_sensitive" magic from the radio button callback. * plug-ins/[75 plugins]: - Return STATUS_CANCEL in all file load/save dialogs if "Cancel" was pressed. - Standardized the file plugins' "run" functions. - Use G_PI and G_MAXRAND everywhere. - Added tons of scales and spinbuttons instead of text entries. - Applied uniform packing/spacings all over the place. - Reorganized some UIs (stuff like moving the preview to the top left corner of the dialog). - Removed many ui helper functions and callbacks and use the stuff from libgimp instead. - I tried not to restrict the range of possible values when I replaced entries with spinbuttons/scales but may have failed, though in some cases. Please test ;-) - #include <libgimp/gimpmath.h> where appropriate and use it's constants. - Indentation, s/int/gint/ et.al., code cleanup. RFC: The plugins are definitely not useable with GIMP 1.0 any more, so shouldn't we remove all the remaining compatibility stuff ??? (like "#ifdef GIMP_HAVE_PARASITES")
2000-01-25 17:46:56 +00:00
#include <libgimp/stdplugins-intl.h>
1999-08-26 22:29:37 +00:00
static gimpressionist_vals_t runningvals;
1999-08-26 22:29:37 +00:00
static double get_siz_from_pcvals(double x, double y)
{
return getsiz_proto(x,y, pcvals.num_size_vectors, pcvals.size_vectors,
pcvals.size_strength_exponent, pcvals.size_voronoi);
}
static int get_pixel_value (double dir)
{
while(dir < 0.0) dir += 360.0;
while(dir >= 360.0) dir -= 360.0;
return dir * 255.0 / 360.0;
}
static void prepare_brush (ppm_t *p)
1999-08-26 22:29:37 +00:00
{
int x, y;
1999-08-29 21:06:26 +00:00
int rowstride = p->width * 3;
1999-08-26 22:29:37 +00:00
for (y = 0; y< p->height; y++) {
for (x = 0; x < p->width; x++) {
1999-08-29 21:06:26 +00:00
p->col[y*rowstride+x*3+1] = 0;
1999-08-26 22:29:37 +00:00
}
}
for (y = 1; y< p->height; y++) {
for (x = 1; x < p->width; x++) {
1999-08-29 21:06:26 +00:00
int v = p->col[y*rowstride+x*3] - p->col[(y-1)*rowstride+(x-1)*3];
1999-08-26 22:29:37 +00:00
if(v < 0) v = 0;
1999-08-29 21:06:26 +00:00
p->col[y*rowstride+x*3+1] = v;
1999-08-26 22:29:37 +00:00
}
}
}
static double sum_brush (ppm_t *p)
1999-08-26 22:29:37 +00:00
{
double sum = 0;
1999-08-29 21:06:26 +00:00
int i;
for(i = 0; i < p->width*3*p->height; i += 3)
sum += p->col[i];
1999-08-26 22:29:37 +00:00
return sum;
}
/* TODO : Use r = rgb[0]; g = rgb[1] ; b = rgb[2]; instead of
* the direct references here.
* */
static int get_hue (guchar *rgb)
1999-08-26 22:29:37 +00:00
{
double h, v, temp, diff;
/* TODO : There seems to be some typoes in the comments here.
* Ask vidar what he meant.
* */
1999-08-29 21:06:26 +00:00
if((rgb[0] == rgb[1]) && (rgb[0] == rgb[2])) /* Gray */
1999-08-26 22:29:37 +00:00
return 0;
1999-08-29 21:06:26 +00:00
v = (rgb[0] > rgb[1] ? rgb[0] : rgb[1]); /* v = st<F8>rste verdi */
if(rgb[2] > v) v = rgb[2];
temp = (rgb[0] > rgb[1] ? rgb[1] : rgb[0] ); /* temp = minste */
if(rgb[2] < temp) temp = rgb[2];
1999-08-26 22:29:37 +00:00
diff = v - temp;
1999-08-29 21:06:26 +00:00
if(v == rgb[0])
h = ((double)rgb[1] - rgb[2]) / diff;
else if(v == rgb[1])
h = ((double)rgb[2] - rgb[0]) / diff + 2;
else /* v == rgb[2] */
h = ((double)rgb[0] - rgb[1]) / diff + 4;
1999-08-26 22:29:37 +00:00
if(h < 0) h += 6;
return h * 255.0 / 6.0;
}
static int choose_best_brush (ppm_t *p, ppm_t *a, int tx, int ty,
ppm_t *brushes, int num_brushes,
double *brushes_sum, int start, int step)
1999-08-26 22:29:37 +00:00
{
double dev, thissum;
double bestdev = 0.0;
double r, g, b;
int best = -1;
int x, y, h;
long i;
GList *brlist = NULL;
for(i = start; i < num_brushes; i += step) {
ppm_t *brush = &brushes[i];
#if 0
thissum = 0.0;
#endif
thissum = brushes_sum[i];
1999-08-26 22:29:37 +00:00
/* TODO: Pointer-arithmeticize this code */
1999-08-26 22:29:37 +00:00
r = g = b = 0.0;
for(y = 0; y < brush->height; y++) {
1999-08-29 21:06:26 +00:00
guchar *row = p->col + (ty+y)*p->width*3;
1999-08-26 22:29:37 +00:00
for(x = 0; x < brush->width; x++) {
int k = (tx+x)*3;
double v;
if((h = brush->col[(y*brush->width*3)+x*3])) {
#if 0
thissum += h;
#endif
v = h / 255.0;
r += row[k+0] * v;
g += row[k+1] * v;
b += row[k+2] * v;
}
1999-08-26 22:29:37 +00:00
}
}
r = r * 255.0 / thissum;
g = g * 255.0 / thissum;
b = b * 255.0 / thissum;
dev = 0.0;
for(y = 0; y < brush->height; y++) {
1999-08-29 21:06:26 +00:00
guchar *row = p->col + (ty+y)*p->width*3;
1999-08-26 22:29:37 +00:00
for(x = 0; x < brush->width; x++) {
int k = (tx+x)*3;
double v;
if((h = brush->col[(y*brush->width*3)+x*3])) {
v = h / 255.0;
dev += abs(row[k+0] - r) * v;
dev += abs(row[k+1] - g) * v;
dev += abs(row[k+2] - b) * v;
if(img_has_alpha)
dev += a->col[(ty+y)*a->width*3+(tx+x)*3] * v;
}
1999-08-26 22:29:37 +00:00
}
}
dev /= thissum;
if((best == -1) || (dev < bestdev)) {
if(brlist)
g_list_free(brlist);
1999-08-26 22:29:37 +00:00
brlist = NULL;
}
if(dev <= bestdev || best < 0) {
1999-08-26 22:29:37 +00:00
best = i;
bestdev = dev;
brlist = g_list_append(brlist, (void *)i);
}
if(dev < runningvals.devthresh) break;
}
if(!brlist) {
g_printerr("What!? No brushes?!\n");
1999-08-26 22:29:37 +00:00
return 0;
}
i = g_rand_int_range (random_generator, 0, g_list_length(brlist));
1999-08-26 22:29:37 +00:00
best = (long)((g_list_nth(brlist,i))->data);
g_list_free(brlist);
return best;
}
static void apply_brush (ppm_t *brush,
ppm_t *shadow,
ppm_t *p, ppm_t *a,
int tx, int ty, int r, int g, int b)
1999-08-26 22:29:37 +00:00
{
ppm_t tmp;
ppm_t atmp;
1999-08-26 22:29:37 +00:00
double v, h;
int x, y;
double edgedarken = 1.0 - runningvals.general_dark_edge;
double relief = runningvals.brush_relief / 100.0;
int shadowdepth = pcvals.general_shadow_depth;
int shadowblur = pcvals.general_shadow_blur;
1999-08-26 22:29:37 +00:00
tmp = *p;
if(img_has_alpha)
atmp = *a;
1999-08-26 22:29:37 +00:00
if (shadow) {
1999-08-26 22:29:37 +00:00
int sx = tx + shadowdepth - shadowblur*2;
int sy = ty + shadowdepth - shadowblur*2;
for(y = 0; y < shadow->height; y++) {
1999-08-29 21:06:26 +00:00
guchar *row, *arow = NULL;
1999-08-26 22:29:37 +00:00
if((sy + y) < 0) continue;
if((sy + y) >= tmp.height) break;
1999-08-29 21:06:26 +00:00
row = tmp.col + (sy+y) * tmp.width * 3;
if(img_has_alpha) arow = atmp.col + (sy+y) * atmp.width * 3;
1999-08-26 22:29:37 +00:00
for(x = 0; x < shadow->width; x++) {
int k = (sx + x) * 3;
if((sx + x) < 0) continue;
if((sx + x) >= tmp.width) break;
h = shadow->col[y*shadow->width*3+x*3+2];
if(!h) continue;
v = 1.0 - (h / 255.0 * runningvals.general_shadow_darkness / 100.0);
row[k+0] *= v;
row[k+1] *= v;
row[k+2] *= v;
if(img_has_alpha) arow[k] *= v;
1999-08-26 22:29:37 +00:00
}
}
}
for(y = 0; y < brush->height; y++) {
1999-08-29 21:06:26 +00:00
guchar *row = tmp.col + (ty+y)*tmp.width*3;
guchar *arow = NULL;
if(img_has_alpha) arow = atmp.col + (ty+y)*atmp.width*3;
1999-08-26 22:29:37 +00:00
for(x = 0; x < brush->width; x++) {
1999-08-29 21:06:26 +00:00
int k = (tx + x) * 3;
h = brush->col[y*brush->width*3+x*3];
1999-08-26 22:29:37 +00:00
if(!h) continue;
if(runningvals.color_brushes) {
v = 1.0 - brush->col[y*brush->width*3+x*3+2] / 255.0;
row[k+0] *= v;
row[k+1] *= v;
row[k+2] *= v;
if(img_has_alpha) arow[(tx+x)*3] *= v;
1999-08-26 22:29:37 +00:00
}
v = (1.0 - h / 255.0) * edgedarken;
1999-08-29 21:06:26 +00:00
row[k+0] *= v;
row[k+1] *= v;
row[k+2] *= v;
if(img_has_alpha) arow[k] *= v;
1999-08-26 22:29:37 +00:00
v = h / 255.0;
1999-08-29 21:06:26 +00:00
row[k+0] += r * v;
row[k+1] += g * v;
row[k+2] += b * v;
1999-08-26 22:29:37 +00:00
}
}
if(relief > 0.001) {
for(y = 1; y < brush->height; y++) {
1999-08-29 21:06:26 +00:00
guchar *row = tmp.col + (ty+y)*tmp.width*3;
1999-08-26 22:29:37 +00:00
for(x = 1; x < brush->width; x++) {
int k = (tx + x) * 3;
h = brush->col[y*brush->width*3+x*3+1] * relief;
if(h < 0.001) continue;
if(h > 255) h = 255;
row[k+0] = (row[k+0] * (255-h) + 255 * h) / 255;
row[k+1] = (row[k+1] * (255-h) + 255 * h) / 255;
row[k+2] = (row[k+2] * (255-h) + 255 * h) / 255;
1999-08-26 22:29:37 +00:00
}
}
}
}
void repaint(ppm_t *p, ppm_t *a)
1999-08-26 22:29:37 +00:00
{
int x, y;
int tx = 0, ty = 0;
ppm_t tmp = {0,0,NULL};
ppm_t atmp = {0,0,NULL};
1999-08-26 22:29:37 +00:00
int r, g, b, n, h, i, j, on, sn;
int num_brushes, maxbrushwidth, maxbrushheight;
1999-08-29 21:06:26 +00:00
guchar back[3] = {0,0,0};
ppm_t *brushes, *shadows;
ppm_t *brush, *shadow = NULL;
double *brushes_sum;
1999-08-26 22:29:37 +00:00
int cx, cy, maxdist;
double scale, relief, startangle, anglespan, density, bgamma;
double thissum;
int max_progress;
ppm_t paper_ppm = {0,0,NULL};
ppm_t dirmap = {0,0,NULL};
ppm_t sizmap = {0,0,NULL};
1999-08-26 22:29:37 +00:00
int *xpos = NULL, *ypos = NULL;
int step = 1;
int progstep;
static int running = 0;
int dropshadow = pcvals.general_drop_shadow;
int shadowblur = pcvals.general_shadow_blur;
1999-08-26 22:29:37 +00:00
if (running)
1999-08-26 22:29:37 +00:00
return;
running++;
runningvals = pcvals;
1999-08-26 22:29:37 +00:00
/* Shouldn't be necessary, but... */
if(img_has_alpha)
if((p->width != a->width) || (p->height != a->height)) {
g_printerr("Huh? Image size != alpha size?\n");
1999-08-26 22:29:37 +00:00
return;
}
num_brushes = runningvals.orient_num * runningvals.size_num;
startangle = runningvals.orient_first;
anglespan = runningvals.orient_last;
1999-08-26 22:29:37 +00:00
density = runningvals.brush_density;
1999-08-26 22:29:37 +00:00
if(runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST)
density /= 3.0;
1999-08-26 22:29:37 +00:00
bgamma = runningvals.brushgamma;
brushes = g_malloc (num_brushes * sizeof(ppm_t));
brushes_sum = g_malloc (num_brushes * sizeof(double));
1999-08-26 22:29:37 +00:00
if(dropshadow)
shadows = g_malloc (num_brushes * sizeof(ppm_t));
1999-08-26 22:29:37 +00:00
else
shadows = NULL;
brushes[0].col = NULL;
brush_get_selected (&brushes[0]);
1999-08-26 22:29:37 +00:00
resize(&brushes[0], brushes[0].width, brushes[0].height * pow(10,runningvals.brush_aspect));
scale = runningvals.size_last / MAX(brushes[0].width, brushes[0].height);
1999-08-26 22:29:37 +00:00
if(bgamma != 1.0)
ppm_apply_gamma(&brushes[0], 1.0/bgamma, 1,1,1);
1999-08-26 22:29:37 +00:00
resize(&brushes[0], brushes[0].width * scale, brushes[0].height * scale);
i = 1 + sqrt(brushes[0].width * brushes[0].width +
brushes[0].height * brushes[0].height);
ppm_pad(&brushes[0], i-brushes[0].width, i-brushes[0].width,
1999-08-29 21:06:26 +00:00
i-brushes[0].height, i-brushes[0].height, back);
for(i = 1; i < num_brushes; i++) {
1999-08-26 22:29:37 +00:00
brushes[i].col = NULL;
ppm_copy(&brushes[0], &brushes[i]);
1999-08-26 22:29:37 +00:00
}
for(i = 0; i < runningvals.size_num; i++) {
1999-08-26 22:29:37 +00:00
double sv;
if(runningvals.size_num > 1)
sv = i / (runningvals.size_num - 1.0);
1999-08-26 22:29:37 +00:00
else sv = 1.0;
for(j = 0; j < runningvals.orient_num; j++) {
h = j + i * runningvals.orient_num;
free_rotate(&brushes[h],
startangle + j * anglespan / runningvals.orient_num);
rescale(&brushes[h], (sv * runningvals.size_first + (1.0-sv) * runningvals.size_last) / runningvals.size_last);
1999-08-26 22:29:37 +00:00
autocrop(&brushes[h],1);
}
1999-08-26 22:29:37 +00:00
}
/* Brush-debugging */
#if 0
for(i = 0; i < num_brushes; i++) {
1999-08-26 22:29:37 +00:00
char tmp[1000];
g_snprintf (tmp, sizeof (tmp), "/tmp/_brush%03d.ppm", i);
ppm_save(&brushes[i], tmp);
1999-08-26 22:29:37 +00:00
}
#endif
1999-08-26 22:29:37 +00:00
for(i = 0; i < num_brushes; i++) {
if(!runningvals.color_brushes)
prepare_brush(&brushes[i]);
brushes_sum[i] = sum_brush(&brushes[i]);
1999-08-26 22:29:37 +00:00
}
brush = &brushes[0];
thissum = brushes_sum[0];
1999-08-26 22:29:37 +00:00
maxbrushwidth = maxbrushheight = 0;
for(i = 0; i < num_brushes; i++) {
1999-08-26 22:29:37 +00:00
if(brushes[i].width > maxbrushwidth) maxbrushwidth = brushes[i].width;
if(brushes[i].height > maxbrushheight) maxbrushheight = brushes[i].height;
}
for(i = 0; i < num_brushes; i++) {
1999-08-26 22:29:37 +00:00
int xp, yp;
1999-08-29 21:06:26 +00:00
guchar blk[3] = {0,0,0};
1999-08-26 22:29:37 +00:00
xp = maxbrushwidth - brushes[i].width;
yp = maxbrushheight - brushes[i].height;
if(xp || yp)
ppm_pad(&brushes[i], xp/2, xp-xp/2, yp/2, yp-yp/2, blk);
1999-08-26 22:29:37 +00:00
}
if(dropshadow) {
for(i = 0; i < num_brushes; i++) {
1999-08-26 22:29:37 +00:00
shadows[i].col = NULL;
ppm_copy(&brushes[i], &shadows[i]);
ppm_apply_gamma(&shadows[i], 0, 1,1,0);
ppm_pad(&shadows[i], shadowblur*2, shadowblur*2,
shadowblur*2, shadowblur*2, back);
1999-08-26 22:29:37 +00:00
for(j = 0; j < shadowblur; j++)
blur(&shadows[i], 2, 2);
#if 0
autocrop(&shadows[i],1);
#endif
1999-08-26 22:29:37 +00:00
}
#if 0
1999-08-26 22:29:37 +00:00
maxbrushwidth += shadowdepth*3;
maxbrushheight += shadowdepth*3;
#endif
1999-08-26 22:29:37 +00:00
}
1999-08-26 22:29:37 +00:00
/* For extra annoying debugging :-) */
#if 0
ppm_save(brushes, "/tmp/__brush.ppm");
if(shadows) ppm_save(shadows, "/tmp/__shadow.ppm");
1999-08-26 22:29:37 +00:00
system("xv /tmp/__brush.ppm & xv /tmp/__shadow.ppm & ");
#endif
1999-08-26 22:29:37 +00:00
if(runningvals.general_paint_edges) {
1999-08-26 22:29:37 +00:00
edgepad(p, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
if(img_has_alpha)
edgepad(a, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
}
if(img_has_alpha) {
/* Initially fully transparent */
if(runningvals.general_background_type == BG_TYPE_TRANSPARENT) {
1999-08-29 21:06:26 +00:00
guchar tmpcol[3] = {255,255,255};
ppm_new(&atmp, a->width, a->height);
1999-08-29 21:06:26 +00:00
fill(&atmp, tmpcol);
1999-08-26 22:29:37 +00:00
} else {
ppm_copy(a, &atmp);
1999-08-26 22:29:37 +00:00
}
}
if(runningvals.general_background_type == BG_TYPE_SOLID) {
1999-08-29 21:06:26 +00:00
guchar tmpcol[3];
ppm_new(&tmp, p->width, p->height);
gimp_rgb_get_uchar(&runningvals.color, &tmpcol[0], &tmpcol[1], &tmpcol[2]);
1999-08-29 21:06:26 +00:00
fill(&tmp, tmpcol);
} else if(runningvals.general_background_type == BG_TYPE_KEEP_ORIGINAL) {
ppm_copy(p, &tmp);
1999-08-26 22:29:37 +00:00
} else {
scale = runningvals.paper_scale / 100.0;
ppm_new(&tmp, p->width, p->height);
ppm_load(runningvals.selected_paper, &paper_ppm);
resize(&paper_ppm, paper_ppm.width * scale, paper_ppm.height * scale);
if(runningvals.paper_invert)
ppm_apply_gamma(&paper_ppm, -1.0, 1, 1, 1);
1999-08-26 22:29:37 +00:00
for(x = 0; x < tmp.width; x++) {
int rx = x % paper_ppm.width;
1999-08-26 22:29:37 +00:00
for(y = 0; y < tmp.height; y++) {
int ry = y % paper_ppm.height;
memcpy(&tmp.col[y*tmp.width*3+x*3], &paper_ppm.col[ry*paper_ppm.width*3+rx*3], 3);
1999-08-26 22:29:37 +00:00
}
}
}
cx = p->width / 2;
cy = p->height / 2;
maxdist = sqrt(cx*cx+cy*cy);
switch(runningvals.orient_type)
{
case ORIENTATION_VALUE:
ppm_new(&dirmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < dirmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &dirmap.col[y*dirmap.width*3];
guchar *srcrow = &p->col[y*p->width*3];
1999-08-26 22:29:37 +00:00
for(x = 0; x < dirmap.width; x++) {
dstrow[x*3] = (srcrow[x*3] + srcrow[x*3+1] + srcrow[x*3+2]) / 3;
1999-08-26 22:29:37 +00:00
}
}
break;
case ORIENTATION_RADIUS:
ppm_new(&dirmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < dirmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &dirmap.col[y*dirmap.width*3];
1999-08-26 22:29:37 +00:00
double ysqr = (cy-y)*(cy-y);
for(x = 0; x < dirmap.width; x++) {
dstrow[x*3] = sqrt((cx-x)*(cx-x)+ysqr) * 255 / maxdist;
1999-08-26 22:29:37 +00:00
}
}
break;
case ORIENTATION_RADIAL:
ppm_new(&dirmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < dirmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &dirmap.col[y*dirmap.width*3];
1999-08-26 22:29:37 +00:00
for(x = 0; x < dirmap.width; x++) {
dstrow[x*3] = (G_PI + atan2(cy-y, cx-x)) * 255.0 / (G_PI*2);
1999-08-26 22:29:37 +00:00
}
}
break;
case ORIENTATION_FLOWING:
ppm_new(&dirmap, p->width / 6 + 5, p->height / 6 + 5);
1999-08-26 22:29:37 +00:00
mkgrayplasma(&dirmap, 15);
blur(&dirmap, 2, 2);
blur(&dirmap, 2, 2);
resize(&dirmap, p->width, p->height);
blur(&dirmap, 2, 2);
if(runningvals.general_paint_edges)
1999-08-26 22:29:37 +00:00
edgepad(&dirmap, maxbrushwidth, maxbrushheight,maxbrushwidth, maxbrushheight);
break;
case ORIENTATION_HUE:
ppm_new(&dirmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < dirmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &dirmap.col[y*dirmap.width*3];
guchar *srcrow = &p->col[y*p->width*3];
1999-08-26 22:29:37 +00:00
for(x = 0; x < dirmap.width; x++) {
dstrow[x*3] = get_hue(&srcrow[x*3]);
1999-08-26 22:29:37 +00:00
}
}
break;
case ORIENTATION_ADAPTIVE:
{
guchar tmpcol[3] = {0,0,0};
ppm_new(&dirmap, p->width, p->height);
fill(&dirmap, tmpcol);
}
break;
case ORIENTATION_MANUAL:
ppm_new(&dirmap, p->width-maxbrushwidth*2, p->height-maxbrushheight*2);
1999-08-26 22:29:37 +00:00
for(y = 0; y < dirmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &dirmap.col[y*dirmap.width*3];
1999-08-26 22:29:37 +00:00
double tmpy = y / (double)dirmap.height;
for(x = 0; x < dirmap.width; x++) {
dstrow[x*3] = get_pixel_value(90-get_direction(x / (double)dirmap.width, tmpy, 1));
1999-08-26 22:29:37 +00:00
}
}
edgepad(&dirmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
break;
1999-08-26 22:29:37 +00:00
}
if(runningvals.size_type == SIZE_TYPE_VALUE)
{
ppm_new(&sizmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < sizmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &sizmap.col[y*sizmap.width*3];
guchar *srcrow = &p->col[y*p->width*3];
1999-08-26 22:29:37 +00:00
for(x = 0; x < sizmap.width; x++) {
dstrow[x*3] = (srcrow[x*3] + srcrow[x*3+1] + srcrow[x*3+2]) / 3;
1999-08-26 22:29:37 +00:00
}
}
}
else if(runningvals.size_type == SIZE_TYPE_RADIUS)
{
ppm_new(&sizmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < sizmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &sizmap.col[y*sizmap.width*3];
1999-08-26 22:29:37 +00:00
double ysqr = (cy-y)*(cy-y);
for(x = 0; x < sizmap.width; x++) {
dstrow[x*3] = sqrt((cx-x)*(cx-x)+ysqr) * 255 / maxdist;
1999-08-26 22:29:37 +00:00
}
}
}
else if(runningvals.size_type == SIZE_TYPE_RADIAL)
{
ppm_new(&sizmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < sizmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &sizmap.col[y*sizmap.width*3];
1999-08-26 22:29:37 +00:00
for(x = 0; x < sizmap.width; x++) {
dstrow[x*3] = (G_PI + atan2(cy-y, cx-x)) * 255.0 / (G_PI*2);
1999-08-26 22:29:37 +00:00
}
}
}
else if(runningvals.size_type == SIZE_TYPE_FLOWING)
{
ppm_new(&sizmap, p->width / 6 + 5, p->height / 6 + 5);
1999-08-26 22:29:37 +00:00
mkgrayplasma(&sizmap, 15);
blur(&sizmap, 2, 2);
blur(&sizmap, 2, 2);
resize(&sizmap, p->width, p->height);
blur(&sizmap, 2, 2);
if(runningvals.general_paint_edges)
1999-08-26 22:29:37 +00:00
edgepad(&sizmap, maxbrushwidth, maxbrushheight,maxbrushwidth, maxbrushheight);
}
else if(runningvals.size_type == SIZE_TYPE_HUE)
{
ppm_new(&sizmap, p->width, p->height);
1999-08-26 22:29:37 +00:00
for(y = 0; y < sizmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &sizmap.col[y*sizmap.width*3];
guchar *srcrow = &p->col[y*p->width*3];
1999-08-26 22:29:37 +00:00
for(x = 0; x < sizmap.width; x++) {
dstrow[x*3] = get_hue(&srcrow[x*3]);
1999-08-26 22:29:37 +00:00
}
}
}
else if(runningvals.size_type == SIZE_TYPE_ADAPTIVE)
{
1999-08-29 21:06:26 +00:00
guchar tmpcol[3] = {0,0,0};
ppm_new(&sizmap, p->width, p->height);
1999-08-29 21:06:26 +00:00
fill(&sizmap, tmpcol);
1999-08-26 22:29:37 +00:00
}
else if(runningvals.size_type == SIZE_TYPE_MANUAL)
{
ppm_new(&sizmap, p->width-maxbrushwidth*2, p->height-maxbrushheight*2);
1999-08-26 22:29:37 +00:00
for(y = 0; y < sizmap.height; y++) {
1999-08-29 21:06:26 +00:00
guchar *dstrow = &sizmap.col[y*sizmap.width*3];
1999-08-26 22:29:37 +00:00
double tmpy = y / (double)sizmap.height;
for(x = 0; x < sizmap.width; x++) {
dstrow[x*3] = 255 * (1.0 - get_siz_from_pcvals(x / (double)sizmap.width, tmpy));
1999-08-26 22:29:37 +00:00
}
}
edgepad(&sizmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight);
}
#if 0
ppm_save(&sizmap, "/tmp/_sizmap.ppm");
#endif
if(runningvals.place_type == PLACEMENT_TYPE_RANDOM) {
1999-08-26 22:29:37 +00:00
i = tmp.width * tmp.height / (maxbrushwidth * maxbrushheight);
i *= density;
} else if(runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) {
1999-08-26 22:29:37 +00:00
i = (int)(tmp.width * density / maxbrushwidth) *
(int)(tmp.height * density / maxbrushheight);
step = i;
#if 0
g_printerr("step=%d i=%d\n", step, i);
#endif
1999-08-26 22:29:37 +00:00
}
if(i < 1) i = 1;
max_progress = i;
progstep = max_progress / 30;
if(progstep < 10) progstep = 10;
if(runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) {
1999-08-26 22:29:37 +00:00
int j;
xpos = g_new (int, i);
ypos = g_new (int, i);
1999-08-26 22:29:37 +00:00
for(j = 0; j < i; j++) {
int factor = (int)(tmp.width * density / maxbrushwidth + 0.5);
if(factor < 1) factor = 1;
xpos[j] = maxbrushwidth/2 + (j % factor) * maxbrushwidth / density;
ypos[j] = maxbrushheight/2 + (j / factor) * maxbrushheight / density;
}
for(j = 0; j < i; j++) {
int a, b;
a = g_rand_int_range (random_generator, 0, i);
1999-08-26 22:29:37 +00:00
b = xpos[j]; xpos[j] = xpos[a]; xpos[a] = b;
b = ypos[j]; ypos[j] = ypos[a]; ypos[a] = b;
}
}
for(; i; i--) {
if(i % progstep == 0) {
if(runningvals.run) {
removed our own action_area API and use GtkDialog's one. Create all 2003-11-06 Michael Natterer <mitch@gimp.org> * libgimpwidgets/gimpdialog.[ch]: removed our own action_area API and use GtkDialog's one. Create all dialogs without separator. Changed almost everything else too. Fixes bug #125143. * libgimpwidgets/gimpquerybox.c * libgimpwidgets/gimpunitmenu.c: changed accordingly. * libgimp/gimpexport.[ch]: ditto. Renamed enum GimpExportReturnType to GimpExportReturn. * libgimp/gimpcompat.h: added a #define for the old name. * themes/Default/gtkrc: increased action_area border to 6 pixels. * app/display/gimpdisplayshell-filter-dialog.c * app/display/gimpdisplayshell-scale.c * app/display/gimpprogress.c * app/gui/brush-select.c * app/gui/channels-commands.c * app/gui/color-notebook.c * app/gui/convert-dialog.c * app/gui/file-new-dialog.c * app/gui/font-select.c * app/gui/gradient-editor-commands.c * app/gui/gradient-select.c * app/gui/grid-dialog.c * app/gui/image-commands.c * app/gui/info-window.c * app/gui/layers-commands.c * app/gui/module-browser.c * app/gui/offset-dialog.c * app/gui/palette-import-dialog.c * app/gui/palette-select.c * app/gui/pattern-select.c * app/gui/preferences-dialog.c * app/gui/qmask-commands.c * app/gui/resize-dialog.c * app/gui/resolution-calibrate-dialog.c * app/gui/stroke-dialog.c * app/gui/templates-commands.c * app/gui/user-install-dialog.c * app/gui/vectors-commands.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpimagemaptool.c * app/tools/gimpmeasuretool.c * app/tools/gimptransformtool.c * app/widgets/gimptexteditor.c * app/widgets/gimptooldialog.[ch] * app/widgets/gimpviewabledialog.[ch] * app/widgets/gimpwidgets-utils.c: changed accordingly and increased the dialogs' outer borders to 6 pixels all over the place. * plug-ins/*/*.c: changed accordingly. The plug-ins may be arbitrarily broken, I tested none of them.
2003-11-06 15:27:05 +00:00
gimp_progress_update(0.8 - 0.8*((double)i / max_progress));
1999-08-26 22:29:37 +00:00
} else {
char tmps[40];
g_snprintf (tmps, sizeof (tmps),
"%.1f %%", 100 * (1.0 - ((double)i / max_progress)));
preview_set_button_label (tmps);
while(gtk_events_pending())
gtk_main_iteration();
1999-08-26 22:29:37 +00:00
}
}
if(runningvals.place_type == PLACEMENT_TYPE_RANDOM) {
tx = g_rand_int_range (random_generator, maxbrushwidth/2,
configure.in app/core/gimpbrushpipe.c app/gui/about-dialog.c 2002-11-20 Dave Neary <bolsh@gimp.org> * configure.in * app/core/gimpbrushpipe.c * app/gui/about-dialog.c * app/paint-funcs/paint-funcs-generic.h * app/paint-funcs/paint-funcs.c * libgimpmath/gimpmath.h * libgimpwidgets/gimpwidgets.c * plug-ins/common/CML_explorer.c * plug-ins/common/blur.c * plug-ins/common/cubism.c * plug-ins/common/gee.c * plug-ins/common/gee_zoom.c * plug-ins/common/gqbist.c * plug-ins/common/jigsaw.c * plug-ins/common/lic.c * plug-ins/common/noisify.c * plug-ins/common/nova.c * plug-ins/common/papertile.c * plug-ins/common/plasma.c * plug-ins/common/randomize.c * plug-ins/common/sample_colorize.c * plug-ins/common/scatter_hsv.c * plug-ins/common/shift.c * plug-ins/common/sinus.c * plug-ins/common/smooth_palette.c * plug-ins/common/snoise.c * plug-ins/common/sparkle.c * plug-ins/common/spheredesigner.c * plug-ins/common/spread.c * plug-ins/common/warp.c * plug-ins/common/wind.c * plug-ins/flame/cmap.c * plug-ins/flame/flame.c * plug-ins/flame/libifs.c * plug-ins/gflare/gflare.c * plug-ins/gimpressionist/gimpressionist.c * plug-ins/gimpressionist/gimpressionist.h * plug-ins/gimpressionist/plasma.c * plug-ins/gimpressionist/repaint.c * plug-ins/ifscompose/ifscompose_utils.c * plug-ins/maze/algorithms.c * plug-ins/maze/maze.c * plug-ins/maze/maze.h * plug-ins/mosaic/mosaic.c: Change all occurrences of RAND_MAX, G_MAXRAND, rand(), srand(), lrand48(), srand48(), random(), srandom(), RAND_FUNC and SRAND_FUNC to the appropriate g_rand* equivalent. Programs which require seed setting for reproducible results, and anything in the core, gets a dedicated GRand * for the lifetime required. Programs which only ever used random numbers for tossing a coin, rolling a dice, etc use g_random functions. For the rest, judgement was used. Where it was easy, a GRand * object was used and g_rand_* functions were preferred. This fixes bug #67386 in HEAD.
2002-11-20 09:27:48 +00:00
tmp.width - maxbrushwidth/2);
ty = g_rand_int_range (random_generator, maxbrushheight/2,
configure.in app/core/gimpbrushpipe.c app/gui/about-dialog.c 2002-11-20 Dave Neary <bolsh@gimp.org> * configure.in * app/core/gimpbrushpipe.c * app/gui/about-dialog.c * app/paint-funcs/paint-funcs-generic.h * app/paint-funcs/paint-funcs.c * libgimpmath/gimpmath.h * libgimpwidgets/gimpwidgets.c * plug-ins/common/CML_explorer.c * plug-ins/common/blur.c * plug-ins/common/cubism.c * plug-ins/common/gee.c * plug-ins/common/gee_zoom.c * plug-ins/common/gqbist.c * plug-ins/common/jigsaw.c * plug-ins/common/lic.c * plug-ins/common/noisify.c * plug-ins/common/nova.c * plug-ins/common/papertile.c * plug-ins/common/plasma.c * plug-ins/common/randomize.c * plug-ins/common/sample_colorize.c * plug-ins/common/scatter_hsv.c * plug-ins/common/shift.c * plug-ins/common/sinus.c * plug-ins/common/smooth_palette.c * plug-ins/common/snoise.c * plug-ins/common/sparkle.c * plug-ins/common/spheredesigner.c * plug-ins/common/spread.c * plug-ins/common/warp.c * plug-ins/common/wind.c * plug-ins/flame/cmap.c * plug-ins/flame/flame.c * plug-ins/flame/libifs.c * plug-ins/gflare/gflare.c * plug-ins/gimpressionist/gimpressionist.c * plug-ins/gimpressionist/gimpressionist.h * plug-ins/gimpressionist/plasma.c * plug-ins/gimpressionist/repaint.c * plug-ins/ifscompose/ifscompose_utils.c * plug-ins/maze/algorithms.c * plug-ins/maze/maze.c * plug-ins/maze/maze.h * plug-ins/mosaic/mosaic.c: Change all occurrences of RAND_MAX, G_MAXRAND, rand(), srand(), lrand48(), srand48(), random(), srandom(), RAND_FUNC and SRAND_FUNC to the appropriate g_rand* equivalent. Programs which require seed setting for reproducible results, and anything in the core, gets a dedicated GRand * for the lifetime required. Programs which only ever used random numbers for tossing a coin, rolling a dice, etc use g_random functions. For the rest, judgement was used. Where it was easy, a GRand * object was used and g_rand_* functions were preferred. This fixes bug #67386 in HEAD.
2002-11-20 09:27:48 +00:00
tmp.height - maxbrushheight/2);
} else if(runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) {
1999-08-26 22:29:37 +00:00
tx = xpos[i-1];
ty = ypos[i-1];
}
if(runningvals.placement_center) {
double z = g_rand_double_range (random_generator, 0, 0.75);
1999-08-26 22:29:37 +00:00
tx = tx * (1.0-z) + tmp.width/2 * z;
ty = ty * (1.0-z) + tmp.height/2 * z;
}
if((tx < maxbrushwidth/2) || (ty < maxbrushwidth/2) ||
(tx + maxbrushwidth/2 >= p->width) ||
(ty + maxbrushheight/2 >= p->height)) {
#if 0
g_printerr("Internal Error; invalid coords: (%d,%d) i=%d\n", tx, ty, i);
#endif
1999-08-26 22:29:37 +00:00
continue;
}
if(img_has_alpha) {
1999-08-29 21:06:26 +00:00
if(a->col[ty*a->width*3+tx*3] > 128)
continue;
1999-08-26 22:29:37 +00:00
}
n = sn = on = 0;
switch(runningvals.orient_type) {
case ORIENTATION_RANDOM:
on = g_rand_int_range (random_generator, 0, runningvals.orient_num);
1999-08-26 22:29:37 +00:00
break;
case ORIENTATION_VALUE:
case ORIENTATION_RADIUS:
case ORIENTATION_RADIAL:
case ORIENTATION_FLOWING:
case ORIENTATION_HUE:
case ORIENTATION_MANUAL:
on = runningvals.orient_num * dirmap.col[ty*dirmap.width*3+tx*3] / 256;
1999-08-26 22:29:37 +00:00
break;
case ORIENTATION_ADAPTIVE:
1999-08-26 22:29:37 +00:00
break; /* Handled below */
default:
g_printerr("Internal error; Unknown orientationtype\n");
1999-08-26 22:29:37 +00:00
on = 0;
break;
}
switch(runningvals.size_type) {
case SIZE_TYPE_RANDOM:
sn = g_rand_int_range (random_generator, 0, runningvals.size_num);
1999-08-26 22:29:37 +00:00
break;
case SIZE_TYPE_VALUE:
case SIZE_TYPE_RADIUS:
case SIZE_TYPE_RADIAL:
case SIZE_TYPE_FLOWING:
case SIZE_TYPE_HUE:
case SIZE_TYPE_MANUAL:
sn = runningvals.size_num * sizmap.col[ty*sizmap.width*3+tx*3] / 256;
1999-08-26 22:29:37 +00:00
break;
case SIZE_TYPE_ADAPTIVE:
1999-08-26 22:29:37 +00:00
break; /* Handled below */
default:
g_printerr("Internal error; Unknown size_type\n");
1999-08-26 22:29:37 +00:00
sn = 0;
break;
}
/* Handle Adaptive selections */
if (runningvals.orient_type == ORIENTATION_ADAPTIVE)
{
if (runningvals.size_type == SIZE_TYPE_ADAPTIVE)
n = choose_best_brush (p, a, tx-maxbrushwidth/2,
ty-maxbrushheight/2, brushes,
num_brushes, brushes_sum, 0, 1);
else
{
int st = sn * runningvals.orient_num;
n = choose_best_brush (p, a, tx-maxbrushwidth/2,
ty-maxbrushheight/2, brushes,
st+runningvals.orient_num, brushes_sum,
st, 1);
}
}
else
{
if (runningvals.size_type == SIZE_TYPE_ADAPTIVE)
n = choose_best_brush (p, a, tx-maxbrushwidth/2,
ty-maxbrushheight/2, brushes,
num_brushes, brushes_sum,
on, runningvals.orient_num);
else
n = sn * runningvals.orient_num + on;
}
1999-08-26 22:29:37 +00:00
/* Should never happen, but hey... */
if(n < 0) n = 0;
else if(n >= num_brushes) n = num_brushes - 1;
1999-08-26 22:29:37 +00:00
tx -= maxbrushwidth/2;
ty -= maxbrushheight/2;
brush = &brushes[n];
if(dropshadow)
shadow = &shadows[n];
thissum = brushes_sum[n];
1999-08-26 22:29:37 +00:00
/* Calculate color - avg. of in-brush pixels */
if(runningvals.color_type == 0) {
r = g = b = 0;
for(y = 0; y < brush->height; y++) {
guchar *row = &p->col[(ty+y)*p->width*3];
for(x = 0; x < brush->width; x++) {
int k = (tx+x) * 3;
double v;
if((h = brush->col[y*brush->width*3+x*3])) {
v = h / 255.0;
r += row[k+0] * v;
g += row[k+1] * v;
b += row[k+2] * v;
}
}
1999-08-26 22:29:37 +00:00
}
r = r * 255.0 / thissum;
g = g * 255.0 / thissum;
b = b * 255.0 / thissum;
} else if(runningvals.color_type == 1) {
guchar *pixel;
y = ty + (brush->height / 2);
x = tx + (brush->width / 2);
pixel = &p->col[y*p->width*3 + x*3];
r = pixel[0];
g = pixel[1];
b = pixel[2];
} else {
/* No such color_type! */
r = g = b = 0;
}
if(runningvals.color_noise > 0.0) {
double v = runningvals.color_noise;
#define BOUNDS(a) (((a) < 0) ? (a) : ((a) > 255) ? 255 : (a))
#define MYASSIGN(a) \
{ \
a = a + g_rand_double_range (random_generator, -v/2.0, v/2.0); \
a = BOUNDS(a) ; \
}
MYASSIGN(r);
MYASSIGN(g);
MYASSIGN(b);
#undef BOUNDS
#undef MYASSIGN
1999-08-26 22:29:37 +00:00
}
apply_brush(brush, shadow, &tmp, &atmp, tx,ty, r,g,b);
if(runningvals.general_tileable && runningvals.general_paint_edges) {
int orig_width = tmp.width - 2 * maxbrushwidth;
int orig_height = tmp.height - 2 * maxbrushheight;
1999-08-26 22:29:37 +00:00
int dox = 0, doy = 0;
if(tx < maxbrushwidth) {
apply_brush(brush, shadow, &tmp, &atmp, tx+orig_width,ty, r,g,b);
dox = -1;
} else if(tx > orig_width) {
apply_brush(brush, shadow, &tmp, &atmp, tx-orig_width,ty, r,g,b);
dox = 1;
1999-08-26 22:29:37 +00:00
}
if(ty < maxbrushheight) {
apply_brush(brush, shadow, &tmp, &atmp, tx,ty+orig_height, r,g,b);
doy = 1;
} else if(ty > orig_height) {
apply_brush(brush, shadow, &tmp, &atmp, tx,ty-orig_height, r,g,b);
doy = -1;
1999-08-26 22:29:37 +00:00
}
if(doy) {
if(dox < 0)
apply_brush(brush, shadow, &tmp, &atmp, tx+orig_width,ty+doy*orig_height,r,g,b);
if(dox > 0)
apply_brush(brush, shadow, &tmp, &atmp, tx-orig_width,ty+doy*orig_height,r,g,b);
1999-08-26 22:29:37 +00:00
}
}
}
for(i = 0; i < num_brushes; i++) {
ppm_kill(&brushes[i]);
1999-08-26 22:29:37 +00:00
}
g_free(brushes);
g_free(shadows);
g_free(brushes_sum);
g_free (xpos);
g_free (ypos);
1999-08-26 22:29:37 +00:00
if(runningvals.general_paint_edges) {
1999-08-26 22:29:37 +00:00
crop(&tmp, maxbrushwidth, maxbrushheight, tmp.width - maxbrushwidth, tmp.height - maxbrushheight);
if(img_has_alpha)
crop(&atmp, maxbrushwidth, maxbrushheight, atmp.width - maxbrushwidth, atmp.height - maxbrushheight);
}
ppm_kill(p);
1999-08-26 22:29:37 +00:00
p->width = tmp.width;
p->height = tmp.height;
p->col = tmp.col;
if(img_has_alpha) {
ppm_kill(a);
1999-08-26 22:29:37 +00:00
a->width = atmp.width;
a->height = atmp.height;
a->col = atmp.col;
}
relief = runningvals.paper_relief / 100.0;
1999-08-26 22:29:37 +00:00
if(relief > 0.001) {
scale = runningvals.paper_scale / 100.0;
1999-08-26 22:29:37 +00:00
if (PPM_IS_INITED (&paper_ppm)) {
tmp = paper_ppm;
paper_ppm.col = NULL;
1999-08-26 22:29:37 +00:00
} else {
tmp.col = NULL;
ppm_load(runningvals.selected_paper, &tmp);
1999-08-26 22:29:37 +00:00
resize(&tmp, tmp.width * scale, tmp.height * scale);
if(runningvals.paper_invert)
ppm_apply_gamma(&tmp, -1.0, 1,1,1);
1999-08-26 22:29:37 +00:00
}
for(x = 0; x < p->width; x++) {
double h, v;
int px = x % tmp.width, py;
for(y = 0; y < p->height; y++) {
int k = y * p->width * 3 + x * 3;
py = y % tmp.height;
if(runningvals.paper_overlay)
h = (tmp.col[py*tmp.width*3+px*3]-128) * relief;
else
h = (tmp.col[py*tmp.width*3+px*3] - (int)tmp.col[((py+1)%tmp.height)*tmp.width*3+((px+1)%tmp.width)*3]) / -2.0 * relief;
if(h <= 0.0) {
v = 1.0 + h/128.0;
if(v < 0.0) v = 0.0; else if(v > 1.0) v = 1.0;
p->col[k+0] *= v;
p->col[k+1] *= v;
p->col[k+2] *= v;
} else {
v = h/128.0;
if(v < 0.0) v = 0.0; else if(v > 1.0) v = 1.0;
p->col[k+0] = p->col[k+0] * (1.0-v) + 255 * v;
p->col[k+1] = p->col[k+1] * (1.0-v) + 255 * v;
p->col[k+2] = p->col[k+2] * (1.0-v) + 255 * v;
}
1999-08-26 22:29:37 +00:00
}
}
ppm_kill(&tmp);
1999-08-26 22:29:37 +00:00
}
ppm_kill (&paper_ppm);
ppm_kill (&dirmap);
ppm_kill (&sizmap);
1999-08-26 22:29:37 +00:00
if(runningvals.run) {
removed our own action_area API and use GtkDialog's one. Create all 2003-11-06 Michael Natterer <mitch@gimp.org> * libgimpwidgets/gimpdialog.[ch]: removed our own action_area API and use GtkDialog's one. Create all dialogs without separator. Changed almost everything else too. Fixes bug #125143. * libgimpwidgets/gimpquerybox.c * libgimpwidgets/gimpunitmenu.c: changed accordingly. * libgimp/gimpexport.[ch]: ditto. Renamed enum GimpExportReturnType to GimpExportReturn. * libgimp/gimpcompat.h: added a #define for the old name. * themes/Default/gtkrc: increased action_area border to 6 pixels. * app/display/gimpdisplayshell-filter-dialog.c * app/display/gimpdisplayshell-scale.c * app/display/gimpprogress.c * app/gui/brush-select.c * app/gui/channels-commands.c * app/gui/color-notebook.c * app/gui/convert-dialog.c * app/gui/file-new-dialog.c * app/gui/font-select.c * app/gui/gradient-editor-commands.c * app/gui/gradient-select.c * app/gui/grid-dialog.c * app/gui/image-commands.c * app/gui/info-window.c * app/gui/layers-commands.c * app/gui/module-browser.c * app/gui/offset-dialog.c * app/gui/palette-import-dialog.c * app/gui/palette-select.c * app/gui/pattern-select.c * app/gui/preferences-dialog.c * app/gui/qmask-commands.c * app/gui/resize-dialog.c * app/gui/resolution-calibrate-dialog.c * app/gui/stroke-dialog.c * app/gui/templates-commands.c * app/gui/user-install-dialog.c * app/gui/vectors-commands.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpimagemaptool.c * app/tools/gimpmeasuretool.c * app/tools/gimptransformtool.c * app/widgets/gimptexteditor.c * app/widgets/gimptooldialog.[ch] * app/widgets/gimpviewabledialog.[ch] * app/widgets/gimpwidgets-utils.c: changed accordingly and increased the dialogs' outer borders to 6 pixels all over the place. * plug-ins/*/*.c: changed accordingly. The plug-ins may be arbitrarily broken, I tested none of them.
2003-11-06 15:27:05 +00:00
gimp_progress_update(0.8);
1999-08-26 22:29:37 +00:00
} else {
preview_set_button_label (_("Update"));
1999-08-26 22:29:37 +00:00
}
running = 0;
}