summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2015-10-04 15:35:30 -0400
committerTavian Barnes <tavianator@tavianator.com>2015-10-04 15:35:30 -0400
commitd95e93bf70f3351e6fd489284794ef7909fd94ce (patch)
tree0093ab92fe45d92c73e1bce97a92efe69da2866a
parent51baf3067c368e1c638f708e0d166cc2227149b0 (diff)
downloadkd-forest-d95e93bf70f3351e6fd489284794ef7909fd94ce.tar.xz
Make striping optional.HEADmaster
-rw-r--r--main.c123
-rw-r--r--options.c10
-rw-r--r--options.h1
3 files changed, 79 insertions, 55 deletions
diff --git a/main.c b/main.c
index 055c854..109f9f6 100644
--- a/main.c
+++ b/main.c
@@ -40,6 +40,10 @@ typedef struct {
uint32_t *colors;
pixel_t *pixels;
png_byte **bitmap;
+ unsigned int iteration;
+ unsigned int update_interval;
+ unsigned int frame;
+ size_t max_boundary;
} state_t;
static void init_state(state_t *state, const options_t *options);
@@ -109,6 +113,10 @@ init_state(state_t *state, const options_t *options)
state->colors = generate_colors(options);
state->pixels = create_pixels(options);
state->bitmap = create_bitmap(options);
+ state->iteration = 0;
+ state->update_interval = 1U << (state->options->bit_depth + 1)/2;
+ state->frame = 0;
+ state->max_boundary = 0;
}
static void generate_bitmap(state_t *state);
@@ -342,91 +350,96 @@ print_progress(const char *format, ...)
}
static void
-generate_bitmap(state_t *state)
+place_color(state_t *state, kd_forest_t *kdf, unsigned int i)
{
- // Make the forest
- kd_forest_t kdf;
- kdf_init(&kdf);
+ if (state->iteration % state->update_interval == 0) {
+ if (state->options->animate) {
+ char filename[strlen(state->options->filename) + 10];
+ sprintf(filename, "%s/%04u.png", state->options->filename, state->frame);
+ write_png(state, filename);
+ ++state->frame;
+ }
- bool animate = state->options->animate;
- unsigned int frame = 0;
- char filename[strlen(state->options->filename) + 10];
+ print_progress("%.2f%%\t| boundary size: %zu\t| max boundary size: %zu",
+ 100.0*state->iteration/state->options->ncolors, kdf->size, state->max_boundary);
+ }
- size_t max_size = 0;
- unsigned int update_interval = 1U << (state->options->bit_depth + 1)/2;
+ uint32_t color = state->colors[i];
- // Do multiple passes to get rid of artifacts in HUE_SORT mode
- unsigned int bit_depth = state->options->bit_depth;
- for (unsigned int i = 1, progress = 0; i <= bit_depth + 1; ++i) {
- unsigned int stripe = 1 << i;
+ double target[KD_DIMEN];
+ switch (state->options->color_space) {
+ case COLOR_SPACE_RGB:
+ color_set_RGB(target, color);
+ break;
+ case COLOR_SPACE_LAB:
+ color_set_Lab(target, color);
+ break;
+ case COLOR_SPACE_LUV:
+ color_set_Luv(target, color);
+ break;
+ }
- for (unsigned int j = stripe/2 - 1; j < state->options->ncolors; j += stripe, ++progress) {
- if (progress % update_interval == 0) {
- if (animate) {
- sprintf(filename, "%s/%04u.png", state->options->filename, frame);
- write_png(state, filename);
- ++frame;
- }
+ pixel_t *pixel;
+ if (state->iteration == 0) {
+ pixel = get_pixel(state, state->options->x, state->options->y);
+ } else {
+ pixel = find_next_pixel(state, kdf, target);
+ }
- print_progress("%.2f%%\t| boundary size: %zu\t| max boundary size: %zu",
- 100.0*progress/state->options->ncolors, kdf.size, max_size);
- }
+ memcpy(pixel->value, target, sizeof(target));
+ insert_new_pixel(state, kdf, pixel);
+ if (kdf->size > state->max_boundary) {
+ state->max_boundary = kdf->size;
+ }
- uint32_t color = state->colors[j];
-
- double target[KD_DIMEN];
- switch (state->options->color_space) {
- case COLOR_SPACE_RGB:
- color_set_RGB(target, color);
- break;
- case COLOR_SPACE_LAB:
- color_set_Lab(target, color);
- break;
- case COLOR_SPACE_LUV:
- color_set_Luv(target, color);
- break;
- }
+ png_byte *png_pixel = state->bitmap[pixel->y] + 4*pixel->x;
+ color_unpack(png_pixel, color);
+ png_pixel[3] = 0xFF;
+}
- pixel_t *pixel;
- if (j == 0) {
- pixel = get_pixel(state, state->options->x, state->options->y);
- } else {
- pixel = find_next_pixel(state, &kdf, target);
- }
+static void
+generate_bitmap(state_t *state)
+{
+ // Make the forest
+ kd_forest_t kdf;
+ kdf_init(&kdf);
- memcpy(pixel->value, target, sizeof(target));
- insert_new_pixel(state, &kdf, pixel);
- if (kdf.size > max_size) {
- max_size = kdf.size;
+ if (state->options->stripe) {
+ for (unsigned int i = 1; i <= state->options->bit_depth + 1; ++i) {
+ unsigned int stripe = 1 << i;
+ for (unsigned int j = stripe/2 - 1; j < state->options->ncolors; j += stripe, ++state->iteration) {
+ place_color(state, &kdf, j);
}
-
- png_byte *png_pixel = state->bitmap[pixel->y] + 4*pixel->x;
- color_unpack(png_pixel, color);
- png_pixel[3] = 0xFF;
+ }
+ } else {
+ for (unsigned int i = 0; i < state->options->ncolors; ++i, ++state->iteration) {
+ place_color(state, &kdf, i);
}
}
- if (animate) {
+ if (state->options->animate) {
+ char filename[strlen(state->options->filename) + 10];
+
#if __unix__
sprintf(filename, "%s/last.png", state->options->filename);
write_png(state, filename);
for (int i = 0; i < 120; ++i) {
- sprintf(filename, "%s/%04u.png", state->options->filename, frame + i);
+ sprintf(filename, "%s/%04u.png", state->options->filename, state->frame + i);
if (symlink("last.png", filename) != 0) {
abort();
}
}
#else
for (int i = 0; i < 120; ++i) {
- sprintf(filename, "%s/%04u.png", state->options->filename, frame + i);
+ sprintf(filename, "%s/%04u.png", state->options->filename, state->frame + i);
write_png(state, filename);
}
#endif
}
print_progress("%.2f%%\t| boundary size: %zu\t| max boundary size: %zu\n",
- 100.0, kdf.size, max_size);
+ 100.0, kdf.size, state->max_boundary);
kdf_destroy(&kdf);
}
diff --git a/options.c b/options.c
index 7834c58..e25930a 100644
--- a/options.c
+++ b/options.c
@@ -226,6 +226,7 @@ print_usage(FILE *file, const char *command, bool verbose)
usage("Usage:\n");
usage(" !$! *%s* [-b|--bit-depth @DEPTH@]\n", command);
usage(" %s [-s|--hue-sort] [-r|--random] [-M|--morton] [-H|--hilbert]\n", whitespace);
+ usage(" %s [-t|--stripe] [-T|--no-stripe]\n", whitespace);
usage(" %s [-l|--selection @min@|@mean@]\n", whitespace);
usage(" %s [-c|--color-space @RGB@|@Lab@|@Luv@]\n", whitespace);
usage(" %s [-w|--width @WIDTH@] [-h|--height @HEIGHT@]\n", whitespace);
@@ -250,6 +251,10 @@ print_usage(FILE *file, const char *command, bool verbose)
usage(" Place colors in Morton order (Z\\-order)\n");
usage(" -H, --hilbert:\n");
usage(" Place colors in Hilbert curve order\n\n");
+ usage(" -t, --stripe:\n");
+ usage(" -T, --no-stripe:\n");
+ usage(" Whether to reduce artifacts by iterating through the colors in\n");
+ usage(" multiple stripes (!default!: --stripe)\n\n");
usage(" -l, --selection @min@|@mean@:\n");
usage(" Specify the selection mode (!default!: @min@)\n\n");
usage(" @min@: Pick the pixel with the closest neighboring pixel\n");
@@ -281,6 +286,7 @@ parse_options(options_t *options, int argc, char *argv[])
// Set defaults
options->bit_depth = 24;
options->mode = MODE_HUE_SORT;
+ options->stripe = true;
options->selection = SELECTION_MIN;
options->color_space = COLOR_SPACE_LAB;
options->animate = false;
@@ -311,6 +317,10 @@ parse_options(options_t *options, int argc, char *argv[])
options->mode = MODE_MORTON;
} else if (parse_arg(argc, argv, "-H", "--hilbert", NULL, &i, &error)) {
options->mode = MODE_HILBERT;
+ } else if (parse_arg(argc, argv, "-t", "--stripe", NULL, &i, &error)) {
+ options->stripe = true;
+ } else if (parse_arg(argc, argv, "-T", "--no-stripe", NULL, &i, &error)) {
+ options->stripe = false;
} else if (parse_arg(argc, argv, "-l", "--selection", &value, &i, &error)) {
if (strcmp(value, "min") == 0) {
options->selection = SELECTION_MIN;
diff --git a/options.h b/options.h
index 62038a4..07ecc45 100644
--- a/options.h
+++ b/options.h
@@ -40,6 +40,7 @@ typedef enum {
typedef struct {
unsigned int bit_depth;
mode_t mode;
+ bool stripe;
selection_t selection;
color_space_t color_space;
unsigned int width, height;