From 7500d3b40ebd24f32d8ae226aed65fabc28c7e8d Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sun, 24 May 2015 17:32:48 +0200 Subject: Add improvecolors command Also fixes try_colors, which used an integer division *before* casting the result to double. --- flam3.c | 4 +- flam3.h | 6 +- main.c | 55 ++++++++++++++++-- palettes.c | 189 +++++++++++++++++++++++++++---------------------------------- 4 files changed, 142 insertions(+), 112 deletions(-) diff --git a/flam3.c b/flam3.c index b0caaf7..0a6f59b 100644 --- a/flam3.c +++ b/flam3.c @@ -1736,11 +1736,11 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in if (s < 0.4) { /* randomize xform color coords */ - flam3_improve_colors(cp, 100, 0, 10, pc, rc); + flam3_improve_colors(cp, 100, 0, 10, 1.0, pc, rc); } else if (s < 0.8) { /* randomize xform color coords and palette */ - flam3_improve_colors(cp, 25, 1, 10, pc, rc); + flam3_improve_colors(cp, 25, 1, 10, 1.0, pc, rc); } else { /* randomize palette only */ const palette * const p = palette_random (pc, rc); diff --git a/flam3.h b/flam3.h index b011d81..e5127fc 100644 --- a/flam3.h +++ b/flam3.h @@ -461,7 +461,11 @@ flam3_genome *flam3_parse_xml2(const int, int default_flag, int *ncps, randctx * void flam3_add_symmetry(flam3_genome *cp, int sym, randctx * const rc); -void flam3_improve_colors(flam3_genome *g, int ntries, int change_palette, int color_resolution, const palette_collection * const pc, randctx * const rc); +void flam3_improve_colors(flam3_genome *g, unsigned int ntries, + bool change_palette, + unsigned int color_resolution, double timelimit, + const palette_collection * const pc, + randctx * const rc); int flam3_estimate_bounding_box(flam3_genome *g, double eps, int nsamples, double *bmin, double *bmax, randctx *rc); diff --git a/main.c b/main.c index 909db71..ec6205d 100644 --- a/main.c +++ b/main.c @@ -422,11 +422,38 @@ static void do_cross (const cross_arguments * const arguments) { print_genome (&genome_out); } -#if 0 -static void do_improvecolors () { - flam3_improve_colors(&cp_orig, 100, 0, 10, &rc); +typedef struct { + unsigned int tries, resolution; + bool change_palette; + double time; +} improvecolors_arguments; + +static error_t parse_improvecolors_opt (int key, char *arg, + struct argp_state * const state) { + improvecolors_arguments * const arguments = state->input; + + return 0; +} + +static void do_improvecolors (const improvecolors_arguments * const arguments) { + randctx rc; + + rand_seed(&rc); + + int ncps; + flam3_genome * const cps = flam3_parse_xml2 (STDIN_FILENO, + flam3_defaults_on, &ncps, &rc); + if (cps == NULL) { + fprintf(stderr,"error reading genomes from file\n"); + exit(1); + } + assert (ncps == 1); + + flam3_improve_colors (&cps[0], arguments->tries, arguments->change_palette, + arguments->resolution, arguments->time, &builtin_palettes, &rc); + + print_genome (&cps[0]); } -#endif typedef struct { float time; @@ -495,6 +522,7 @@ static void show_help (const char * const argv0) { } fprintf (stderr, "Usage: %s cross [OPTION...]\n" + " Or: %s improvecolors [OPTION...]\n" " Or: %s interpolate [OPTION...]\n" " Or: %s mutate [OPTION...]\n" " Or: %s random [OPTION...]\n" @@ -527,6 +555,25 @@ int main (int argc, char **argv) { argp_parse (&argp, argc, argv, 0, NULL, &arguments); do_cross (&arguments); + } else if (streq (command, "improvecolors")) { + const struct argp_option options[] = { + { 0 }, + }; + const char doc[] = PACKAGE "-improvecolors -- improve flame colors"; + const struct argp argp = { + .options = options, .parser = parse_improvecolors_opt, + .args_doc = NULL, .doc = doc, .children = NULL + }; + + improvecolors_arguments arguments = { + .tries = 100, + .resolution = 10, + .change_palette = true, + .time = 1.0, + }; + + argp_parse (&argp, argc, argv, 0, NULL, &arguments); + do_improvecolors (&arguments); } else if (streq (command, "interpolate")) { const struct argp_option options[] = { {"time", 't', "float", OPTION_ARG_OPTIONAL, "Time step (0.5)" }, diff --git a/palettes.c b/palettes.c index 6da1fc5..eb13cb3 100644 --- a/palettes.c +++ b/palettes.c @@ -226,88 +226,66 @@ static int random_xform(flam3_genome *g, int excluded, randctx * const rc) { return -1; } -static double try_colors(flam3_genome *g, int color_resolution) { - int *hist; - int i, hits, res = color_resolution; - int res3 = res * res * res; - flam3_frame f; - unsigned char *image, *p; - flam3_genome saved; - double scalar; - int pixtotal; - - memset(&saved, 0, sizeof(flam3_genome)); - - flam3_copy(&saved, g); - - /* Scale the image so that the total number of pixels is ~10000 */ - pixtotal = g->width * g->height; - scalar = sqrt( 10000.0 / (double)pixtotal); - g->width *= scalar; - g->height *= scalar; - g->pixels_per_unit *= scalar; - -// g->width = 100; // XXX keep aspect ratio -// g->height = 100; -// g->pixels_per_unit = 50; - - f.bytes_per_channel=1; - f.genomes = g; - f.ngenomes = 1; - f.earlyclip = 1; - f.pixel_aspect_ratio = 1.0; - f.progress = 0; - f.nthreads = 1; - f.sub_batch_size = 10000; - - image = (unsigned char *) calloc(g->width * g->height, 3); +static double try_colors(flam3_genome *g, unsigned int color_resolution, + double timelimit) { + assert (g != NULL); + assert (color_resolution > 0); + + int *hist; + unsigned int res = color_resolution, res3 = res * res * res; + unsigned char *image, *p; + flam3_genome saved; + int pixtotal; + + memset(&saved, 0, sizeof(flam3_genome)); + + flam3_copy(&saved, g); + + /* Scale the image so that the total number of pixels is ~10000 */ + pixtotal = g->width * g->height; + const double scalar = sqrt( 10000.0 / (double)pixtotal); + g->width *= scalar; + g->height *= scalar; + g->pixels_per_unit *= scalar; + + const unsigned int bytes_per_channel=1; + const unsigned int channels = 4; + + image = (unsigned char *) calloc(g->width * g->height, bytes_per_channel * channels); bucket bucket; bucket_init (&bucket, (uint2) { g->width, g->height }); - render_bucket (g, &bucket, 0.2); - render_image (g, &bucket, image, f.bytes_per_channel); - - hist = calloc(sizeof(int), res3); - p = image; - for (i = 0; i < g->height * g->width; i++) { - hist[(p[0] * res / 256) + - (p[1] * res / 256) * res + - (p[2] * res / 256) * res * res]++; - p += 3; - } - - if (0) { - int j, k; - for (i = 0; i < res; i++) { - fprintf(stderr, "\ni=%d: \n", i); - for (j = 0; j < res; j++) { - for (k = 0; k < res; k++) { - fprintf(stderr, " %5d", hist[i * res * res + j * res + k]); - } - fprintf(stderr, "\n"); - } - } - } - - hits = 0; - for (i = 0; i < res3; i++) { - if (hist[i]) hits++; - } - - free(hist); - free(image); - - g->width = saved.width; - g->height = saved.height; - g->pixels_per_unit = saved.pixels_per_unit; - - /* Free xform storage */ - clear_cp(&saved,flam3_defaults_on); - - return (double) (hits / res3); + render_bucket (g, &bucket, timelimit); + render_image (g, &bucket, image, bytes_per_channel); + + hist = calloc(sizeof(int), res3); + p = image; + for (unsigned int i = 0; i < g->height * g->width; i++) { + hist[(p[0] * res / 256) + + (p[1] * res / 256) * res + + (p[2] * res / 256) * res * res]++; + p += channels; + } + + unsigned int hits = 0; + for (unsigned int i = 0; i < res3; i++) { + if (hist[i]) hits++; + } + + free(hist); + free(image); + + g->width = saved.width; + g->height = saved.height; + g->pixels_per_unit = saved.pixels_per_unit; + + /* Free xform storage */ + clear_cp(&saved,flam3_defaults_on); + + return (double) hits / (double) res3; } -static void change_colors(flam3_genome *g, int change_palette, +static void change_colors(flam3_genome *g, bool change_palette, const palette_collection * const pc, randctx * const rc) { int i; int x0, x1; @@ -326,34 +304,35 @@ static void change_colors(flam3_genome *g, int change_palette, if (x1 >= 0 && rand_bool(rc)) g->xform[x1].color = 1.0; } -void flam3_improve_colors(flam3_genome *g, int ntries, int change_palette, int color_resolution, const palette_collection * const pc, randctx * const rc) { - int i; - double best, b; - flam3_genome best_genome; - - memset(&best_genome, 0, sizeof(flam3_genome)); - - best = try_colors(g, color_resolution); - if (best<0) { - fprintf(stderr,"error in try_colors, skipping flam3_improve_colors\n"); - return; - } - - flam3_copy(&best_genome,g); - for (i = 0; i < ntries; i++) { - change_colors(g, change_palette, pc, rc); - b = try_colors(g, color_resolution); - if (b < 0) { - fprintf(stderr,"error in try_colors, aborting tries\n"); - break; - } - if (b > best) { - best = b; - flam3_copy(&best_genome,g); - } - } +void flam3_improve_colors(flam3_genome *g, unsigned int ntries, + bool change_palette, + unsigned int color_resolution, double timelimit, + const palette_collection * const pc, + randctx * const rc) { + const double trytime = timelimit/(double) ntries; + flam3_genome best_genome; + + memset(&best_genome, 0, sizeof(flam3_genome)); + + double best = try_colors(g, color_resolution, trytime); + assert (best >= 0.0); + + flam3_copy(&best_genome,g); + for (unsigned int i = 0; i < ntries; i++) { + change_colors(g, change_palette, pc, rc); + const double b = try_colors(g, color_resolution, trytime); + assert (b >= 0.0); + if (b < 0) { + fprintf(stderr,"error in try_colors, aborting tries\n"); + break; + } + if (b > best) { + best = b; + flam3_copy(&best_genome,g); + } + } - flam3_copy(g,&best_genome); - clear_cp(&best_genome,flam3_defaults_on); + flam3_copy(g,&best_genome); + clear_cp(&best_genome,flam3_defaults_on); } -- cgit v1.2.3