void brush_get_selected (ppm_t *p) { if (brush_from_file) brush_reload (pcvals.selected_brush, p); else ppm_copy (&brushppm, p); }
static void update_vector_prev (void) { static gint ok = 0; gint i, x, y; gdouble dir, xo, yo; gdouble val; static gdouble last_val = 0.0; guchar gray[3] = {120, 120, 120}; guchar red[3] = {255, 0, 0}; guchar white[3] = {255, 255, 255}; if (vector_preview_brightness_adjust) val = 1.0 - gtk_adjustment_get_value (GTK_ADJUSTMENT (vector_preview_brightness_adjust)) / 100.0; else val = 0.5; if (!ok || (val != last_val)) { infile_copy_to_ppm (&update_vector_preview_backup); ppm_apply_brightness (&update_vector_preview_backup, val, 1,1,1); if ((update_vector_preview_backup.width != OMWIDTH) || (update_vector_preview_backup.height != OMHEIGHT)) resize_fast (&update_vector_preview_backup, OMWIDTH, OMHEIGHT); ok = 1; } ppm_copy (&update_vector_preview_backup, &update_vector_preview_buffer); for (i = 0; i < num_vectors; i++) { gdouble s; x = vector[i].x * OMWIDTH; y = vector[i].y * OMHEIGHT; dir = gimp_deg_to_rad (vector[i].dir); s = gimp_deg_to_rad (vector[i].str); xo = sin (dir) * (6.0+100*s); yo = cos (dir) * (6.0+100*s); if (i == selectedvector) { ppm_drawline (&update_vector_preview_buffer, x - xo, y - yo, x + xo, y + yo, red); } else { ppm_drawline (&update_vector_preview_buffer, x - xo, y - yo, x + xo, y + yo, gray); } ppm_put_rgb (&update_vector_preview_buffer, x - xo, y - yo, white); } gimp_preview_area_draw (GIMP_PREVIEW_AREA (vector_preview), 0, 0, OMWIDTH, OMHEIGHT, GIMP_RGB_IMAGE, (guchar *)update_vector_preview_buffer.col, OMWIDTH * 3); }
/* * This function caches the last result. Call it with fn as NULL, to * free the arguments. * */ void brush_reload (const gchar *fn, ppm_t *p) { static char lastfn[256] = ""; static ppm_t cache = {0, 0, NULL}; if (fn == NULL) { ppm_kill (&cache); lastfn[0] = '\0'; return; } if (strcmp (fn, lastfn)) { g_strlcpy (lastfn, fn, sizeof (lastfn)); ppm_kill (&cache); ppm_load (fn, &cache); } ppm_copy (&cache, p); set_colorbrushes (fn); }
static void update_brush_preview (const gchar *fn) { gint i, j; guchar *preview_image; if (fn) brush_from_file = 1; preview_image = g_new0 (guchar, 100*100); if (!fn && brush_from_file) { /* preview_image is already initialized to our liking. */ } else { double sc; ppm_t p = {0, 0, NULL}; guchar gammatable[256]; int newheight; if (brush_from_file) brush_reload (fn, &p); else if (PPM_IS_INITED (&brushppm)) ppm_copy (&brushppm, &p); set_colorbrushes (fn); sc = gtk_adjustment_get_value (brush_gamma_adjust); if (sc != 1.0) for (i = 0; i < 256; i++) gammatable[i] = pow (i / 255.0, sc) * 255; else for (i = 0; i < 256; i++) gammatable[i] = i; newheight = p.height * pow (10, gtk_adjustment_get_value (brush_aspect_adjust)); sc = p.width > newheight ? p.width : newheight; sc = 100.0 / sc; resize_fast (&p, p.width*sc,newheight*sc); padbrush (&p, 100, 100); for (i = 0; i < 100; i++) { int k = i * p.width * 3; if (i < p.height) for (j = 0; j < p.width; j++) preview_image[i*100+j] = gammatable[p.col[k + j * 3]]; } ppm_kill (&p); } gimp_preview_area_draw (GIMP_PREVIEW_AREA (brush_preview), 0, 0, 100, 100, GIMP_GRAY_IMAGE, preview_image, 100); g_free (preview_image); }
void repaint (ppm_t *p, ppm_t *a) { int x, y; int tx = 0, ty = 0; ppm_t tmp = {0, 0, NULL}; ppm_t atmp = {0, 0, NULL}; int r, g, b, h, i, j, on, sn; int num_brushes, maxbrushwidth, maxbrushheight; guchar back[3] = {0, 0, 0}; ppm_t *brushes, *shadows; ppm_t *brush, *shadow = NULL; double *brushes_sum; int cx, cy, maxdist; double scale, relief, startangle, anglespan, density, bgamma; int max_progress; ppm_t paper_ppm = {0, 0, NULL}; ppm_t dirmap = {0, 0, NULL}; ppm_t sizmap = {0, 0, NULL}; int *xpos = NULL, *ypos = NULL; int progstep; static int running = 0; int dropshadow = pcvals.general_drop_shadow; int shadowblur = pcvals.general_shadow_blur; if (running) return; running++; runningvals = pcvals; /* 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"); return; } num_brushes = runningvals.orient_num * runningvals.size_num; startangle = runningvals.orient_first; anglespan = runningvals.orient_last; density = runningvals.brush_density; if (runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) density /= 3.0; bgamma = runningvals.brushgamma; brushes = g_malloc (num_brushes * sizeof (ppm_t)); brushes_sum = g_malloc (num_brushes * sizeof (double)); if (dropshadow) shadows = g_malloc (num_brushes * sizeof (ppm_t)); else shadows = NULL; brushes[0].col = NULL; brush_get_selected (&brushes[0]); 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); if (bgamma != 1.0) ppm_apply_gamma (&brushes[0], 1.0 / bgamma, 1,1,1); 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, i - brushes[0].height, i - brushes[0].height, back); for (i = 1; i < num_brushes; i++) { brushes[i].col = NULL; ppm_copy (&brushes[0], &brushes[i]); } for (i = 0; i < runningvals.size_num; i++) { double sv; if (runningvals.size_num > 1) sv = i / (runningvals.size_num - 1.0); 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); autocrop (&brushes[h],1); } } /* Brush-debugging */ #if 0 for (i = 0; i < num_brushes; i++) { char tmp[1000]; g_snprintf (tmp, sizeof (tmp), "/tmp/_brush%03d.ppm", i); ppm_save (&brushes[i], tmp); } #endif for (i = 0; i < num_brushes; i++) { if (!runningvals.color_brushes) prepare_brush (&brushes[i]); brushes_sum[i] = sum_brush (&brushes[i]); } brush = &brushes[0]; maxbrushwidth = maxbrushheight = 0; for (i = 0; i < num_brushes; i++) { 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++) { int xp, yp; guchar blk[3] = {0, 0, 0}; 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); } if (dropshadow) { for (i = 0; i < num_brushes; i++) { 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); for (j = 0; j < shadowblur; j++) blur (&shadows[i], 2, 2); #if 0 autocrop (&shadows[i],1); #endif } #if 0 maxbrushwidth += shadowdepth*3; maxbrushheight += shadowdepth*3; #endif } /* For extra annoying debugging :-) */ #if 0 ppm_save (brushes, "/tmp/__brush.ppm"); if (shadows) ppm_save (shadows, "/tmp/__shadow.ppm"); system ("xv /tmp/__brush.ppm & xv /tmp/__shadow.ppm & "); #endif if (runningvals.general_paint_edges) { 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) { guchar tmpcol[3] = {255, 255, 255}; ppm_new (&atmp, a->width, a->height); fill (&atmp, tmpcol); } else { ppm_copy (a, &atmp); } } if (runningvals.general_background_type == BG_TYPE_SOLID) { guchar tmpcol[3]; ppm_new (&tmp, p->width, p->height); gimp_rgb_get_uchar (&runningvals.color, &tmpcol[0], &tmpcol[1], &tmpcol[2]); fill (&tmp, tmpcol); } else if (runningvals.general_background_type == BG_TYPE_KEEP_ORIGINAL) { ppm_copy (p, &tmp); } else { int dx, dy; ppm_new (&tmp, p->width, p->height); ppm_load (runningvals.selected_paper, &paper_ppm); if (runningvals.paper_scale != 100.0) { scale = runningvals.paper_scale / 100.0; 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); dx = runningvals.general_paint_edges ? paper_ppm.width - maxbrushwidth : 0; dy = runningvals.general_paint_edges ? paper_ppm.height - maxbrushheight : 0; for (y = 0; y < tmp.height; y++) { int lx; int ry = (y + dy) % paper_ppm.height; for (x = 0; x < tmp.width; x+=lx) { int rx = (x + dx) % paper_ppm.width; lx = MIN (tmp.width - x, paper_ppm.width - rx); memcpy (&tmp.col[y * tmp.width * 3 + x * 3], &paper_ppm.col[ry * paper_ppm.width * 3 + rx * 3], 3 * lx); } } } 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); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = (srcrow[x * 3] + srcrow[x * 3 + 1] + srcrow[x * 3 + 2]) / 3; } } break; case ORIENTATION_RADIUS: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; double ysqr = (cy - y) * (cy - y); for (x = 0; x < dirmap.width; x++) { dstrow[x*3] = sqrt ((cx - x) * (cx - x) + ysqr) * 255 / maxdist; } } break; case ORIENTATION_RADIAL: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = (G_PI + atan2 (cy - y, cx - x)) * 255.0 / (G_PI * 2); } } break; case ORIENTATION_FLOWING: ppm_new (&dirmap, p->width / 6 + 5, p->height / 6 + 5); 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) edgepad (&dirmap, maxbrushwidth, maxbrushheight, maxbrushwidth, maxbrushheight); break; case ORIENTATION_HUE: ppm_new (&dirmap, p->width, p->height); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < dirmap.width; x++) { dstrow[x * 3] = get_hue (&srcrow[x * 3]); } } 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); for (y = 0; y < dirmap.height; y++) { guchar *dstrow = &dirmap.col[y * dirmap.width * 3]; 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)); } } edgepad (&dirmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight); break; } if (runningvals.size_type == SIZE_TYPE_VALUE) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = (srcrow[x * 3] + srcrow[x * 3 + 1] + srcrow[x * 3 + 2]) / 3; } } } else if (runningvals.size_type == SIZE_TYPE_RADIUS) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; double ysqr = (cy - y) * (cy - y); for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = sqrt ((cx - x) * (cx - x) + ysqr) * 255 / maxdist; } } } else if (runningvals.size_type == SIZE_TYPE_RADIAL) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; for (x = 0; x < sizmap.width; x++) { dstrow[x * 3] = (G_PI + atan2 (cy - y, cx - x)) * 255.0 / (G_PI * 2); } } } else if (runningvals.size_type == SIZE_TYPE_FLOWING) { ppm_new (&sizmap, p->width / 6 + 5, p->height / 6 + 5); 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) edgepad (&sizmap, maxbrushwidth, maxbrushheight, maxbrushwidth, maxbrushheight); } else if (runningvals.size_type == SIZE_TYPE_HUE) { ppm_new (&sizmap, p->width, p->height); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; guchar *srcrow = &p->col[y * p->width * 3]; for (x = 0; x < sizmap.width; x++) { dstrow[ x * 3] = get_hue (&srcrow[x * 3]); } } } else if (runningvals.size_type == SIZE_TYPE_ADAPTIVE) { guchar tmpcol[3] = {0, 0, 0}; ppm_new (&sizmap, p->width, p->height); fill (&sizmap, tmpcol); } else if (runningvals.size_type == SIZE_TYPE_MANUAL) { ppm_new (&sizmap, p->width-maxbrushwidth * 2, p->height-maxbrushheight * 2); for (y = 0; y < sizmap.height; y++) { guchar *dstrow = &sizmap.col[y * sizmap.width * 3]; 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)); } } edgepad (&sizmap, maxbrushwidth, maxbrushwidth, maxbrushheight, maxbrushheight); } #if 0 ppm_save(&sizmap, "/tmp/_sizmap.ppm"); #endif if (runningvals.place_type == PLACEMENT_TYPE_RANDOM) { i = tmp.width * tmp.height / (maxbrushwidth * maxbrushheight); i *= density; } else if (runningvals.place_type == PLACEMENT_TYPE_EVEN_DIST) { i = (int)(tmp.width * density / maxbrushwidth) * (int)(tmp.height * density / maxbrushheight); #if 0 g_printerr("i=%d\n", i); #endif } 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) { int j; xpos = g_new (int, i); ypos = g_new (int, i); 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); b = xpos[j]; xpos[j] = xpos[a]; xpos[a] = b; b = ypos[j]; ypos[j] = ypos[a]; ypos[a] = b; } }
static void updatesmvectorprev (void) { static int ok = 0; gint i, x, y; gdouble val; static gdouble last_val = 0.0; guchar gray[3] = {120, 120, 120}; guchar red[3] = {255, 0, 0}; guchar white[3] = {255, 255, 255}; if (smvectprevbrightadjust) val = 1.0 - gtk_adjustment_get_value (GTK_ADJUSTMENT (smvectprevbrightadjust)) / 100.0; else val = 0.5; if (!ok || (val != last_val)) { #if 0 if (!PPM_IS_INITED (&infile)) updatepreview (NULL, (void *)2); /* Force grabarea () */ ppm_copy (&infile, &update_vector_preview_backup); #else infile_copy_to_ppm (&update_vector_preview_backup); #endif ppm_apply_brightness (&update_vector_preview_backup, val, 1,1,1); if (update_vector_preview_backup.width != OMWIDTH || update_vector_preview_backup.height != OMHEIGHT) resize_fast (&update_vector_preview_backup, OMWIDTH, OMHEIGHT); ok = 1; } ppm_copy (&update_vector_preview_backup, &update_vector_preview_sbuffer); for (i = 0; i < numsmvect; i++) { x = smvector[i].x * OMWIDTH; y = smvector[i].y * OMHEIGHT; if (i == selectedsmvector) { ppm_drawline (&update_vector_preview_sbuffer, x-5, y, x+5, y, red); ppm_drawline (&update_vector_preview_sbuffer, x, y-5, x, y+5, red); } else { ppm_drawline (&update_vector_preview_sbuffer, x-5, y, x+5, y, gray); ppm_drawline (&update_vector_preview_sbuffer, x, y-5, x, y+5, gray); } ppm_put_rgb (&update_vector_preview_sbuffer, x, y, white); } gimp_preview_area_draw (GIMP_PREVIEW_AREA (smvectorprev), 0, 0, OMWIDTH, OMHEIGHT, GIMP_RGB_IMAGE, update_vector_preview_sbuffer.col, OMWIDTH * 3); gtk_widget_set_sensitive (prev_button, (numsmvect > 1)); gtk_widget_set_sensitive (next_button, (numsmvect > 1)); gtk_widget_set_sensitive (add_button, (numsmvect < MAXORIENTVECT)); gtk_widget_set_sensitive (kill_button, (numsmvect > 1)); }