GRASS Programmer's Manual 6.4.1(2011)
color_look.c
Go to the documentation of this file.
00001 #include <math.h>
00002 #include <grass/gis.h>
00003 
00004 /* old 4.1 routine */
00005 
00038 int G_lookup_colors(const CELL * cell,
00039                     unsigned char *red, unsigned char *grn,
00040                     unsigned char *blu, unsigned char *set, int n,
00041                     struct Colors *colors)
00042 {
00043     G_lookup_c_raster_colors(cell, red, grn, blu, set, n, colors);
00044 
00045     return 0;
00046 }
00047 
00048 /* I don't think it should exist, because it requires openning
00049    of raster map every time Olga 
00050    int G_lookup_rgb_colors(map, mapset, r, g, b)
00051    char *name, *mapset;
00052    unsigned char *r, *g, *b;
00053    {
00054    RASTER_MAP_TYPE map_type;
00055    void *rast;
00056    ....
00057    }
00058  */
00059 
00060 
00076 int G_lookup_c_raster_colors(const CELL * cell,
00077                              unsigned char *red, unsigned char *grn,
00078                              unsigned char *blu, unsigned char *set, int n,
00079                              struct Colors *colors)
00080 {
00081     G__organize_colors(colors); /* make sure the lookup tables are in place */
00082 
00083     G_zero((char *)set, n * sizeof(unsigned char));
00084 
00085     /* first lookup the fixed colors */
00086     G__lookup_colors((void *)cell, red, grn, blu, set, n, colors, 0, 0,
00087                      CELL_TYPE);
00088 
00089     /* now lookup unset colors using the modular rules */
00090     G__lookup_colors((void *)cell, red, grn, blu, set, n, colors, 1, 0,
00091                      CELL_TYPE);
00092 
00093     return 0;
00094 }
00095 
00096 
00118 int G_lookup_raster_colors(const void *raster,
00119                            unsigned char *red, unsigned char *grn,
00120                            unsigned char *blu, unsigned char *set, int n,
00121                            struct Colors *colors, RASTER_MAP_TYPE map_type)
00122 {
00123     G__organize_colors(colors); /* make sure the lookup tables are in place */
00124     /* in case of float color rules, fp_lookup table is created */
00125 
00126     G_zero((char *)set, n * sizeof(unsigned char));
00127 
00128     /* first lookup the fixed colors */
00129     G__lookup_colors(raster, red, grn, blu, set, n, colors, 0, 0, map_type);
00130 
00131     /* now lookup unset colors using the modular rules */
00132     G__lookup_colors(raster, red, grn, blu, set, n, colors, 1, 0, map_type);
00133 
00134     return 0;
00135 }
00136 
00137 
00155 int G_lookup_f_raster_colors(const FCELL * fcell, unsigned char *red,
00156                              unsigned char *grn, unsigned char *blu,
00157                              unsigned char *set, int n, struct Colors *colors)
00158 {
00159     G__organize_colors(colors); /* make sure the lookup tables are in place */
00160     /* in case of float color rules, fp_lookup table is created */
00161 
00162     G_zero((char *)set, n * sizeof(unsigned char));
00163 
00164     /* first lookup the fixed colors */
00165     G__lookup_colors((void *)fcell, red, grn, blu, set, n, colors, 0, 0,
00166                      FCELL_TYPE);
00167 
00168     /* now lookup unset colors using the modular rules */
00169     G__lookup_colors((void *)fcell, red, grn, blu, set, n, colors, 1, 0,
00170                      FCELL_TYPE);
00171 
00172     return 0;
00173 }
00174 
00175 
00193 int G_lookup_d_raster_colors(const DCELL * dcell, unsigned char *red,
00194                              unsigned char *grn, unsigned char *blu,
00195                              unsigned char *set, int n, struct Colors *colors)
00196 {
00197     G__organize_colors(colors); /* make sure the lookup tables are in place */
00198     /* in case of float color rules, fp_lookup table is created */
00199 
00200     G_zero((char *)set, n * sizeof(unsigned char));
00201 
00202     /* first lookup the fixed colors */
00203     G__lookup_colors((void *)dcell, red, grn, blu, set, n, colors, 0, 0,
00204                      DCELL_TYPE);
00205 
00206     /* now lookup unset colors using the modular rules */
00207     G__lookup_colors((void *)dcell, red, grn, blu, set, n, colors, 1, 0,
00208                      DCELL_TYPE);
00209 
00210     return 0;
00211 }
00212 
00213 
00214 static int less_or_equal(double x, double y)
00215 {
00216     if (x <= y)
00217         return 1;
00218     else
00219         return 0;
00220 }
00221 
00222 static int less(double x, double y)
00223 {
00224     if (x < y)
00225         return 1;
00226     else
00227         return 0;
00228 }
00229 
00230 
00231 int G__lookup_colors(const void *raster, unsigned char *red,
00232                      unsigned char *grn, unsigned char *blu,
00233                      unsigned char *set, int n, struct Colors *colors,
00234                      int mod, int rules_only, RASTER_MAP_TYPE data_type)
00235 {
00236     struct _Color_Info_ *cp;
00237     struct _Color_Rule_ *rule;
00238     DCELL dmin, dmax, val, dmod = 0L, shift;
00239     CELL cat, min, max;
00240     register const void *ptr, *last_ptr = NULL;
00241     int invert;
00242     int found, r, g, b;
00243     int cell_type;
00244     int lookup, max_ind, min_ind, try;
00245     int (*lower) ();
00246 
00247     if (mod)
00248         cp = &colors->modular;
00249     else
00250         cp = &colors->fixed;
00251 
00252     /* rules_only will be true only when called by G__organize_colors()
00253      * when building the integer lookup talbes from the rules,
00254      * so do not shift, invert, use lookup table or modulate cats.
00255      * these operations will happen when lookup is called by user code
00256      */
00257     /* we want min, max for cp, not min, max overall */
00258     dmin = cp->min;
00259     dmax = cp->max;
00260     min = (CELL) dmin;
00261     max = (CELL) dmax + 1;
00262 
00263     cell_type = (data_type == CELL_TYPE);
00264 
00265     if (rules_only) {
00266         shift = invert = lookup = mod = 0;
00267     }
00268     else {
00269         if (mod) {
00270             dmod = dmax - dmin;
00271             /* for integers color table we make a gap of 1 in order
00272                to make the same colors as before */
00273             if (cell_type)
00274                 dmod += 1;
00275         }
00276 
00277         shift = colors->shift;
00278         invert = colors->invert;
00279         lookup = cp->lookup.active;
00280     }
00281 
00282     ptr = raster;
00283 
00284     for (; n-- > 0;
00285          ptr =
00286          G_incr_void_ptr(ptr, G_raster_size(data_type)), red++, grn++, blu++,
00287          *set++ = found) {
00288         /* if the cell is the same as last one, use the prev color values */
00289         if (ptr != raster && G_raster_cmp(ptr, last_ptr, data_type) == 0) {
00290             *red = *(red - 1);
00291             *blu = *(blu - 1);
00292             *grn = *(grn - 1);
00293             found = *(set - 1);
00294             last_ptr = ptr;
00295             continue;
00296         }
00297         val = G_get_raster_value_d(ptr, data_type);
00298         /* DEBUG fprintf (stderr, "val: %.4lf\n", val); */
00299         last_ptr = ptr;
00300 
00301         if (*set) {
00302             found = 1;
00303             continue;
00304         }
00305 
00306         if (G_is_null_value(ptr, data_type)) {
00307             /* returns integers, not unsigned chars */
00308             G_get_null_value_color(&r, &g, &b, colors);
00309             *red = r;
00310             *grn = g;
00311             *blu = b;
00312             found = 1;
00313             continue;
00314         }
00315 
00316         if (shift && val >= dmin && val <= dmax) {
00317             val += shift;
00318             while (val < dmin)
00319                 val += dmax - dmin + 1;
00320             while (val > dmax)
00321                 val -= dmax - dmin + 1;
00322         }
00323 
00324         /* invert non-null data around midpoint of range [min:max] */
00325         if (invert)
00326             val = dmin + dmax - val;
00327 
00328         if (mod) {
00329             if (dmod > 0) {
00330                 val -= dmin;
00331                 while (val < 0)
00332                     val += dmod;
00333                 val = val - dmod * floor(val / dmod);
00334                 val += dmin;
00335             }
00336             else
00337                 val = dmin;
00338         }
00339 
00340         cat = (CELL) val;
00341 
00342         found = 0;
00343 
00344         /* for non-null integers  try to look them up in lookup table */
00345         /* note: lookup table exists only for integer maps, and we also must
00346            check if val is really integer */
00347 
00348         if (lookup && ((double)cat - val == 0.)) {
00349             if (cat >= min && cat <= max) {
00350                 cat -= min;
00351                 if (cp->lookup.set[cat]) {
00352                     *red = cp->lookup.red[cat];
00353                     *grn = cp->lookup.grn[cat];
00354                     *blu = cp->lookup.blu[cat];
00355                     found = 1;
00356                     /*DEBUG
00357                        fprintf (stderr, "lookup %d %.2lf %d %d %d\n\n", cat, val, *red, *grn, *blu);
00358                      */
00359                 }
00360             }
00361         }
00362 
00363         if (found)
00364             continue;
00365 
00366         /* if floating point lookup table is active, look up in there */
00367         if (cp->fp_lookup.active) {
00368             try = (cp->fp_lookup.nalloc - 1) / 2;
00369             min_ind = 0;
00370             max_ind = cp->fp_lookup.nalloc - 2;
00371             while (1) {
00372                 /* when the rule for the interval is NULL, we exclude the end points.
00373                    when it exists, we include the end-points */
00374                 if (cp->fp_lookup.rules[try])
00375                     lower = less;
00376                 else
00377                     lower = less_or_equal;
00378                 /* DEBUG
00379                    fprintf (stderr, "%d %d %d %lf %lf %lf\n", min_ind, try, max_ind,
00380                    cp->fp_lookup.vals[try-1],
00381                    val,
00382                    cp->fp_lookup.vals[try]);
00383                  */
00384 
00385                 if (lower(cp->fp_lookup.vals[try + 1], val)) {  /* recurse to the second half */
00386                     min_ind = try + 1;
00387                     /* must be still < nalloc-1, since number is within the range */
00388                     try = (max_ind + min_ind) / 2;
00389                     if (min_ind > max_ind) {
00390                         rule = NULL;
00391                         break;
00392                     }
00393                     continue;
00394                 }
00395                 if (lower(val, cp->fp_lookup.vals[try])) {      /* recurse to the second half */
00396                     max_ind = try - 1;
00397                     /* must be still >= 0, since number is within the range */
00398                     try = (max_ind + min_ind) / 2;
00399                     if (max_ind < min_ind) {
00400                         rule = NULL;
00401                         break;
00402                     }
00403                     continue;
00404                 }
00405                 rule = cp->fp_lookup.rules[try];
00406                 break;
00407             }
00408         }
00409         else {
00410             /* find the [low:high] rule that applies */
00411             for (rule = cp->rules; rule; rule = rule->next) {
00412                 /* DEBUG
00413                    fprintf (stderr, "%.2lf %.2lf %.2lf\n", 
00414                    val, rule->low.value, rule->high.value);
00415                  */
00416                 if (rule->low.value <= val && val <= rule->high.value)
00417                     break;
00418             }
00419         }
00420 
00421         /* if found, perform linear interpolation from low to high.
00422          * else set colors to colors->undef or white if undef not set
00423          */
00424 
00425         if (rule) {
00426             G__interpolate_color_rule(val, red, grn, blu, rule);
00427             found = 1;
00428         }
00429         if (!found) {
00430             /* otherwise use default color */
00431             G_get_default_color(&r, &g, &b, colors);
00432             *red = r;
00433             *grn = g;
00434             *blu = b;
00435         }
00436         /* DEBUG
00437            if (rule)
00438            fprintf (stderr, "%.2lf %d %d %d   %.2lf %d %d %d \n", rule->low.value , (int)rule->low.red, (int)rule->low.grn, (int)rule->low.blu, rule->high.value, (int)rule->high.red, (int)rule->high.grn, (int)rule->high.blu);
00439            fprintf (stderr, "rule found %d %.2lf %d %d %d\n\n", cat, val, *red, *grn, *blu);
00440          */
00441     }
00442 
00443     return 0;
00444 }
00445 
00446 int G__interpolate_color_rule(DCELL val, unsigned char *red,
00447                               unsigned char *grn, unsigned char *blu,
00448                               const struct _Color_Rule_ *rule)
00449 {
00450     DCELL delta;
00451 
00452     if ((delta = rule->high.value - rule->low.value)) {
00453         val -= rule->low.value;
00454 
00455         *red =
00456             (int)(val * (double)((int)rule->high.red - (int)rule->low.red) /
00457                   delta)
00458             + (int)rule->low.red;
00459         *grn =
00460             (int)(val * (double)((int)rule->high.grn - (int)rule->low.grn) /
00461                   delta)
00462             + (int)rule->low.grn;
00463         *blu =
00464             (int)(val * (double)((int)rule->high.blu - (int)rule->low.blu) /
00465                   delta)
00466             + (int)rule->low.blu;
00467     }
00468     else {
00469         *red = rule->low.red;
00470         *grn = rule->low.grn;
00471         *blu = rule->low.blu;
00472     }
00473 
00474     return 0;
00475 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines