GRASS Programmer's Manual  6.4.2(2012)
g3dcolor.c
Go to the documentation of this file.
00001 
00002 
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <sys/types.h>
00007 #include <unistd.h>
00008 #include <rpc/types.h>
00009 #include <rpc/xdr.h>
00010 #include <grass/gis.h>
00011 #include "G3d_intern.h"
00012 
00013 static int read_colors(const char *, const char *, const char *,
00014                        struct Colors *);
00015 static int read_new_colors(FILE *, struct Colors *);
00016 static int read_old_colors(FILE *, struct Colors *);
00017 
00018 /*---------------------------------------------------------------------------*/
00019 
00020 int G3d_removeColor(const char *name)
00021  /* adapted from G_remove_colr */
00022 {
00023     char buf[200], secondary[500], buf2[200], xname[512], xmapset[512];
00024 
00025     if (G__name_is_fully_qualified(name, xname, xmapset)) {
00026         sprintf(buf, "%s/%s", G3D_DIRECTORY, xname);
00027         sprintf(buf2, "%s@%s", G3D_COLOR_ELEMENT, xmapset);     /* == color@mapset */
00028     }
00029     else {
00030         sprintf(buf, "%s/%s", G3D_DIRECTORY, name);
00031         sprintf(buf2, "%s", G3D_COLOR_ELEMENT);
00032     }
00033 
00034     G_remove(buf, buf2);
00035 
00036     sprintf(secondary, "%s/%s/%s",
00037             G3D_DIRECTORY, G3D_COLOR2_DIRECTORY, G_mapset());
00038     G_remove(secondary, name);
00039 
00040     return 0;
00041 }
00042 
00043 /*---------------------------------------------------------------------------*/
00044 
00045 int
00046 G3d_readColors(const char *name, const char *mapset, struct Colors *colors)
00047  /* adapted from G_read_colors */
00048 {
00049     char buf[512], buf2[200];
00050     const char *err;
00051     char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
00052     struct FPRange drange;
00053     DCELL dmin, dmax;
00054 
00055     G_init_colors(colors);
00056 
00057     if (G__name_is_fully_qualified(name, xname, xmapset)) {
00058         if (strcmp(xmapset, mapset) != 0)
00059             return -1;
00060         name = xname;
00061     }
00062 
00063     sprintf(buf, "%s/%s/%s", G3D_DIRECTORY, G3D_COLOR2_DIRECTORY, mapset);
00064     if (read_colors(buf, name, G_mapset(), colors) >= 0)
00065         return 1;
00066 
00067     G_mark_colors_as_fp(colors);
00068 
00069     /* now look for the regular color table */
00070     /*if (G__name_is_fully_qualified (name, xname, xmapset)) {
00071        sprintf (buf, "%s/%s", G3D_DIRECTORY, xname);
00072        sprintf (buf2, "%s@%s", G3D_COLOR_ELEMENT, xmapset); // == color@mapset
00073        //} else { */
00074     sprintf(buf, "%s/%s", G3D_DIRECTORY, name);
00075     sprintf(buf2, "%s", G3D_COLOR_ELEMENT);
00076     /*//}
00077      */
00078 
00079     switch (read_colors(buf, buf2, mapset, colors)) {
00080     case -2:
00081         if (G3d_readRange(name, mapset, &drange) >= 0) {
00082             G_get_fp_range_min_max(&drange, &dmin, &dmax);
00083             if (!G_is_d_null_value(&dmin) && !G_is_d_null_value(&dmax))
00084                 G_make_rainbow_fp_colors(colors, dmin, dmax);
00085             return 0;
00086         }
00087         err = "missing";
00088         break;
00089     case -1:
00090         err = "invalid";
00091         break;
00092     default:
00093         return 1;
00094     }
00095 
00096     G_warning("color support for [%s] in mapset [%s] %s", name, mapset, err);
00097     return -1;
00098 }
00099 
00100 static int read_colors(const char *element, const char *name,
00101                        const char *mapset, struct Colors *colors)
00102 {
00103     FILE *fd;
00104     int stat;
00105     char buf[1024];
00106 
00107     if (!(fd = G_fopen_old(element, name, mapset)))
00108         return -2;
00109 
00110     /*
00111      * first line in 4.0 color files is %
00112      * otherwise it is pre 4.0
00113      */
00114     if (fgets(buf, sizeof buf, fd) == NULL) {
00115         fclose(fd);
00116         return -1;
00117     }
00118     fseek(fd, 0L, 0);
00119 
00120     G_strip(buf);
00121     if (*buf == '%') {          /* 4.0 format */
00122         stat = read_new_colors(fd, colors);
00123         colors->version = 0;    /* 4.0 format */
00124     }
00125     else {
00126         stat = read_old_colors(fd, colors);
00127         colors->version = -1;   /* pre 4.0 format */
00128     }
00129     fclose(fd);
00130     return stat;
00131 }
00132 
00133 /* parse input lines with the following formats
00134  *   val1:r:g:b val2:r:g:b
00135  *   val:r:g:b          (implies cat1==cat2)
00136  *
00137  * r:g:b can be just a single grey level
00138  *   cat1:x cat2:y
00139  *   cat:x
00140  *
00141  * optional lines are
00142  *    invert            invert color table
00143  *    shift:n           where n is the amount to shift the color table
00144  */
00145 static int read_new_colors(FILE * fd, struct Colors *colors)
00146 {
00147     double val1, val2;
00148     long cat1, cat2;
00149     int r1, g1, b1;
00150     int r2, g2, b2;
00151     char buf[1024];
00152     char word1[256], word2[256];
00153     int n, fp_rule;
00154     int null, undef;
00155     int modular;
00156     DCELL shift;
00157 
00158     if (fgets(buf, sizeof buf, fd) == NULL)
00159         return -1;
00160     G_strip(buf);
00161 
00162     if (sscanf(buf + 1, "%lf %lf", &val1, &val2) == 2)
00163         G_set_d_color_range((DCELL) val1, (DCELL) val2, colors);
00164 
00165     modular = 0;
00166     while (fgets(buf, sizeof buf, fd)) {
00167         null = undef = fp_rule = 0;
00168         *word1 = *word2 = 0;
00169         n = sscanf(buf, "%s %s", word1, word2);
00170         if (n < 1)
00171             continue;
00172 
00173         if (sscanf(word1, "shift:%lf", &shift) == 1
00174             || (strcmp(word1, "shift:") == 0 &&
00175                 sscanf(word2, "%lf", &shift) == 1)) {
00176             G_shift_d_colors(shift, colors);
00177             continue;
00178         }
00179         if (strcmp(word1, "invert") == 0) {
00180             G_invert_colors(colors);
00181             continue;
00182         }
00183         if (strcmp(word1, "%%") == 0) {
00184             modular = !modular;
00185             continue;
00186         }
00187 
00188         switch (sscanf(word1, "nv:%d:%d:%d", &r1, &g1, &b1)) {
00189         case 1:
00190             null = 1;
00191             b1 = g1 = r1;
00192             break;
00193         case 3:
00194             null = 1;
00195             break;
00196         }
00197         if (!null)
00198             switch (sscanf(word1, "*:%d:%d:%d", &r1, &g1, &b1)) {
00199             case 1:
00200                 undef = 1;
00201                 b1 = g1 = r1;
00202                 break;
00203             case 3:
00204                 undef = 1;
00205                 break;
00206             }
00207         if (!null && !undef)
00208             switch (sscanf(word1, "%ld:%d:%d:%d", &cat1, &r1, &g1, &b1)) {
00209             case 2:
00210                 b1 = g1 = r1;
00211                 break;
00212             case 4:
00213                 break;
00214             default:
00215                 if (sscanf(word1, "%lf:%d:%d:%d", &val1, &r1, &g1, &b1) == 4)
00216                     fp_rule = 1;
00217                 else if (sscanf(word1, "%lf:%d", &val1, &r1) == 2) {
00218                     fp_rule = 1;
00219                     b1 = g1 = r1;
00220                 }
00221                 else
00222                     continue;   /* other lines are ignored */
00223             }
00224         if (n == 2) {
00225             switch (sscanf(word2, "%ld:%d:%d:%d", &cat2, &r2, &g2, &b2)) {
00226             case 2:
00227                 b2 = g2 = r2;
00228                 if (fp_rule)
00229                     val2 = (DCELL) cat2;
00230                 break;
00231             case 4:
00232                 if (fp_rule)
00233                     val2 = (DCELL) cat2;
00234                 break;
00235             default:
00236                 if (sscanf(word2, "%lf:%d:%d:%d", &val2, &r2, &g2, &b2) == 4) {
00237                     if (!fp_rule)
00238                         val1 = (DCELL) cat1;
00239                     fp_rule = 1;
00240                 }
00241                 else if (sscanf(word2, "%lf:%d", &val2, &r2) == 2) {
00242                     if (!fp_rule)
00243                         val1 = (DCELL) cat1;
00244                     fp_rule = 1;
00245                     b2 = g2 = r2;
00246                 }
00247                 else
00248                     continue;   /* other lines are ignored */
00249             }
00250         }
00251         else {
00252             if (!fp_rule)
00253                 cat2 = cat1;
00254             else
00255                 val2 = val1;
00256             r2 = r1;
00257             g2 = g1;
00258             b2 = b1;
00259         }
00260         if (null)
00261             G_set_null_value_color(r1, g1, b1, colors);
00262         else if (undef)
00263             G_set_default_color(r1, g1, b1, colors);
00264 
00265         else if (modular) {
00266             if (fp_rule)
00267                 G_add_modular_d_raster_color_rule((DCELL *) & val1, r1, g1,
00268                                                   b1, (DCELL *) & val2, r2,
00269                                                   g2, b2, colors);
00270             else
00271                 G_add_modular_color_rule((CELL) cat1, r1, g1, b1,
00272                                          (CELL) cat2, r2, g2, b2, colors);
00273         }
00274         else {
00275             if (fp_rule)
00276                 G_add_d_raster_color_rule((DCELL *) & val1, r1, g1, b1,
00277                                           (DCELL *) & val2, r2, g2, b2,
00278                                           colors);
00279             else
00280                 G_add_color_rule((CELL) cat1, r1, g1, b1,
00281                                  (CELL) cat2, r2, g2, b2, colors);
00282         }
00283         /*
00284            fprintf (stderr, "adding rule %d=%.2lf %d %d %d  %d=%.2lf %d %d %d\n", cat1,val1,  r1, g1, b1, cat2, val2, r2, g2, b2);
00285          */
00286     }
00287     return 1;
00288 }
00289 
00290 static int read_old_colors(FILE * fd, struct Colors *colors)
00291 {
00292     char buf[256];
00293     long n;
00294     long min;
00295     float red_f, grn_f, blu_f;
00296     int red, grn, blu;
00297     int old;
00298     int zero;
00299 
00300     G_init_colors(colors);
00301     /*
00302      * first line in pre 3.0 color files is number of colors - ignore
00303      * otherwise it is #min first color, and the next line is for color 0
00304      */
00305     if (fgets(buf, sizeof buf, fd) == NULL)
00306         return -1;
00307 
00308     G_strip(buf);
00309     if (*buf == '#') {          /* 3.0 format */
00310         old = 0;
00311         if (sscanf(buf + 1, "%ld", &min) != 1)  /* first color */
00312             return -1;
00313         zero = 1;
00314     }
00315     else {
00316         old = 1;
00317         min = 0;
00318         zero = 0;
00319     }
00320 
00321     colors->cmin = min;
00322     n = min;
00323     while (fgets(buf, sizeof buf, fd)) {
00324         if (old) {
00325             if (sscanf(buf, "%f %f %f", &red_f, &grn_f, &blu_f) != 3)
00326                 return -1;
00327 
00328             red = 256 * red_f;
00329             grn = 256 * grn_f;
00330             blu = 256 * blu_f;
00331         }
00332         else {
00333             switch (sscanf(buf, "%d %d %d", &red, &grn, &blu)) {
00334             case 1:
00335                 blu = grn = red;
00336                 break;
00337             case 2:
00338                 blu = grn;
00339                 break;
00340             case 3:
00341                 break;
00342             default:
00343                 return -1;
00344             }
00345         }
00346         if (zero) {
00347             G__insert_color_into_lookup((CELL) 0, red, grn, blu,
00348                                         &colors->fixed);
00349             zero = 0;
00350         }
00351         else
00352             G__insert_color_into_lookup((CELL) n++, red, grn, blu,
00353                                         &colors->fixed);
00354     }
00355     colors->cmax = n - 1;
00356 
00357     return 0;
00358 }
00359 
00360 /*---------------------------------------------------------------------------*/
00361 
00362 int
00363 G3d_writeColors(const char *name, const char *mapset, struct Colors *colors)
00364  /* adapted from G_write_colors */
00365 {
00366     char element[512], buf[512], buf2[200];
00367     char xname[512], xmapset[512];
00368     FILE *fd;
00369     int stat;
00370 
00371     if (G__name_is_fully_qualified(name, xname, xmapset)) {
00372         if (strcmp(xmapset, mapset) != 0)
00373             return -1;
00374         name = xname;
00375     }
00376 
00377     /*
00378      * if mapset is current mapset, remove colr2 file (created by pre 3.0 grass)
00379      *    and then write original color table
00380      * else write secondary color table
00381      */
00382 
00383     sprintf(element, "%s/%s/%s", G3D_DIRECTORY, G3D_COLOR2_DIRECTORY, mapset);
00384     if (strcmp(mapset, G_mapset()) == 0) {
00385         G_remove(element, name);        /* get rid of existing colr2, if any */
00386 
00387         if (G__name_is_fully_qualified(name, xname, xmapset)) {
00388             sprintf(buf, "%s/%s", G3D_DIRECTORY, xname);
00389             sprintf(buf2, "%s@%s", G3D_COLOR_ELEMENT, xmapset); /* == color@mapset */
00390         }
00391         else {
00392             sprintf(buf, "%s/%s", G3D_DIRECTORY, name);
00393             sprintf(buf2, "%s", G3D_COLOR_ELEMENT);
00394         }
00395 
00396         if (!(fd = G_fopen_new(buf, buf2)))
00397             return -1;
00398     }
00399     else {
00400         if (!(fd = G_fopen_new(element, name)))
00401             return -1;
00402     }
00403 
00404     stat = G__write_colors(fd, colors);
00405     fclose(fd);
00406     return stat;
00407 }
00408 
00409 /*---------------------------------------------------------------------------*/
00410 
00411 /*---------------------------------------------------------------------------*/
00412 
00413 /*---------------------------------------------------------------------------*/
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines