summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2015-03-15 17:08:55 +0100
committerLars-Dominik Braun <lars@6xq.net>2015-05-02 21:36:45 +0200
commitd5a00c0d05030a875ebd85356509ee270bdb7410 (patch)
tree0886c3e0bbc1ee6015f8b160eb3e0a3ea640a9aa
parentb2fc4eb99e9eb6207505252227d716df0527deec (diff)
downloadpucket-d5a00c0d05030a875ebd85356509ee270bdb7410.tar.gz
pucket-d5a00c0d05030a875ebd85356509ee270bdb7410.tar.bz2
pucket-d5a00c0d05030a875ebd85356509ee270bdb7410.zip
Rewrite color palettes
Supports palettes with != 256 colors properly now. A lot of old code still (silently!) relies on that number though.
-rw-r--r--flam3.c113
-rw-r--r--flam3.h28
-rw-r--r--interpolation.c52
-rw-r--r--interpolation.h2
-rw-r--r--main.c12
-rw-r--r--palettes.c287
-rw-r--r--palettes.h33
-rw-r--r--parser.c54
-rw-r--r--parser.h7
-rw-r--r--rect.c21
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;i<numstd;i++)
memcpy(dest->chaos[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;i<ns;i++) {
- free(cp->chaos[i]);
- }
- free(cp->chaos);
- cp->chaos=NULL;
-
- for (i=0;i<cp->num_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, "<color index=\"%d\" rgb=\"%.6g %.6g %.6g\"/>", i, r, g, b);
+ fprintf(f, "<color index=\"%d\" rgb=\"%.6g %.6g %.6g\"/>", i, rgba[0],
+ rgba[1], rgba[2]);
} else {
- fprintf(f, " <color index=\"%d\" rgba=\"%.6g %.6g %.6g %.6g\"/>", i, r, g, b, a);
+ fprintf(f, " <color index=\"%d\" rgba=\"%.6g %.6g %.6g %.6g\"/>", 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;ci<out->palette.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 <assert.h>
+
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_count<count);
- } else if (!xmlStrcmp(attr->name, (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 <http://www.gnu.org/licenses/>.
*/
-#ifndef palettes_included
-#define palettes_included
+#pragma once
+#include <stdlib.h>
+#include <stdbool.h>
+#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 <errno.h>
+#include <assert.h>
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 <http://www.gnu.org/licenses/>.
*/
-#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) {