/* FLAM3 - cosmic recursive fractal flames Copyright (C) 1992-2009 Spotworks LLC 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 the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include "random.h" #include "private.h" #include "img.h" #define streq(a,b) (strcmp (a, b) == 0) const char *argp_program_version = "vlam3-pre"; typedef struct { bool verbose; unsigned int threads, bpc, quality, oversample, width, height; float scale; } render_arguments; static error_t parse_render_opt (int key, char *arg, struct argp_state * const state) { render_arguments * const arguments = state->input; switch (key) { case 'b': { int i = atoi (arg); if (i == 8 || i == 16) { arguments->bpc = i; } else { argp_error (state, "Bits per channel must be 8 or 16"); } break; } case 'h': { int i = atoi (arg); if (i <= 0) { argp_error (state, "Height must be > 0"); } else { arguments->height = i; } break; } case 'o': { int i = atoi (arg); if (i < 1) { argp_error (state, "Oversample must be >= 1"); } else { arguments->oversample = i; } break; } case 'q': { int i = atoi (arg); if (i < 1) { argp_error (state, "Quality must be >= 1"); } else { arguments->quality = i; } break; } case 's': arguments->scale = atof (arg); if (arguments->scale <= 0.0) { argp_error (state, "Scale must be > 0"); } break; case 't': { int i = atoi (arg); if (i <= 0) { argp_error (state, "Threads must be > 0"); } else { arguments->threads = i; } break; } case 'w': { int i = atoi (arg); if (i <= 0) { argp_error (state, "Width must be > 0"); } else { arguments->width = i; } break; } case ARGP_KEY_ARG: if (state->arg_num > 0) { return ARGP_ERR_UNKNOWN; } break; case ARGP_KEY_END: break; default: return ARGP_ERR_UNKNOWN; break; } return 0; } static void do_render (const render_arguments * const arguments) { randctx rc; rand_seed(&rc); int ncps; flam3_genome * const cps = flam3_parse_from_file (stdin, NULL, flam3_defaults_on, &ncps, &rc); if (cps == NULL) { fprintf(stderr,"error reading genomes from file\n"); exit(1); } assert (ncps == 1); flam3_genome * const genome = &cps[0]; /* Force ntemporal_samples to 1 for -render */ genome->ntemporal_samples = 1; genome->sample_density = arguments->quality; if (arguments->height != 0) { genome->height = arguments->height; } if (arguments->width != 0) { genome->width = arguments->width; } genome->height *= arguments->scale; genome->width *= arguments->scale; genome->pixels_per_unit *= arguments->scale; genome->spatial_oversample = arguments->oversample; flam3_frame f; f.genomes = genome; f.ngenomes = 1; f.verbose = arguments->verbose; f.time = 0.0; f.pixel_aspect_ratio = 1.0; f.progress = 0; f.nthreads = arguments->threads; f.earlyclip = 0; f.sub_batch_size = 10000; f.bytes_per_channel = arguments->bpc / 8; const unsigned int channels = 4; const size_t this_size = channels * genome->width * genome->height * f.bytes_per_channel; void *image = (void *) calloc(this_size, sizeof(char)); stat_struct stats; if (flam3_render (&f, image, flam3_field_both, &stats)) { fprintf(stderr,"error rendering image: aborting.\n"); exit(1); } flam3_img_comments fpc; write_png (stdout, image, genome->width, genome->height, &fpc, f.bytes_per_channel); } typedef struct { int symmetry; const char *palette; } random_arguments; static void do_random (const random_arguments * const arguments) { randctx rc; rand_seed(&rc); flam3_genome genome = { .edits = NULL }; int ivars = flam3_variation_random; flam3_random (&genome, &ivars, 1, arguments->symmetry, 0, &rc); flam3_print (stdout, &genome, NULL, flam3_dont_print_edits); fflush(stdout); } typedef struct { int method; unsigned int symmetry; } mutate_arguments; static error_t parse_mutate_opt (int key, char *arg, struct argp_state * const state) { mutate_arguments * const arguments = state->input; switch (key) { case 'm': if (arg == NULL) { arguments->method = MUTATE_NOT_SPECIFIED; } else if (streq (arg, "all-vars")) { arguments->method = MUTATE_ALL_VARIATIONS; } else if (streq(arg,"one-xform")) { arguments->method = MUTATE_ONE_XFORM_COEFS; } else if (streq(arg,"add-symmetry")) { arguments->method = MUTATE_ADD_SYMMETRY; } else if (streq(arg,"post-xforms")) { arguments->method = MUTATE_POST_XFORMS; } else if (streq(arg,"color-palette")) { arguments->method = MUTATE_COLOR_PALETTE; } else if (streq(arg,"delete-xform")) { arguments->method = MUTATE_DELETE_XFORM; } else if (streq(arg,"all-coefs")) { arguments->method = MUTATE_ALL_COEFS; } else { argp_error (state, "Unknown method %s", arg); } break; case ARGP_KEY_ARG: if (state->arg_num > 0) { return ARGP_ERR_UNKNOWN; } break; case ARGP_KEY_END: break; default: return ARGP_ERR_UNKNOWN; break; } return 0; } static void do_mutate (const mutate_arguments * const arguments) { randctx rc; rand_seed(&rc); int ncps; flam3_genome * const cps = flam3_parse_from_file (stdin, NULL, flam3_defaults_on, &ncps, &rc); if (cps == NULL) { fprintf(stderr,"error reading genomes from file\n"); exit(1); } assert (ncps == 1); 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); printf("\n", flam3_version()); flam3_print (stdout, genome, NULL, flam3_dont_print_edits); printf("\n"); fflush(stdout); } typedef struct { int method; } cross_arguments; static error_t parse_cross_opt (int key, char *arg, struct argp_state * const state) { mutate_arguments * const arguments = state->input; switch (key) { case 'm': if (arg == NULL) { arguments->method = CROSS_NOT_SPECIFIED; } else if (streq(arg,"union")) { arguments->method = CROSS_UNION; } else if (streq(arg,"interpolate")) { arguments->method = CROSS_INTERPOLATE; } else if (streq(arg,"alternate")) { arguments->method = CROSS_ALTERNATE; } else { argp_error (state, "Unknown method %s", arg); } break; case ARGP_KEY_ARG: if (state->arg_num > 0) { return ARGP_ERR_UNKNOWN; } break; case ARGP_KEY_END: break; default: return ARGP_ERR_UNKNOWN; break; } return 0; } static void do_cross (const cross_arguments * const arguments) { randctx rc; rand_seed(&rc); int ncps; flam3_genome * const cps = flam3_parse_from_file (stdin, NULL, flam3_defaults_on, &ncps, &rc); if (cps == NULL) { fprintf(stderr,"error reading genomes from file\n"); exit(1); } assert (ncps == 2); flam3_genome * const genome_a = &cps[0], * const genome_b = &cps[1]; flam3_genome genome_out; flam3_cross (genome_a, genome_b, &genome_out, arguments->method, &rc); printf("\n", flam3_version()); flam3_print (stdout, &genome_out, NULL, flam3_dont_print_edits); printf("\n"); fflush(stdout); } #if 0 static void do_improvecolors () { flam3_improve_colors(&cp_orig, 100, 0, 10, &rc); } static void do_interpolate () { for (ftime = first_frame; ftime <= last_frame; ftime += 1) { iscp=0; for (i=0;i