/*! \brief Build color table (256) Calling function must have already allocated space in buff for range of data (256 for now) - simply calls get_color for each cat in color range \param filename raster map name \param[out] buff data buffer \return 1 on success \return 0 on failure */ int Gs_build_256lookup(const char *filename, int *buff) { const char *mapset; struct Colors colrules; CELL min, max, cats[256]; int i; unsigned char r[256], g[256], b[256], set[256]; G_debug(3, "building color table"); mapset = G_find_raster2(filename, ""); if (!mapset) { G_warning(_("Raster map <%s> not found"), filename); return 0; } Rast_read_colors(filename, mapset, &colrules); Rast_get_c_color_range(&min, &max, &colrules); if (min < 0 || max > 255) { G_warning(_("Color table range doesn't match data (mincol=%d, maxcol=%d"), min, max); min = min < 0 ? 0 : min; max = max > 255 ? 255 : max; } G_zero(cats, 256 * sizeof(CELL)); for (i = min; i <= max; i++) { cats[i] = i; } Rast_lookup_c_colors(cats, r, g, b, set, 256, &colrules); for (i = 0; i < 256; i++) { if (set[i]) { buff[i] = (r[i] & 0xff) | ((g[i] & 0xff) << 8) | ((b[i] & 0xff) << 16); } else { buff[i] = NO_DATA_COL; } } return (1); }
int table_toggle(char *name, char *mapset, struct Colors *colors) { CELL min, max; char *msg = '\0'; char info[100]; Rast_get_c_color_range(&min, &max, colors); Rast_free_colors(colors); sprintf(info, "Color range: %d to %d\n", min, max); toggle_number++; toggle_number &= 6; switch (toggle_number) { case 0: msg = "Original colors"; Rast_read_colors(name, mapset, colors); break; case 1: msg = "Ramp colors"; Rast_make_ramp_colors(colors, min, max); break; case 2: msg = "Grey scale colors"; Rast_make_grey_scale_colors(colors, min, max); break; case 3: msg = "Random colors"; Rast_make_random_colors(colors, min, max); break; case 4: msg = "Wave colors"; Rast_make_wave_colors(colors, min, max); break; case 5: msg = "Aspect colors"; Rast_make_aspect_colors(colors, min, max); break; } Write_message(2, msg); Write_message(3, info); return 0; }
/* actual raster band export * returns 0 on success * -1 on raster data read/write error * */ int export_band(GDALDatasetH hMEMDS, int band, const char *name, const char *mapset, struct Cell_head *cellhead, RASTER_MAP_TYPE maptype, double nodataval, int suppress_main_colortable) { struct Colors sGrassColors; GDALColorTableH hCT; int iColor; int bHaveMinMax; double dfCellMin; double dfCellMax; struct FPRange sRange; int fd; int cols = cellhead->cols; int rows = cellhead->rows; int ret = 0; char value[200]; /* Open GRASS raster */ fd = Rast_open_old(name, mapset); /* Get raster band */ GDALRasterBandH hBand = GDALGetRasterBand(hMEMDS, band); if (hBand == NULL) { G_warning(_("Unable to get raster band")); return -1; } /* Get min/max values. */ if (Rast_read_fp_range(name, mapset, &sRange) == -1) { bHaveMinMax = FALSE; } else { bHaveMinMax = TRUE; Rast_get_fp_range_min_max(&sRange, &dfCellMin, &dfCellMax); } sprintf(value, "GRASS GIS %s", GRASS_VERSION_NUMBER); GDALSetMetadataItem(hBand, "Generated_with", value, NULL); /* use default color rules if no color rules are given */ if (Rast_read_colors(name, mapset, &sGrassColors) >= 0) { int maxcolor, i; CELL min, max; char key[200]; int rcount; Rast_get_c_color_range(&min, &max, &sGrassColors); if (bHaveMinMax) { if (max < dfCellMax) { maxcolor = max; } else { maxcolor = (int)ceil(dfCellMax); } if (maxcolor > GRASS_MAX_COLORS) { maxcolor = GRASS_MAX_COLORS; G_warning("Too many values, color table cut to %d entries", maxcolor); } } else { if (max < GRASS_MAX_COLORS) { maxcolor = max; } else { maxcolor = GRASS_MAX_COLORS; G_warning("Too many values, color table set to %d entries", maxcolor); } } rcount = Rast_colors_count(&sGrassColors); G_debug(3, "dfCellMin: %f, dfCellMax: %f, maxcolor: %d", dfCellMin, dfCellMax, maxcolor); if (!suppress_main_colortable) { hCT = GDALCreateColorTable(GPI_RGB); for (iColor = 0; iColor <= maxcolor; iColor++) { int nRed, nGreen, nBlue; GDALColorEntry sColor; if (Rast_get_c_color(&iColor, &nRed, &nGreen, &nBlue, &sGrassColors)) { sColor.c1 = nRed; sColor.c2 = nGreen; sColor.c3 = nBlue; sColor.c4 = 255; G_debug(3, "Rast_get_c_color: Y, rcount %d, nRed %d, nGreen %d, nBlue %d", rcount, nRed, nGreen, nBlue); GDALSetColorEntry(hCT, iColor, &sColor); } else { sColor.c1 = 0; sColor.c2 = 0; sColor.c3 = 0; sColor.c4 = 0; G_debug(3, "Rast_get_c_color: N, rcount %d, nRed %d, nGreen %d, nBlue %d", rcount, nRed, nGreen, nBlue); GDALSetColorEntry(hCT, iColor, &sColor); } } GDALSetRasterColorTable(hBand, hCT); } if (rcount > 0) { /* Create metadata entries for color table rules */ sprintf(value, "%d", rcount); GDALSetMetadataItem(hBand, "COLOR_TABLE_RULES_COUNT", value, NULL); } /* Add the rules in reverse order */ /* This can cause a GDAL warning with many rules, something like * Warning 1: Lost metadata writing to GeoTIFF ... too large to fit in tag. */ for (i = rcount - 1; i >= 0; i--) { DCELL val1, val2; unsigned char r1, g1, b1, r2, g2, b2; Rast_get_fp_color_rule(&val1, &r1, &g1, &b1, &val2, &r2, &g2, &b2, &sGrassColors, i); sprintf(key, "COLOR_TABLE_RULE_RGB_%d", rcount - i - 1); sprintf(value, "%e %e %d %d %d %d %d %d", val1, val2, r1, g1, b1, r2, g2, b2); GDALSetMetadataItem(hBand, key, value, NULL); } } /* Create GRASS raster buffer */ void *bufer = Rast_allocate_buf(maptype); if (bufer == NULL) { G_warning(_("Unable to allocate buffer for reading raster map")); return -1; } /* the following routine must be kept identical to exact_checks */ /* Copy data form GRASS raster to GDAL raster */ int row, col; int n_nulls = 0; /* Better use selected GDAL datatype instead of * the best match with GRASS raster map types ? */ if (maptype == FCELL_TYPE) { /* Source datatype understandable by GDAL */ GDALDataType datatype = GDT_Float32; FCELL fnullval = (FCELL) nodataval; G_debug(1, "FCELL nodata val: %f", fnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_f_null_value(&((FCELL *) bufer)[col])) { ((FCELL *) bufer)[col] = fnullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } else if (maptype == DCELL_TYPE) { GDALDataType datatype = GDT_Float64; DCELL dnullval = (DCELL) nodataval; G_debug(1, "DCELL nodata val: %f", dnullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_d_null_value(&((DCELL *) bufer)[col])) { ((DCELL *) bufer)[col] = dnullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } else { GDALDataType datatype = GDT_Int32; CELL inullval = (CELL) nodataval; G_debug(1, "CELL nodata val: %d", inullval); for (row = 0; row < rows; row++) { Rast_get_row(fd, bufer, row, maptype); for (col = 0; col < cols; col++) { if (Rast_is_c_null_value(&((CELL *) bufer)[col])) { ((CELL *) bufer)[col] = inullval; if (n_nulls == 0) { GDALSetRasterNoDataValue(hBand, nodataval); } n_nulls++; } } if (GDALRasterIO (hBand, GF_Write, 0, row, cols, 1, bufer, cols, 1, datatype, 0, 0) >= CE_Failure) { G_warning(_("Unable to write GDAL raster file")); return -1; } G_percent(row + 1, rows, 2); } } Rast_close(fd); G_free(bufer); return ret; }