ae836788da4f7728de4674384cfb6a6dfd4df522
[gencolormap.git] / cmdline.cpp
1 /*
2  * Copyright (C) 2015, 2016 Computer Graphics Group, University of Siegen
3  * Written by Martin Lambers <martin.lambers@uni-siegen.de>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23
24 #include <vector>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 #include <cmath>
29
30 #include <getopt.h>
31 extern char *optarg;
32 extern int optind;
33
34 #include "colormap.hpp"
35
36 enum type {
37     brewer_sequential = 0,
38     brewer_diverging = 1,
39     brewer_qualitative = 2,
40     cubehelix = 3
41 };
42
43 int main(int argc, char* argv[])
44 {
45     bool print_version = false;
46     bool print_help = false;
47     int type = -1;
48     int n = -1;
49     float hue = -1.0f;
50     float divergence = -1.0f;
51     float contrast = -1.0f;
52     float saturation = -1.0f;
53     float brightness = -1.0f;
54     float warmth = -1.0f;
55     float rotations = NAN;
56     float gamma = -1.0f;
57     struct option options[] = {
58         { "version",    no_argument,       0, 'v' },
59         { "help",       no_argument,       0, 'H' },
60         { "type",       required_argument, 0, 't' },
61         { "n",          required_argument, 0, 'n' },
62         { "hue",        required_argument, 0, 'h' },
63         { "divergence", required_argument, 0, 'd' },
64         { "contrast",   required_argument, 0, 'c' },
65         { "saturation", required_argument, 0, 's' },
66         { "brightness", required_argument, 0, 'b' },
67         { "warmth",     required_argument, 0, 'w' },
68         { "rotations",  required_argument, 0, 'r' },
69         { "gamma",      required_argument, 0, 'g' },
70         { 0, 0, 0, 0 }
71     };
72
73     for (;;) {
74         int c = getopt_long(argc, argv, "vHt:n:h:d:c:s:b:w:r:g:", options, NULL);
75         if (c == -1)
76             break;
77         switch (c) {
78         case 'v':
79             print_version = true;
80             break;
81         case 'H':
82             print_help = true;
83             break;
84         case 't':
85             type = (strcmp(optarg, "brewer-sequential") == 0 ? brewer_sequential
86                     : strcmp(optarg, "brewer-diverging") == 0 ? brewer_diverging
87                     : strcmp(optarg, "brewer-qualitative") == 0 ? brewer_qualitative
88                     : strcmp(optarg, "cubehelix") == 0 ? cubehelix
89                     : -2);
90             break;
91         case 'n':
92             n = atoi(optarg);
93             break;
94         case 'h':
95             hue = atof(optarg) * M_PI / 180.0;
96             break;
97         case 'd':
98             divergence = atof(optarg) * M_PI / 180.0;
99             break;
100         case 'c':
101             contrast = atof(optarg);
102             break;
103         case 's':
104             saturation = atof(optarg);
105             break;
106         case 'b':
107             brightness = atof(optarg);
108             break;
109         case 'w':
110             warmth = atof(optarg);
111             break;
112         case 'r':
113             rotations = atof(optarg);
114             break;
115         case 'g':
116             gamma = atof(optarg);
117             break;
118         default:
119             return 1;
120         }
121     }
122
123     if (print_version) {
124         printf("gencolormap version 0.2\n"
125                 "Copyright (C) 2016 Computer Graphics Group, University of Siegen.\n"
126                 "Written by Martin Lambers <martin.lambers@uni-siegen.de>.\n"
127                 "This is free software under the terms of the MIT/Expat License.\n"
128                 "There is NO WARRANTY, to the extent permitted by law.\n");
129         return 0;
130     }
131
132     if (print_help) {
133         printf("Usage: %s\n"
134                 "  Common options, required for all types:\n"
135                 "    -n|--n=N                      Set number of colors in the map\n"
136                 "  Brewer-like color maps:\n"
137                 "    -t|--type=brewer-sequential   Generate a sequential color map\n"
138                 "    -t|--type=brewer-diverging    Generate a diverging color map\n"
139                 "    -t|--type=brewer-qualitative  Generate a qualitative color map\n"
140                 "    [-h|--hue=H]                  Set default hue in [0,360] degrees\n"
141                 "    [-c|--contrast=C]             Set contrast in [0,1]\n"
142                 "    [-s|--saturation=S]           Set saturation in [0,1]\n"
143                 "    [-b|--brightness=B]           Set brightness in [0,1]\n"
144                 "    [-w|--warmth=W]               Set warmth in [0,1] for seq. and div. maps\n"
145                 "    [-d|--divergence=D]           Set divergence for div. and qual. maps\n"
146                 "  CubeHelix color maps:\n"
147                 "    -t|--type=cubehelix           Generate a CubeHelix color map\n"
148                 "    [-r|--rotations=R]            Set number of rotations, in (-infty,infty)\n"
149                 "    [-s|--saturation=S]           Set saturation, in [0,1]\n"
150                 "    [-g|--gamma=G]                Set gamma correction, in (0,infty)\n"
151                 "Generates a color map and prints it to standard output as sRGB triplets.\n"
152                 "Report bugs to <martin.lambers@uni-siegen.de>.\n", argv[0]);
153         return 0;
154     }
155
156     if (type < 0) {
157         fprintf(stderr, "Invalid or missing option -t|--type.\n");
158         return 1;
159     }
160     if (n < 2) {
161         fprintf(stderr, "Invalid or missing option -n|--n.\n");
162         return 1;
163     }
164     if (hue < 0.0f) {
165         if (type == brewer_sequential)
166             hue = ColorMap::BrewerSequentialDefaultHue;
167         else if (type == brewer_diverging)
168             hue = ColorMap::BrewerDivergingDefaultHue;
169         else if (type == brewer_qualitative)
170             hue = ColorMap::BrewerQualitativeDefaultHue;
171         else if (type == cubehelix)
172             hue = ColorMap::CubeHelixDefaultHue;
173     }
174     if (divergence < 0.0f) {
175         if (type == brewer_diverging)
176             divergence = ColorMap::BrewerDivergingDefaultDivergence;
177         else if (type == brewer_qualitative)
178             divergence = ColorMap::BrewerQualitativeDefaultDivergence;
179     }
180     if (contrast < 0.0f) {
181         if (type == brewer_sequential)
182             contrast = (n <= 9 ? ColorMap::BrewerSequentialDefaultContrastForSmallN(n)
183                     : ColorMap::BrewerSequentialDefaultContrast);
184         else if (type == brewer_diverging)
185             contrast = (n <= 9 ? ColorMap::BrewerDivergingDefaultContrastForSmallN(n)
186                     : ColorMap::BrewerDivergingDefaultContrast);
187         else if (type == brewer_qualitative)
188             contrast = ColorMap::BrewerQualitativeDefaultContrast;
189     }
190     if (saturation < 0.0f) {
191         if (type == brewer_sequential)
192             saturation = ColorMap::BrewerSequentialDefaultSaturation;
193         else if (type == brewer_diverging)
194             saturation = ColorMap::BrewerDivergingDefaultSaturation;
195         else if (type == brewer_qualitative)
196             saturation = ColorMap::BrewerQualitativeDefaultSaturation;
197         else if (type == cubehelix)
198             saturation = ColorMap::CubeHelixDefaultSaturation;
199     }
200     if (brightness < 0.0f) {
201         if (type == brewer_sequential)
202             brightness = ColorMap::BrewerSequentialDefaultBrightness;
203         else if (type == brewer_diverging)
204             brightness = ColorMap::BrewerDivergingDefaultBrightness;
205         else if (type == brewer_qualitative)
206             brightness = ColorMap::BrewerQualitativeDefaultBrightness;
207     }
208     if (warmth < 0.0f) {
209         if (type == brewer_sequential)
210             brightness = ColorMap::BrewerSequentialDefaultWarmth;
211         else if (type == brewer_diverging)
212             brightness = ColorMap::BrewerDivergingDefaultWarmth;
213     }
214     if (std::isnan(rotations)) {
215         if (type == cubehelix)
216             rotations = ColorMap::CubeHelixDefaultRotations;
217     }
218     if (gamma < 0.0f) {
219         if (type == cubehelix)
220             gamma = ColorMap::CubeHelixDefaultGamma;
221     }
222
223     std::vector<unsigned char> colormap(3 * n);
224     switch (type) {
225     case brewer_sequential:
226         ColorMap::BrewerSequential(n, &(colormap[0]), hue, contrast, saturation, brightness, warmth);
227         break;
228     case brewer_diverging:
229         ColorMap::BrewerDiverging(n, &(colormap[0]), hue, divergence, contrast, saturation, brightness, warmth);
230         break;
231     case brewer_qualitative:
232         ColorMap::BrewerQualitative(n, &(colormap[0]), hue, divergence, contrast, saturation, brightness);
233         break;
234     case cubehelix:
235         ColorMap::CubeHelix(n, &(colormap[0]), hue, rotations, saturation, gamma);
236         break;
237     }
238
239     for (int i = 0; i < n; i++) {
240         printf("%d, %d, %d\n", colormap[3 * i + 0], colormap[3 * i + 1], colormap[3 * i + 2]);
241     }
242
243     return 0;
244 }