@@ -1552,6 +1552,68 @@ GMT_LOCAL void gmtsupport_truncate_cpt_slice (struct GMT_LUT *S, bool do_hsv, do
1552
1552
S->i_dz = 1.0 / (S->z_high - S->z_low);
1553
1553
}
1554
1554
1555
+ void gmt_explain_cpt_output (struct GMTAPI_CTRL *API, char option) {
1556
+ /* Display usage synopsis for -F cpt output/categorical option in makecpt/grd2cpt */
1557
+
1558
+ GMT_Usage (API, 1, "\n-%c%s", option, GMT_COLORMODES_OPT);
1559
+ GMT_Usage (API, -2, "Select the color model for output [Default uses the input model]:");
1560
+ GMT_Usage (API, 3, "R: Output r/g/b or colornames.");
1561
+ GMT_Usage (API, 3, "c: Output c/m/y/k.");
1562
+ GMT_Usage (API, 3, "g: Output gray value (Will apply the YIQ if not a gray value).");
1563
+ GMT_Usage (API, 3, "h: Output h-s-v.");
1564
+ GMT_Usage (API, 3, "r: Output r/g/b only.");
1565
+ GMT_Usage (API, 3, "x: Output hex #rrggbb only.");
1566
+ GMT_Usage (API, -2, "Two modifiers control generation of categorical labels:");
1567
+ GMT_Usage (API, 3, "+c Output a discrete CPT in categorical CPT format. "
1568
+ "The <label>, if appended, sets the labels for each category. It may be a "
1569
+ "comma-separated list of category names, or <start>[-] where we automatically build "
1570
+ "labels from <start> (a letter or an integer). Append - to build range labels <start>-<start+1>.");
1571
+ GMT_Usage (API, 3, "+k Set categorical keys rather than numerical values. "
1572
+ "<keys> may be a file with one key per line or a comma-separated list of keys. "
1573
+ "If <keys> is a single letter then we build sequential alphabetical keys from that letter. "
1574
+ "If number of categories is 12 and label is M then we auto-create month name labels, and "
1575
+ "if it is 7 and label is D then we auto-create weekday name labels.");
1576
+ }
1577
+
1578
+ int gmt_prepare_categorical_cpt (struct GMT_CTRL *GMT, char *label, char *key, struct GMT_PALETTE *Pout) {
1579
+ bool got_key_file = (key && !gmt_access (GMT, key, R_OK)); /* Want categorical labels read from file */
1580
+ unsigned int ns = 0;
1581
+ Pout->categorical = GMT_CPT_CATEGORICAL_VAL;
1582
+ if (label || (key && !got_key_file)) { /* Want auto-categorical labels appended to each CPT record */
1583
+ char **Plabel = gmt_cat_cpt_strings (GMT, (label) ? label : key, Pout->n_colors, &ns);
1584
+ for (unsigned int k = 0; k < MIN (Pout->n_colors, ns); k++) {
1585
+ if (Pout->data[k].label) gmt_M_str_free (Pout->data[k].label);
1586
+ if (Plabel[k]) Pout->data[k].label = Plabel[k]; /* Now the job of the CPT to free these strings */
1587
+ }
1588
+ gmt_M_free (GMT, Plabel); /* But the master array can go */
1589
+ }
1590
+ if (key) { /* Want categorical labels */
1591
+ char **keys = NULL;
1592
+ if (got_key_file) { /* Got a file with category keys */
1593
+ ns = gmt_read_list (GMT, key, &keys);
1594
+ if (ns < Pout->n_colors) {
1595
+ GMT_Report (GMT->parent, GMT_MSG_ERROR, "The categorical keys file %s had %d entries but CPT has %d categories\n", key, ns, Pout->n_colors);
1596
+ return (GMT_RUNTIME_ERROR);
1597
+ }
1598
+ else if (ns > Pout->n_colors)
1599
+ GMT_Report (GMT->parent, GMT_MSG_WARNING, "The categorical keys file %s had %d entries but only %d are needed - skipping the extra keys\n", key, ns, Pout->n_colors);
1600
+ }
1601
+ else /* Got comma-separated keys */
1602
+ keys = gmt_cat_cpt_strings (GMT, key, Pout->n_colors, &ns);
1603
+ for (unsigned int k = 0; k < MIN (Pout->n_colors, ns); k++) {
1604
+ if (Pout->data[k].key) gmt_M_str_free (Pout->data[k].key);
1605
+ if (k < ns && keys[k]) {
1606
+ Pout->data[k].key = keys[k]; /* Now the job of the CPT to free these strings */
1607
+ if (Pout->data[k].label) gmt_M_str_free (Pout->data[k].label);
1608
+ Pout->data[k].label = strdup (keys[k]);
1609
+ }
1610
+ }
1611
+ gmt_M_free (GMT, keys); /* But the master array can go */
1612
+ Pout->categorical = GMT_CPT_CATEGORICAL_KEY;
1613
+ }
1614
+ return (GMT_NOERROR);
1615
+ }
1616
+
1555
1617
bool gmt_consider_current_cpt (struct GMTAPI_CTRL *API, bool *active, char **arg) {
1556
1618
/* Modern mode only: Detect if no CPT is given but -C was set.
1557
1619
* If -C[+u|U<arg>] is given (i.e., no cpt) then we take that to mean
@@ -8330,6 +8392,8 @@ struct GMT_PALETTE * gmtlib_read_cpt (struct GMT_CTRL *GMT, void *source, unsign
8330
8392
X->model = GMT_RGB | GMT_COLORINT;
8331
8393
else if (strstr (line, "RGB"))
8332
8394
X->model = GMT_RGB;
8395
+ else if (strstr (line, "+GRAY") || strstr (line, "gray"))
8396
+ X->model = GMT_GRAY | GMT_COLORINT;
8333
8397
else if (strstr (line, "+HSV") || strstr (line, "hsv"))
8334
8398
X->model = GMT_HSV | GMT_COLORINT;
8335
8399
else if (strstr (line, "HSV"))
@@ -9473,6 +9537,9 @@ int gmtlib_write_cpt (struct GMT_CTRL *GMT, void *dest, unsigned int dest_type,
9473
9537
struct CPT_Z_SCALE *Z = NULL; /* For unit manipulations */
9474
9538
struct GMT_PALETTE_HIDDEN *PH = NULL;
9475
9539
9540
+ if (cpt_flags & GMT_CPT_GRAY_SET && !P->is_gray)
9541
+ GMT_Report (GMT->parent, GMT_MSG_INFORMATION, "Colors in the CPT file %s were converted to gray via the YIQ-translation.\n", &cpt_file[append]);
9542
+
9476
9543
/* When writing the CPT to file it is no longer a normalized CPT with a hinge */
9477
9544
P->has_range = P->has_hinge = 0;
9478
9545
@@ -9537,6 +9604,8 @@ int gmtlib_write_cpt (struct GMT_CTRL *GMT, void *dest, unsigned int dest_type,
9537
9604
gmtlib_write_newheaders (GMT, fp, 0); /* Write general header block */
9538
9605
9539
9606
if (!(P->model & GMT_COLORINT)) {} /* Write nothing when color interpolation is not forced */
9607
+ else if (P->model & GMT_GRAY)
9608
+ fprintf (fp, "# COLOR_MODEL = gray\n");
9540
9609
else if (P->model & GMT_HSV)
9541
9610
fprintf (fp, "# COLOR_MODEL = hsv\n");
9542
9611
else if (P->model & GMT_CMYK)
@@ -9562,6 +9631,8 @@ int gmtlib_write_cpt (struct GMT_CTRL *GMT, void *dest, unsigned int dest_type,
9562
9631
9563
9632
if (P->categorical) {
9564
9633
if (P->categorical & GMT_CPT_CATEGORICAL_KEY) strncpy (lo, P->data[i].key, GMT_LEN64-1);
9634
+ if (P->model & GMT_GRAY)
9635
+ fprintf (fp, format, lo, gmt_putgray (GMT, P->data[i].hsv_low), '\t');
9565
9636
if (P->model & GMT_HSV)
9566
9637
fprintf (fp, format, lo, gmtlib_puthsv (GMT, P->data[i].hsv_low), '\t');
9567
9638
else if (P->model & GMT_CMYK) {
@@ -9575,6 +9646,10 @@ int gmtlib_write_cpt (struct GMT_CTRL *GMT, void *dest, unsigned int dest_type,
9575
9646
else
9576
9647
fprintf (fp, format, lo, gmt_putcolor (GMT, P->data[i].rgb_low), '\t');
9577
9648
}
9649
+ else if (P->model & GMT_GRAY) {
9650
+ fprintf (fp, format, lo, gmt_putgray (GMT, P->data[i].rgb_low), '\t');
9651
+ fprintf (fp, format, hi, gmt_putgray (GMT, P->data[i].rgb_high), '\t');
9652
+ }
9578
9653
else if (P->model & GMT_HSV) {
9579
9654
fprintf (fp, format, lo, gmtlib_puthsv (GMT, P->data[i].hsv_low), '\t');
9580
9655
fprintf (fp, format, hi, gmtlib_puthsv (GMT, P->data[i].hsv_high), '\t');
@@ -9615,6 +9690,8 @@ int gmtlib_write_cpt (struct GMT_CTRL *GMT, void *dest, unsigned int dest_type,
9615
9690
if (!use[i]) continue; /* This BNF entry does not apply to this CPT */
9616
9691
if (P->bfn[i].skip)
9617
9692
fprintf (fp, "%c\t-\n", code[i]);
9693
+ else if (P->model & GMT_GRAY)
9694
+ fprintf (fp, "%c\t%s\n", code[i], gmt_putgray (GMT, P->bfn[i].rgb));
9618
9695
else if (P->model & GMT_HSV)
9619
9696
fprintf (fp, "%c\t%s\n", code[i], gmtlib_puthsv (GMT, P->bfn[i].hsv));
9620
9697
else if (P->model & GMT_CMYK) {
0 commit comments