atomorph/demo/options.h

227 lines
13 KiB
C++

/*
* See Copyright Notice in main.h
*/
#include <getopt.h>
class MORPH_OPTIONS {
public:
MORPH_OPTIONS() {}
~MORPH_OPTIONS() {}
const int AS_TEXTURE = am::TEXTURE;
const int AS_AVERAGE = am::AVERAGE;
const int AS_DISTINCT= am::DISTINCT;
const int BY_RGB = am::RGB;
const int BY_HSP = am::HSP;
const int MOTION_NONE = am::NONE;
const int MOTION_LINEAR = am::LINEAR;
const int MOTION_SPLINE = am::SPLINE;
const int FADING_NONE = am::NONE;
const int FADING_LINEAR = am::LINEAR;
const int FADING_COSINE = am::COSINE;
const int FADING_PERLIN = am::PERLIN;
int verbose = 0;
int blend_blobs = 0;
int finite = 0;
int keep_background= 0;
int show_blobs = AS_TEXTURE;
int differ_blobs = BY_HSP;
int motion = MOTION_SPLINE;
int fading = FADING_PERLIN;
int exit_flag = 0;
std::string name = "";
std::string indir = ".";
std::string outdir = ".";
std::string file = "untitled_morph";
int height = 0;
int width = 0;
unsigned seed = 0;
unsigned frames_out= 0;
unsigned match_time= 1;
unsigned morph_time= 3;
unsigned feather = 0;
unsigned fluid = 0;
unsigned cycle_length=100000;
unsigned threads =8;
size_t blob_number = 1;
size_t blob_max_size = SIZE_MAX;
size_t blob_min_size = 1;
uint16_t blob_box_grip = UINT16_MAX;
size_t blob_box_samples = 100;
double blob_threshold = 1.0;
unsigned char blob_rgba_weight = 1;
unsigned char blob_size_weight = 1;
unsigned char blob_xy_weight = 1;
size_t degenerate = 10000;
uint16_t density = 2;
bool frames_out_defined = false;
std::vector<std::string> files;
inline void print_usage (FILE* stream) {
fprintf (stream, "Usage: %s [options] <input files...>\n", name.c_str());
fprintf (stream, "Example: %s data/otu_1.png data/otu_2.png data/otu_3.png --verbose\n", name.c_str());
fprintf (stream, "Options:\n");
fprintf (stream,
" --blend-blobs Blob intersections are blended together.\n"
" -E --blob-feather INT Number of gradually transparent outer layers.\n"
" -c --blob-rgba-weight[0-255] Importance of a blob's color when matching.\n"
" -z --blob-size-weight[0-255] Importance of a blob's size when matching.\n"
" -p --blob-xy-weight [0-255] Importance of a blob's location when matching.\n"
" -b --blobs INT Preferred number of blobs to keep.\n"
" --blobs-as-texture A blob is textured by its pixels (default).\n"
" --blobs-as-average A blob has the average color of its pixels.\n"
" --blobs-as-distinct A blob has a random color.\n"
" --blobs-by-rgb Differentiate blobs by RGB distance.\n"
" --blobs-by-hsp Differentiate blobs by HSP distance (default).\n"
" -B --blobs-max-size INT Maximum size of a single blob in pixels.\n"
" -m --blobs-min-size INT Minimum size of a single blob in pixels.\n"
" -g --blobs-box-grip INT Unifying grip bounds for undersized blobs.\n"
" -S --blobs-box-samples INT Number of samples to take for each dust box.\n"
" -t --blobs-threshold [0-255] Maximum color difference for merging blobs.\n"
" --brief Print brief messages (default).\n"
" -C --cycle-length INT Number of iterations per morph cycle.\n"
" -d --degenerate INT Degeneration period for energy minimzation.\n"
" -D --density INT Number of atoms per pixel at minimum.\n"
" --fading-none Colours are not interpolated.\n"
" --fading-linear Colours are interpolated linearly.\n"
" --fading-cosine Colours are cosine interpolated.\n"
" --fading-perlin Use Perlin noise colour transition (default).\n"
" -f --file STR Output files with prefix.\n"
" --finite Morph will not repeat itself seamlessly.\n"
" -L --fluid INT Number of fluid simulation steps per frame.\n"
" -F --frames INT Number of frames to generate.\n"
" -h --help Display this usage information.\n"
" -i --indir STR Read input from this directory.\n"
" --keep-background Morph background is cross-dissolved.\n"
" -M --match-time INT Time in seconds given for blob matching.\n"
" -O --morph-time INT Time in seconds given for atom morphing.\n"
" --motion-none Positions are not interpolated.\n"
" --motion-linear Positions are linearly interpolated.\n"
" --motion-spline Uses Catmull-Rom splines (default).\n"
" -o --outdir STR Write output to this directory.\n"
" -s --seed INT Seed for the random number generator.\n"
" -T --threads INT Number of worker threads to spawn.\n"
" --verbose Print verbose messages.\n"
" -v --version Show version information.\n"
);
}
inline bool parse(int argc, char **argv) {
int c;
name = argv[0];
while (1) {
static struct option long_options[] = {
// These options set a flag:
{"verbose", no_argument, &verbose, 1 },
{"blend-blobs", no_argument, &blend_blobs, 1 },
{"finite", no_argument, &finite, 1 },
{"blobs-as-texture", no_argument, &show_blobs, AS_TEXTURE },
{"blobs-as-average", no_argument, &show_blobs, AS_AVERAGE },
{"blobs-as-distinct", no_argument, &show_blobs, AS_DISTINCT },
{"blobs-by-rgb", no_argument, &differ_blobs, BY_RGB },
{"blobs-by-hsp", no_argument, &differ_blobs, BY_HSP },
{"brief", no_argument, &verbose, 0 },
{"keep-background", no_argument, &keep_background, 1 },
// These options don't set a flag. We distinguish them by their indices:
{"blob-feather", required_argument, 0, 'E'},
{"blob-rgba-weight", required_argument, 0, 'c'},
{"blob-size-weight", required_argument, 0, 'z'},
{"blob-xy-weight", required_argument, 0, 'p'},
{"blobs", required_argument, 0, 'b'},
{"blobs-max-size", required_argument, 0, 'B'},
{"blobs-min-size", required_argument, 0, 'm'},
{"blobs-box-grip", required_argument, 0, 'g'},
{"blobs-box-samples", required_argument, 0, 'S'},
{"blobs-threshold", required_argument, 0, 't'},
{"cycle-length", required_argument, 0, 'C'},
{"degenerate", required_argument, 0, 'd'},
{"density", required_argument, 0, 'D'},
{"fading-none", no_argument, &fading, FADING_NONE },
{"fading-linear", no_argument, &fading, FADING_LINEAR },
{"fading-cosine", no_argument, &fading, FADING_COSINE },
{"fading-perlin", no_argument, &fading, FADING_PERLIN },
{"file", required_argument, 0, 'f'},
{"fluid", required_argument, 0, 'L'},
{"frames", required_argument, 0, 'F'},
{"help", no_argument, 0, 'h'},
{"indir", required_argument, 0, 'i'},
{"match-time", required_argument, 0, 'M'},
{"morph-time", required_argument, 0, 'O'},
{"motion-none", no_argument, &motion, MOTION_NONE },
{"motion-linear", no_argument, &motion, MOTION_LINEAR },
{"motion-spline", no_argument, &motion, MOTION_SPLINE },
{"outdir", required_argument, 0, 'o'},
{"seed", required_argument, 0, 's'},
{"threads", required_argument, 0, 'T'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0 }
};
// getopt_long stores the option index here.
int option_index = 0;
c = getopt_long(argc, argv, "b:B:c:C:d:D:E:m:M:O:g:p:S:t:T:f:L:F:hi:o:s:vz:", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1) break;
switch (c) {
case 0: // If this option set a flag, do nothing else now.
if (long_options[option_index].flag != 0) break;
printf ("option %s", long_options[option_index].name);
if (optarg) printf(" with arg %s", optarg); printf ("\n");
break;
case 'E': feather = atoi(optarg); break;
case 'c': blob_rgba_weight= std::min(atoi(optarg),255); break;
case 'z': blob_size_weight= std::min(atoi(optarg),255); break;
case 'p': blob_xy_weight = std::min(atoi(optarg),255); break;
case 'b': blob_number = (size_t) atoi(optarg); break;
case 'B': blob_max_size = atoi(optarg); break;
case 'C': cycle_length = atoi(optarg); break;
case 'd': degenerate = (size_t) atoi(optarg); break;
case 'D': density = (uint16_t) atoi(optarg); break;
case 'm': blob_min_size = atoi(optarg); break;
case 'M': match_time = atoi(optarg); break;
case 'O': morph_time = atoi(optarg); break;
case 'g': blob_box_grip = atoi(optarg); break;
case 'S': blob_box_samples= atoi(optarg); break;
case 't': blob_threshold = std::min(atoi(optarg),255)/255.0; break;
case 's': seed = atoi(optarg); break;
case 'T': threads = std::min(atoi(optarg),1024); break;
case 'L': fluid = atoi(optarg); break;
case 'F': frames_out = atoi(optarg); break;
case 'i': indir = optarg; break;
case 'o': outdir = optarg; break;
case 'f': file = optarg; break;
case 'h': print_usage(stdout); exit_flag = 1; break;
case 'v':
printf("AtoMorph %s Copyright (C) 2013-2014 Erich Erstu\n", am::get_version());
exit_flag = 1;
break;
case '?':
/* getopt_long already printed an error message. */
break;
default: return false;
}
}
while (optind < argc) {
files.push_back(argv[optind++]);
}
if (frames_out == 0) {
if (files.size() > 1) frames_out = files.size()*2;
else frames_out = 1;
}
return true;
}
};