GRASS Programmer's Manual
6.4.1(2011)
|
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 }