texture_t * texture_load(const char *name) { texture_t *tex; tex = (texture_t *)malloc(sizeof(texture_t)); tex->image = ppm_load(&tex->width, &tex->height, name); tex->name = strdup(name); printf("Texture loaded [ %s ] %d x %d\n", name, tex->width, tex->height); return tex; }
static void paper_update_preview (void) { gint i, j; guchar *buf, *paper_preview_buffer; gdouble sc; ppm_t p = {0, 0, NULL}; ppm_load (pcvals.selected_paper, &p); sc = p.width > p.height ? p.width : p.height; sc = 100.0 / sc; resize (&p, p.width*sc,p.height*sc); paper_preview_buffer = g_new0 (guchar, 100*100); for (i = 0, buf = paper_preview_buffer; i < 100; i++, buf += 100) { gint k = i * p.width * 3; if (i < p.height) { for (j = 0; j < p.width; j++) buf[j] = p.col[k + j * 3]; if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (paper_invert))) for (j = 0; j < p.width; j++) buf[j] = 255 - buf[j]; } } gimp_preview_area_draw (GIMP_PREVIEW_AREA (paper_preview), 0, 0, 100, 100, GIMP_GRAY_IMAGE, paper_preview_buffer, 100); ppm_kill (&p); g_free (paper_preview_buffer); gtk_widget_queue_draw (paper_preview); }
/* * 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); }
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; } }