From d5a00c0d05030a875ebd85356509ee270bdb7410 Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Sun, 15 Mar 2015 17:08:55 +0100 Subject: Rewrite color palettes Supports palettes with != 256 colors properly now. A lot of old code still (silently!) relies on that number though. --- flam3.c | 113 ++++++---------------- flam3.h | 28 ++---- interpolation.c | 52 ++++------ interpolation.h | 2 + main.c | 12 ++- palettes.c | 287 ++++++++++++++++++++++---------------------------------- palettes.h | 33 +++++-- parser.c | 54 +++-------- parser.h | 7 +- rect.c | 21 ++--- 10 files changed, 233 insertions(+), 376 deletions(-) diff --git a/flam3.c b/flam3.c index 2646fbb..6f2056f 100644 --- a/flam3.c +++ b/flam3.c @@ -963,6 +963,7 @@ void flam3_copy(flam3_genome *dest, const flam3_genome * const src) { for (i=0;ichaos[i],src->chaos[i], numstd * sizeof(double)); + palette_copy (&src->palette, &dest->palette); } void flam3_copyx(flam3_genome *dest, flam3_genome *src, int dest_std_xforms, int dest_final_xform) { @@ -1025,78 +1026,38 @@ void flam3_copyx(flam3_genome *dest, flam3_genome *src, int dest_std_xforms, int } void clear_cp(flam3_genome *cp, int default_flag) { - cp->palette_index = flam3_palette_random; - cp->center[0] = 0.0; - cp->center[1] = 0.0; - cp->rot_center[0] = 0.0; - cp->rot_center[1] = 0.0; + memset (cp, 0, sizeof (*cp)); + cp->gamma = 4.0; cp->vibrancy = 1.0; cp->contrast = 1.0; cp->brightness = 4.0; - cp->symmetry = 0; - cp->hue_rotation = 0.0; - cp->rotate = 0.0; cp->pixels_per_unit = 50; cp->interpolation = flam3_interpolation_linear; cp->palette_interpolation = flam3_palette_interpolation_hsv; - cp->genome_index = 0; - memset(cp->parent_fname,0,flam3_parent_fn_len); - if (default_flag==flam3_defaults_on) { /* If defaults are on, set to reasonable values */ cp->highlight_power = -1.0; - cp->background[0] = 0.0; - cp->background[1] = 0.0; - cp->background[2] = 0.0; cp->width = 100; cp->height = 100; - cp->zoom = 0.0; - cp->sample_density = 1; cp->gam_lin_thresh = 0.01; -// cp->motion_exp = 0.0; cp->interpolation_type = flam3_inttype_log; cp->palette_mode = PALETTE_MODE_STEP; } else { /* Defaults are off, so set to UN-reasonable values. */ cp->highlight_power = -1.0; - cp->background[0] = -1.0; - cp->background[1] = -1.0; - cp->background[2] = -1.0; cp->zoom = 999999999; cp->width = -1; cp->height = -1; - cp->sample_density = -1; cp->gam_lin_thresh = -1; // cp->motion_exp = -999; cp->interpolation_type = -1; cp->palette_mode = -1; } - if (cp->xform != NULL && cp->num_xforms > 0) { - int i; - int ns = cp->num_xforms - (cp->final_xform_index>=0); - - for (i=0;ichaos[i]); - } - free(cp->chaos); - cp->chaos=NULL; - - for (i=0;inum_xforms;i++) - flam3_delete_motion_elements(&cp->xform[i]); - - free(cp->xform); - cp->xform=NULL; - - cp->num_xforms = 0; - } - - cp->final_xform_enable = 0; cp->final_xform_index = -1; - } flam3_genome *flam3_parse_xml2(char *xmldata, char *xmlfilename, int default_flag, int *ncps, randctx * const rc) { @@ -1243,16 +1204,8 @@ flam3_genome * flam3_parse_from_file(FILE *f, char *fname, int default_flag, int void flam3_apply_template(flam3_genome *cp, flam3_genome *templ) { /* Check for invalid values - only replace those with valid ones */ - if (templ->background[0] >= 0) - cp->background[0] = templ->background[0]; - if (templ->background[1] >= 0) - cp->background[1] = templ->background[1]; - if (templ->background[1] >= 0) - cp->background[2] = templ->background[2]; if (templ->zoom < 999999998) cp->zoom = templ->zoom; - if (templ->sample_density > 0) - cp->sample_density = templ->sample_density; if (templ->width > 0) { /* preserving scale should be an option */ cp->pixels_per_unit = cp->pixels_per_unit * templ->width / cp->width; @@ -1338,9 +1291,6 @@ void flam3_print(FILE *f, flam3_genome *cp, char *extra_attributes, int print_ed fprintf(f, " rotate=\"%g\"", cp->rotate); - fprintf(f, " quality=\"%g\"", cp->sample_density); - fprintf(f, " background=\"%g %g %g\"", - cp->background[0], cp->background[1], cp->background[2]); fprintf(f, " brightness=\"%g\"", cp->brightness); fprintf(f, " gamma=\"%g\"", cp->gamma); @@ -1389,20 +1339,18 @@ void flam3_print(FILE *f, flam3_genome *cp, char *extra_attributes, int print_ed } - for (i = 0; i < 256; i++) { - double r, g, b, a; - r = (cp->palette[i].color[0] * 255.0); - g = (cp->palette[i].color[1] * 255.0); - b = (cp->palette[i].color[2] * 255.0); - a = (cp->palette[i].color[3] * 255.0); - + for (i = 0; i < cp->palette.count; i++) { + double4 rgba = cp->palette.color[i] * 255.0; + fprintf(f, " "); - if (a==255.0) { + if (rgba[3] ==255.0) { - fprintf(f, "", i, r, g, b); + fprintf(f, "", i, rgba[0], + rgba[1], rgba[2]); } else { - fprintf(f, " ", i, r, g, b, a); + fprintf(f, " ", i, + rgba[0], rgba[1], rgba[2], rgba[3]); } // if (i%4 == 3) fprintf(f, "\n"); @@ -2276,19 +2224,20 @@ void flam3_cross(flam3_genome *cp0, flam3_genome *cp1, flam3_genome *out, int cr sprintf(ministr," %d:",startParent); /* Loop over the entries, switching to the other parent 1% of the time */ - for (ci=0;ci<256;ci++) { + for (ci=0;cipalette.count;ci++) { if (rand_d01(rc)<.01) { startParent = 1-startParent; sprintf(ministr," %d",ci); } - out->palette[ci] = startParent ? cp1->palette[ci]: cp0->palette[ci]; + out->palette.color[ci] = startParent ? cp1->palette.color[ci] : + cp0->palette.color[ci]; } } } -void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, int sym, double speed, randctx *rc) { +void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, int sym, double speed, const palette_collection * const pc, randctx *rc) { double randselect; flam3_genome mutation; @@ -2325,7 +2274,7 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in do { /* Create a random flame, and use the variations */ /* to replace those in the original */ - flam3_random(&mutation, ivars, ivars_n, sym, cp->num_xforms, rc); + flam3_random(&mutation, ivars, ivars_n, sym, cp->num_xforms, pc, rc); for (i = 0; i < cp->num_xforms; i++) { for (j = 0; j < flam3_nvariations; j++) { if (cp->xform[i].var[j] != mutation.xform[i].var[j]) { @@ -2347,7 +2296,7 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in int modxf; /* Generate a 2-xform random */ - flam3_random(&mutation, ivars, ivars_n, sym, 2, rc); + flam3_random(&mutation, ivars, ivars_n, sym, 2, pc, rc); /* Which xform do we mutate? */ modxf = rand_mod(rc, cp->num_xforms); @@ -2457,20 +2406,17 @@ 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, rc); + flam3_improve_colors(cp, 100, 0, 10, pc, rc); } else if (s < 0.8) { /* randomize xform color coords and palette */ - flam3_improve_colors(cp, 25, 1, 10, rc); + flam3_improve_colors(cp, 25, 1, 10, pc, rc); } else { /* randomize palette only */ - - cp->palette_index = flam3_get_palette(flam3_palette_random, cp->palette, cp->hue_rotation, rc); - /* if our palette retrieval fails, skip the mutation */ - if (cp->palette_index >= 0) { - } else - fprintf(stderr,"failure getting random palette, palette set to white\n"); - + const palette * const p = palette_random (pc, rc); + assert (p != NULL); + palette_copy (p, &cp->palette); + palette_rotate_hue (&cp->palette, cp->hue_rotation); } } else if (mutate_mode == MUTATE_DELETE_XFORM) { @@ -2483,7 +2429,7 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in } else { /* MUTATE_ALL_COEFS */ int x; - flam3_random(&mutation, ivars, ivars_n, sym, cp->num_xforms, rc); + flam3_random(&mutation, ivars, ivars_n, sym, cp->num_xforms, pc, rc); /* change all the coefs by a fraction of the random */ for (x = 0; x < cp->num_xforms; x++) { @@ -2501,7 +2447,9 @@ void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, in } -void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, int spec_xforms, randctx * const rc) { +void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, + int spec_xforms, const palette_collection * const pc, + randctx * const rc) { int i, nxforms, var, samed, multid, samepost, postid, addfinal=0; int finum = -1; @@ -2520,9 +2468,10 @@ void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, int spec_x clear_cp(cp,flam3_defaults_on); cp->hue_rotation = rand_mod(rc, 8) ? 0.0 : rand_d01(rc); - cp->palette_index = flam3_get_palette(flam3_palette_random, cp->palette, cp->hue_rotation, rc); - if (cp->palette_index < 0) - fprintf(stderr,"error getting palette from xml file, setting to all white\n"); + const palette * const p = palette_random (pc, rc); + assert (p != NULL); + palette_copy (p, &cp->palette); + palette_rotate_hue (&cp->palette, cp->hue_rotation); cp->time = 0.0; cp->interpolation = flam3_interpolation_linear; cp->palette_interpolation = flam3_palette_interpolation_hsv; diff --git a/flam3.h b/flam3.h index 8cd26f4..dad0bc7 100644 --- a/flam3.h +++ b/flam3.h @@ -35,18 +35,8 @@ #include "vector.h" -//typedef double flam3_palette[256][3]; -typedef struct { - double index; - double color[4]; -} flam3_palette_entry; - -typedef flam3_palette_entry flam3_palette[256]; - #include "random.h" -int flam3_get_palette(int n, flam3_palette c, double hue_rotation, randctx * const rc); - #define flam3_variation_random (-1) #define flam3_variation_random_fromspecified (-2) @@ -55,8 +45,6 @@ extern char *flam3_variation_names[]; #define flam3_nvariations 99 #define flam3_nxforms 12 -#define flam3_parent_fn_len 30 - #define flam3_interpolation_linear 0 #define flam3_interpolation_smooth 1 @@ -439,6 +427,8 @@ typedef struct xform { } flam3_xform; +#include "palettes.h" + typedef struct { char flame_name[flam3_name_len+1]; /* 64 chars plus a null */ double time; @@ -455,11 +445,9 @@ typedef struct { int chaos_enable; int genome_index; /* index into source file */ - char parent_fname[flam3_parent_fn_len]; /* base filename where parent was located */ int symmetry; /* 0 means none */ - flam3_palette palette; + palette palette; char *input_image; /* preview/temporary! */ - int palette_index; double brightness; /* 1.0 = normal */ double contrast; /* 1.0 = normal */ double gamma; @@ -470,10 +458,8 @@ typedef struct { double rotate; /* camera */ double vibrancy; /* blend between color algs (0=old,1=new) */ double hue_rotation; /* applies to cmap, 0-1 */ - double background[3]; double zoom; /* effects ppu, sample density, scale */ double pixels_per_unit; /* vertically */ - double sample_density; /* samples per pixel (not bucket) */ /* XML Edit structure */ xmlDocPtr edits; @@ -537,11 +523,13 @@ char *flam3_print_to_string(flam3_genome *cp); /* ivars_n is the number of values in ivars to select from. */ /* sym is either a symmetry group or 0 meaning random or no symmetry */ /* spec_xforms specifies the number of xforms to use, setting to 0 makes the number random. */ -void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, int spec_xforms, randctx * const rc); +void flam3_random(flam3_genome *cp, int *ivars, int ivars_n, int sym, + int spec_xforms, const palette_collection * const pc, + randctx * const rc); void add_to_action(char *action, char *addtoaction); -void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, int sym, double speed, randctx *rc); +void flam3_mutate(flam3_genome *cp, int mutate_mode, int *ivars, int ivars_n, int sym, double speed, const palette_collection * const pc, randctx *rc); void flam3_cross(flam3_genome *cp0, flam3_genome *cp1, flam3_genome *out, int cross_mode, randctx *rc); /* return NULL in case of error */ @@ -550,7 +538,7 @@ flam3_genome *flam3_parse_from_file(FILE *f, char *fn, int default_flag, int *nc 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, randctx * const); +void flam3_improve_colors(flam3_genome *g, int ntries, int change_palette, int color_resolution, const palette_collection * const pc, randctx * const rc); int flam3_colorhist(flam3_genome *cp, int num_batches, randctx *rc, double *hist); int flam3_estimate_bounding_box(flam3_genome *g, double eps, int nsamples, double *bmin, double *bmax, randctx *rc); diff --git a/interpolation.c b/interpolation.c index 271330d..f161b4b 100644 --- a/interpolation.c +++ b/interpolation.c @@ -18,6 +18,8 @@ #include "interpolation.h" #include "palettes.h" +#include + double adjust_percentage(double in) { if (in==0.0) @@ -140,6 +142,7 @@ int compare_xforms(const void *av, const void *bv) { return 0; } +#if 0 void interpolate_cmap(flam3_palette cmap, double blend, int index0, double hue0, int index1, double hue1, randctx * const rc) { @@ -179,6 +182,7 @@ void interpolate_cmap(flam3_palette cmap, double blend, cmap[i].index = t4; } } +#endif void interp_and_convert_back(double *c, int ncps, int xfi, double cxang[4][2], double cxmag[4][2], double cxtrn[4][2],double store_array[3][2]) { @@ -356,7 +360,6 @@ double get_stagger_coef(double t, double stagger_prc, int num_xforms, int this_x } - /* all cpi and result must be aligned (have the same number of xforms, and have final xform in the same slot) */ void flam3_interpolate_n(flam3_genome *result, int ncp, @@ -365,56 +368,43 @@ void flam3_interpolate_n(flam3_genome *result, int ncp, if (flam3_palette_interpolation_hsv == cpi[0].palette_interpolation) { - for (i = 0; i < 256; i++) { - double s4; + for (i = 0; i < cpi[0].palette.count; i++) { double4 s, t; int alpha1 = 1; - s[0] = s[1] = s[2] = s[3] = s4 = 0.0; + s[0] = s[1] = s[2] = s[3] = 0.0; for (k = 0; k < ncp; k++) { - t = rgb2hsv(vector_d4 (cpi[k].palette[i].color)); + assert (cpi[k].palette.count == cpi[0].palette.count); + t = rgb2hsv(cpi[k].palette.color[i]); for (j = 0; j < 3; j++) s[j] += c[k] * t[j]; - s[3] += c[k] * cpi[k].palette[i].color[3]; - if (cpi[k].palette[i].color[3] != 1.0) + s[3] += c[k] * cpi[k].palette.color[i][3]; + if (cpi[k].palette.color[i][3] != 1.0) alpha1 = 0; - s4 += c[k] * cpi[k].palette[i].index; - } if (alpha1 == 1) s[3] = 1.0; const double4 ret_color = hsv2rgb(s); - result->palette[i].color[0] = ret_color[0]; - result->palette[i].color[1] = ret_color[1]; - result->palette[i].color[2] = ret_color[2]; - result->palette[i].color[3] = s[3]; - result->palette[i].index = s4; + palette_add (&result->palette, (double4) { ret_color[0], ret_color[1], + ret_color[2], s[3] }); - for (j = 0; j < 4; j++) { - if (result->palette[i].color[j] < 0.0) - result->palette[i].color[j] = 0.0; - if (result->palette[i].color[j] > 1.0) - result->palette[i].color[j] = 1.0; - } - - if (result->palette[i].index < 0.0) - result->palette[i].index = 0.0; - if (result->palette[i].index > 255.0) - result->palette[i].index = 255.0; } } else { + /* XXX: broken */ + assert (0); +#if 0 /* Sweep - not the best option for float indices */ - for (i = 0; i < 256; i++) { - j = (i < (256 * c[0])) ? 0 : 1; - result->palette[i] = cpi[j].palette[i]; + for (i = 0; i < cpi[0].palette.count; i++) { + j = (i < (cpi[j].palette.count * c[0])) ? 0 : 1; + palette_add (&result->palette, cpi[j].palette.color[i]); } +#endif } - result->palette_index = flam3_palette_random; result->symmetry = 0; result->palette_mode = cpi[0].palette_mode; @@ -431,11 +421,7 @@ void flam3_interpolate_n(flam3_genome *result, int ncp, INTERP(center[1]); INTERP(rot_center[0]); INTERP(rot_center[1]); - INTERP(background[0]); - INTERP(background[1]); - INTERP(background[2]); INTERP(pixels_per_unit); - INTERP(sample_density); INTERP(zoom); INTERP(rotate); INTERP(gam_lin_thresh); diff --git a/interpolation.h b/interpolation.h index 61ea49d..21e333e 100644 --- a/interpolation.h +++ b/interpolation.h @@ -43,8 +43,10 @@ void mult_matrix(double s1[2][2], double s2[2][2], double d[2][2]); int compare_xforms(const void *av, const void *bv); +#if 0 void interpolate_cmap(flam3_palette cmap, double blend, int index0, double hue0, int index1, double hue1, randctx * const); +#endif void interp_and_convert_back(double *c, int ncps, int xfi, double cxang[4][2], double cxmag[4][2], double cxtrn[4][2],double store_array[3][2]); void convert_linear_to_polar(flam3_genome *cp, int ncps, int xfi, int cflag, diff --git a/main.c b/main.c index c490d50..1b3fba6 100644 --- a/main.c +++ b/main.c @@ -224,9 +224,13 @@ static void do_random (const random_arguments * const arguments) { randctx rc; rand_seed(&rc); + palette_collection pc; + bool bret = palette_read_collection ("flam3-palettes.xml", &pc); + assert (bret); + flam3_genome genome = { .edits = NULL }; int ivars = flam3_variation_random; - flam3_random (&genome, &ivars, 1, arguments->symmetry, 0, &rc); + flam3_random (&genome, &ivars, 1, arguments->symmetry, 0, &pc, &rc); /* random resets genome, adjust before finding appropriate bbox */ genome.width = arguments->width; @@ -299,12 +303,16 @@ static void do_mutate (const mutate_arguments * const arguments) { } assert (ncps == 1); + palette_collection pc; + bool bret = palette_read_collection ("flam3-palettes.xml", &pc); + assert (bret); + flam3_genome * const genome = &cps[0]; int ivars = flam3_variation_random; const double speed = 1.0; flam3_mutate (genome, arguments->method, &ivars, 1, arguments->symmetry, - speed, &rc); + speed, &pc, &rc); print_genome (genome); } diff --git a/palettes.c b/palettes.c index 80a8532..03b2c08 100644 --- a/palettes.c +++ b/palettes.c @@ -1,5 +1,6 @@ /* Copyright (C) 1992-2009 Spotworks LLC + Copyright (C) 2015 pucket contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,181 +22,119 @@ #include "palettes.h" #include "rect.h" -lib_palette *the_palettes = NULL; -int npalettes; +/* Add color to the end of palette + */ +void palette_add (palette * const p, const double4 c) { + ++p->count; + if (p->count > p->allocated || p->color == NULL) { + double4 *newcolors; + if (p->allocated == 0) { + /* flam3’s default palette size */ + p->allocated = 256; + } else { + p->allocated *= 2; + } + int ret = posix_memalign ((void **) &newcolors, sizeof (*newcolors), + sizeof (*newcolors) * p->allocated); + assert (ret == 0 && newcolors != NULL); + memcpy (newcolors, p->color, + (p->count-1)*sizeof (*p->color)); + free (p->color); + p->color = newcolors; + } + p->color[p->count-1] = c; +} -static void parse_palettes(xmlNode *node) { - xmlAttrPtr attr; - char *val; - lib_palette *pal; - int hex_error; - - while (node) { - if (node->type == XML_ELEMENT_NODE && !xmlStrcmp(node->name, (const xmlChar *)"palette")) { - attr = node->properties; - pal = &the_palettes[npalettes]; - memset(pal, 0, sizeof(lib_palette)); - - while (attr) { - val = (char *) xmlGetProp(node, attr->name); - if (!xmlStrcmp(attr->name, (const xmlChar *)"data")) { - int count = 256; - int c_idx = 0; - int r,g,b; - int col_count = 0; - int sscanf_ret; - - c_idx=0; - col_count = 0; - hex_error = 0; - - do { - sscanf_ret = sscanf((char *)&(val[c_idx]),"00%2x%2x%2x",&r,&g,&b); - if (sscanf_ret != 3) { - fprintf(stderr,"error: problem reading hexadecimal color data '%8s'\n",&val[c_idx]); - hex_error = 1; - break; - } - c_idx += 8; - while (isspace( (int)val[c_idx])) - c_idx++; - - pal->colors[col_count][0] = (double)r/255.0; - pal->colors[col_count][1] = (double)g/255.0; - pal->colors[col_count][2] = (double)b/255.0; - - col_count++; - } while (col_countname, (const xmlChar *)"number")) { - pal->number = atoi(val); - } else if (!xmlStrcmp(attr->name, (const xmlChar *)"name")) { - strncpy(pal->name, val, flam3_name_len); - pal->name[flam3_name_len-1] = 0; - } - - xmlFree(val); - attr = attr->next; - } - - if (hex_error == 0) { - npalettes++; - the_palettes = realloc(the_palettes, (1 + npalettes) * sizeof(lib_palette)); - } - } else - parse_palettes(node->children); - - node = node->next; - } +static void parse_palettes(xmlNode *node, palette_collection * const pc) { + /* node can be NULL */ + assert (pc != NULL); + + while (node) { + if (node->type == XML_ELEMENT_NODE && + !xmlStrcmp(node->name, (const xmlChar *)"palette")) { + xmlAttrPtr attr = node->properties; + + ++pc->count; + pc->p = realloc (pc->p, pc->count * sizeof (*pc->p)); + assert (pc->p != NULL); + + palette * const p = &pc->p[pc->count-1]; + memset (p, 0, sizeof (*p)); + + while (attr) { + char *val = (char *) xmlGetProp(node, attr->name); + if (!xmlStrcmp(attr->name, (const xmlChar *)"data")) { + int c_idx = 0; + + while (val[c_idx] != '\0') { + if (isspace( (int)val[c_idx])) { + c_idx++; + } else { + unsigned int r,g,b; + const int sscanf_ret = sscanf((char *)&(val[c_idx]), + "00%2x%2x%2x",&r,&g,&b); + assert (sscanf_ret == 3); + + palette_add (p, (double4) { (double) r/255.0, + (double) g/255.0, (double) b/255.0, 1.0 }); + + c_idx += 8; + } + } + } + + xmlFree(val); + attr = attr->next; + } + } else + parse_palettes(node->children, pc); + + node = node->next; + } } -static int init_palettes(char *filename) { - FILE *fp; - xmlDocPtr doc; - xmlNode *rootnode; - int i, c, slen = 5000; - char *s; - - fp = fopen(filename, "rb"); - if (NULL == fp) { - fprintf(stderr, "flam3: could not open palette file "); - perror(filename); - return(-1); - } - - /* Incrementally read XML file into a string */ - s = malloc(slen); - i = 0; - do { - c = getc(fp); - if (EOF == c) { - if (ferror(fp)) { - perror(filename); - return(-1); - } - break; - } - s[i++] = c; - if (i == slen-1) { - slen *= 2; - s = realloc(s, slen); - } - } while (1); +/* Read palette collection from file + */ +bool palette_read_collection (const char * const filename, + palette_collection * const pc) { + xmlDocPtr doc; + xmlNode *rootnode; - fclose(fp); - s[i] = 0; - - doc = xmlReadMemory(s, (int)strlen(s), filename, NULL, XML_PARSE_NONET); - if (NULL == doc) { - fprintf(stderr, "error parsing %s (%s).\n", filename, s); - return(-1); - } - rootnode = xmlDocGetRootElement(doc); - the_palettes = malloc(sizeof(lib_palette)); - npalettes = 0; - parse_palettes(rootnode); - xmlFreeDoc(doc); - - free(s); - xmlCleanupParser(); - return(1); -} + if ((doc = xmlReadFile (filename, NULL, XML_PARSE_NONET)) == NULL) { + return false; + } -int flam3_get_palette(int n, flam3_palette c, double hue_rotation, randctx * const rc) { - int cmap_len = 256; - int idx, i, j, rcode; + memset (pc, 0, sizeof (*pc)); - // set palette to all white in case there are problems - for (i = 0; i < cmap_len; i++) { - c[i].index = i; - for (j = 0; j < 4; j++) - c[i].color[j] = 1.0; - } + rootnode = xmlDocGetRootElement(doc); + parse_palettes (rootnode, pc); + xmlFreeDoc(doc); - if (NULL == the_palettes) { - rcode = init_palettes("flam3-palettes.xml"); - if (rcode<0) { - fprintf(stderr,"error reading xml palette file, setting to all white\n"); - return(-1); - } - } - - if (flam3_palette_random == n) - n = the_palettes[rand_mod(rc, npalettes)].number; + return true; +} - for (idx = 0; idx < npalettes; idx++) { - - if (n == the_palettes[idx].number) { - /* Loop over elements of cmap */ - for (i = 0; i < cmap_len; i++) { - int ii = (i * 256) / cmap_len; - double4 rgb, hsv; - - rgb = (double4) { - the_palettes[idx].colors[ii][0], - the_palettes[idx].colors[ii][1], - the_palettes[idx].colors[ii][2], - 1.0, - }; - - hsv = rgb2hsv(rgb); - hsv[0] += hue_rotation * 6.0; - rgb = hsv2rgb(hsv); - - c[i].index = i; - - c[i].color[0] = rgb[0]; - c[i].color[1] = rgb[1]; - c[i].color[2] = rgb[2]; - c[i].color[3] = 1.0; - } - - return n; - } - } - - fprintf(stderr, "warning: palette number %d not found, using white.\n", n); +const palette *palette_random (const palette_collection * const pc, + randctx * const rc) { + size_t i = rand_mod (rc, pc->count); + return &pc->p[i]; +} - return(-1); +void palette_copy (const palette * const src, palette * const dest) { + dest->count = src->count; + int ret = posix_memalign ((void **) &dest->color, sizeof (*dest->color), + sizeof (*dest->color) * dest->count); + assert (ret == 0 && dest->color != NULL); + memcpy (dest->color, src->color, dest->count * sizeof (*dest->color)); +} + +void palette_rotate_hue (palette * const p, double rot) { + for (unsigned int i = 0; i < p->count; i++) { + double4 rgb = p->color[i]; + double4 hsv = rgb2hsv(rgb); + hsv[0] += rot * 6.0; + rgb = hsv2rgb(hsv); + p->color[i] = rgb; + } } /* rgb 0 - 1, @@ -360,8 +299,6 @@ static double try_colors(flam3_genome *g, int color_resolution) { flam3_copy(&saved, g); - g->sample_density = 1; - /* Scale the image so that the total number of pixels is ~10000 */ pixtotal = g->width * g->height; scalar = sqrt( 10000.0 / (double)pixtotal); @@ -419,7 +356,6 @@ static double try_colors(flam3_genome *g, int color_resolution) { free(hist); free(image); - g->sample_density = saved.sample_density; g->width = saved.width; g->height = saved.height; g->pixels_per_unit = saved.pixels_per_unit; @@ -430,14 +366,15 @@ static double try_colors(flam3_genome *g, int color_resolution) { return (double) (hits / res3); } -static void change_colors(flam3_genome *g, int change_palette, randctx * const rc) { +static void change_colors(flam3_genome *g, int change_palette, + const palette_collection * const pc, randctx * const rc) { int i; int x0, x1; if (change_palette) { g->hue_rotation = 0.0; - g->palette_index = flam3_get_palette(flam3_palette_random, g->palette, 0.0, rc); - if (g->palette_index < 0) - fprintf(stderr,"error retrieving random palette, setting to all white\n"); + const palette * const p = palette_random (pc, rc); + assert (p != NULL); + palette_copy (p, &g->palette); } for (i = 0; i < g->num_xforms; i++) { g->xform[i].color = rand_d01(rc); @@ -448,7 +385,7 @@ static void change_colors(flam3_genome *g, int change_palette, randctx * const r 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, 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) { int i; double best, b; flam3_genome best_genome; @@ -463,7 +400,7 @@ void flam3_improve_colors(flam3_genome *g, int ntries, int change_palette, int c flam3_copy(&best_genome,g); for (i = 0; i < ntries; i++) { - change_colors(g, change_palette, rc); + 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"); diff --git a/palettes.h b/palettes.h index 967c30b..2603c99 100644 --- a/palettes.h +++ b/palettes.h @@ -1,5 +1,6 @@ /* Copyright (C) 1992-2009 Spotworks LLC + Copyright (C) 2015 pucket contributors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,15 +16,27 @@ along with this program. If not, see . */ -#ifndef palettes_included -#define palettes_included +#pragma once +#include +#include +#include "flam3.h" + +/* One palette */ +typedef struct { + /* number of items allocated */ + size_t allocated; + /* number of items in palette */ + size_t count; + double4 *color; +} palette; + +/* A collection/array of palettes */ typedef struct { - int number; - char name[flam3_name_len]; - double colors[256][3]; -} lib_palette; + size_t count; + palette *p; +} palette_collection; #include "vector.h" @@ -32,6 +45,10 @@ double4 hsv2rgb(double4); double flam3_calc_alpha(double density, double gamma, double linrange); double4 flam3_calc_newrgb(double4 cbuf, double ls, double highpow); - -#endif +void palette_add (palette * const p, const double4 c); +const palette *palette_random (const palette_collection * const pc, randctx * const rc); +void palette_copy (const palette * const src, palette * const dest); +void palette_rotate_hue (palette * const p, double rot); +bool palette_read_collection (const char * const filename, + palette_collection * const pc); diff --git a/parser.c b/parser.c index a5bb9af..46198f9 100644 --- a/parser.c +++ b/parser.c @@ -18,6 +18,7 @@ #include "parser.h" #include "interpolation.h" #include +#include static int flam3_conversion_failed; @@ -78,6 +79,7 @@ int var2n(const char *s) { return flam3_variation_none; } +#if 0 int flam3_parse_hexformat_colors(char *colstr, flam3_genome *cp, int numcolors, int chan) { int c_idx=0; @@ -129,7 +131,9 @@ int flam3_parse_hexformat_colors(char *colstr, flam3_genome *cp, int numcolors, return(0); } +#endif +#if 0 int flam3_interp_missing_colors(flam3_genome *cp) { /* Check for a non-full palette */ @@ -209,6 +213,7 @@ int flam3_interp_missing_colors(flam3_genome *cp) { return(0); } +#endif void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag, flam3_genome **all_cps, int *all_ncps, randctx * const rc) { @@ -218,7 +223,6 @@ void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag flam3_genome *genome_storage = *all_cps; /* To simplify semantics */ size_t f3_storage; int pfe_success; - int col_success; memset(&loc_current_cp,0,sizeof(flam3_genome)); @@ -251,18 +255,7 @@ void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag /* Clear out the realloc'd memory */ memset(&(genome_storage[*all_ncps]),0,sizeof(flam3_genome)); - if (loc_current_cp.palette_index != -1) { - col_success = flam3_get_palette(loc_current_cp.palette_index, loc_current_cp.palette, - loc_current_cp.hue_rotation, rc); - if (col_success < 0) - fprintf(stderr,"error retrieving palette %d, setting to all white\n",loc_current_cp.palette_index); - } - - col_success = flam3_interp_missing_colors(&loc_current_cp); - loc_current_cp.genome_index = *all_ncps; - memset(loc_current_cp.parent_fname, 0, flam3_parent_fn_len); - strncpy(loc_current_cp.parent_fname,parent_file,flam3_parent_fn_len-1); flam3_copy(&(genome_storage[*all_ncps]), &loc_current_cp); (*all_ncps) ++; @@ -300,15 +293,6 @@ int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, /* Store this flame element in the current cp */ - /* Wipe out the current palette, replace with -1 for each element */ - for (i=0;i<256;i++) { - cp->palette[i].color[0] = 0; - cp->palette[i].color[1] = 0; - cp->palette[i].color[2] = 0; - cp->palette[i].color[3] = 0; - cp->palette[i].index = -1; - } - /* The top level element is a flame element. */ /* Read the attributes of it and store them. */ att_ptr = flame_node->properties; @@ -365,8 +349,6 @@ int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, cp->flame_name[i] = '_'; } - } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"palette")) { - cp->palette_index = flam3_atoi(att_str); } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"size")) { if (sscanf(att_str, "%d %d%1s", &cp->width, &cp->height, tmps) != 2) { fprintf(stderr,"error: invalid size attribute '%s'\n",att_str); @@ -394,14 +376,6 @@ int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, cp->palette_mode = PALETTE_MODE_LINEAR; else fprintf(stderr,"warning: unrecognized palette mode %s. Using step.\n",att_str); - } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"quality")) { - cp->sample_density = flam3_atof(att_str); - } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"background")) { - if (sscanf(att_str, "%lf %lf %lf%1s", &cp->background[0], &cp->background[1], &cp->background[2], tmps) != 3) { - fprintf(stderr,"error: invalid background attribute '%s'\n",att_str); - xmlFree(att_str); - return(1); - } } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"brightness")) { cp->brightness = flam3_atof(att_str); /* } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"contrast")) { @@ -474,18 +448,12 @@ int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, xmlFree(att_str); } + + assert (cp->palette.count == index); + const double4 c = (double4) { r/255.0, g/255.0, b/255.0, a/255.0 }; + palette_add (&cp->palette, c); - if (index >= 0 && index <= 255) { - cp->palette[index].color[3] = a / 255.0; - /* Don't forget to premultiply the palette... */ - cp->palette[index].color[0] = cp->palette[index].color[3] * r / 255.0; - cp->palette[index].color[1] = cp->palette[index].color[3] * g / 255.0; - cp->palette[index].color[2] = cp->palette[index].color[3] * b / 255.0; - cp->palette[index].index = index; - } else { - fprintf(stderr,"Error: Color element with bad/missing index attribute (%d)\n",index); - return(1); - } +#if 0 } else if (!xmlStrcmp(chld_node->name, (const xmlChar *)"colors")) { int count = 0; @@ -519,7 +487,6 @@ int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, xmlFree(att_str); } - } else if (!xmlStrcmp(chld_node->name, (const xmlChar *)"palette")) { /* This could be either the old form of palette or the new form */ @@ -608,6 +575,7 @@ int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, xmlFree(pal_str); } +#endif } else if (!xmlStrcmp(chld_node->name, (const xmlChar *)"symmetry")) { int kind=0; diff --git a/parser.h b/parser.h index f42a468..e76f812 100644 --- a/parser.h +++ b/parser.h @@ -15,20 +15,23 @@ along with this program. If not, see . */ -#ifndef parser_included -#define parser_included +#pragma once #include "private.h" int flam3_atoi(char *nstr); double flam3_atof(char *nstr); int var2n(const char *s); +#if 0 int flam3_parse_hexformat_colors(char *colstr, flam3_genome *cp, int numcolors, int chan); +#endif void scan_for_flame_nodes(xmlNode *cur_node, char *parent_file, int default_flag, flam3_genome **all_cp, int *all_ncps, randctx * const); int parse_flame_element(xmlNode *flame_node, flam3_genome *loc_current_cp, randctx * const); int parse_xform_xml(xmlNode *chld_node,flam3_xform *this_xform, int *num_xaos, flam3_chaos_entry **xaos, int numstd, int motionxf); void flam3_edit_print(FILE *f, xmlNodePtr editNode, int tabs, int formatting); +#if 0 int flam3_interp_missing_colors(flam3_genome *cp); #endif + diff --git a/rect.c b/rect.c index c63da37..b964e45 100644 --- a/rect.c +++ b/rect.c @@ -40,30 +40,29 @@ typedef struct { /* Lookup color [0,1] */ static double4 color_palette_lookup (const double color, - const color_palette_mode mode, const flam3_palette_entry * const map, - const unsigned int map_count) { + const color_palette_mode mode, const palette * const map) { assert (color >= 0.0 && color <= 1.0); switch (mode) { case PALETTE_MODE_LINEAR: { - const double ix = color * map_count; + const double ix = color * map->count; const double bottomix = floor (ix); const double frac = ix - bottomix; const unsigned int intix = bottomix; - if (intix == map_count-1) { - return vector_d4 (map[intix].color); + if (intix == map->count-1) { + return map->color[intix]; } else { - const double4 c1 = vector_d4 (map[intix].color); - const double4 c2 = vector_d4 (map[intix+1].color); + const double4 c1 = map->color[intix]; + const double4 c2 = map->color[intix+1]; return c1 * (1.0-frac) + c2 * frac; } break; } case PALETTE_MODE_STEP: { - const unsigned int intix = nearbyint (color * (map_count-1)); - return vector_d4 (map[intix].color); + const unsigned int intix = nearbyint (color * (map->count-1)); + return map->color[intix]; break; } @@ -80,6 +79,7 @@ static void iter_thread (flam3_genome * const input_genome, rand_seed (&rc); flam3_genome genome; + memset (&genome, 0, sizeof (genome)); flam3_copy (&genome, input_genome); double4 *iter_storage; @@ -134,8 +134,7 @@ static void iter_thread (flam3_genome * const input_genome, #endif double4 interpcolor = color_palette_lookup (p[2], - genome.palette_mode, input_genome->palette, - 256); + genome.palette_mode, &input_genome->palette); const double logvis = p[3]; if (logvis != 1.0) { -- cgit v1.2.3