29#include <cpl_string.h> 
   33#include <libdap/Byte.h> 
   34#include <libdap/UInt16.h> 
   35#include <libdap/Int16.h> 
   36#include <libdap/UInt32.h> 
   37#include <libdap/Int32.h> 
   38#include <libdap/Float32.h> 
   39#include <libdap/Float64.h> 
   41#include <libdap/DDS.h> 
   42#include <libdap/DAS.h> 
   43#include <libdap/BaseTypeFactory.h> 
   45#include <libdap/DMR.h> 
   46#include <libdap/D4Group.h> 
   47#include <libdap/D4Dimensions.h> 
   48#include <libdap/D4Maps.h> 
   49#include <libdap/D4Attributes.h> 
   50#include <libdap/D4BaseTypeFactory.h> 
   51#include <libdap/debug.h> 
   65static void attach_str_attr_item(AttrTable *parent_table, 
const char *pszKey, 
const char *pszValue)
 
   69    char *pszEscapedText = CPLEscapeString(pszValue, -1,
 
   70    CPLES_BackslashQuotable);
 
   74    parent_table->append_attr(pszKey, 
"String", pszValue );
 
   77    CPLFree(pszEscapedText);
 
   88static void translate_metadata(
char **md, AttrTable *parent_table)
 
   93    md_table = parent_table->append_container(
string(
"Metadata"));
 
   95    for (i = 0; md != NULL && md[i] != NULL; i++) {
 
   99        pszValue = CPLParseNameValue(md[i], &pszKey);
 
  101        attach_str_attr_item(md_table, pszKey, pszValue);
 
  113static void build_global_attributes(
const GDALDatasetH& hDS, AttrTable* attr_table)
 
  118    double adfGeoTransform[6];
 
  119    if (GDALGetGeoTransform(hDS, adfGeoTransform) == CE_None
 
  120        && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0 || adfGeoTransform[2] != 0.0
 
  121            || adfGeoTransform[3] != 0.0 || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0)) {
 
  123        char szGeoTransform[200];
 
  124        double dfMaxX, dfMinX, dfMaxY, dfMinY;
 
  125        int nXSize = GDALGetRasterXSize(hDS);
 
  126        int nYSize = GDALGetRasterYSize(hDS);
 
  129            MAX(MAX(adfGeoTransform[0], adfGeoTransform[0] + adfGeoTransform[1] * nXSize),
 
  130                MAX(adfGeoTransform[0] + adfGeoTransform[2] * nYSize, adfGeoTransform[0] + adfGeoTransform[2] * nYSize + adfGeoTransform[1] * nXSize));
 
  132            MIN(MIN(adfGeoTransform[0], adfGeoTransform[0] + adfGeoTransform[1] * nXSize),
 
  133                MIN(adfGeoTransform[0] + adfGeoTransform[2] * nYSize, adfGeoTransform[0] + adfGeoTransform[2] * nYSize + adfGeoTransform[1] * nXSize));
 
  135            MAX(MAX(adfGeoTransform[3], adfGeoTransform[3] + adfGeoTransform[4] * nXSize),
 
  136                MAX(adfGeoTransform[3] + adfGeoTransform[5] * nYSize, adfGeoTransform[3] + adfGeoTransform[5] * nYSize + adfGeoTransform[4] * nXSize));
 
  138            MIN(MIN(adfGeoTransform[3], adfGeoTransform[3] + adfGeoTransform[4] * nXSize),
 
  139                MIN(adfGeoTransform[3] + adfGeoTransform[5] * nYSize, adfGeoTransform[3] + adfGeoTransform[5] * nYSize + adfGeoTransform[4] * nXSize));
 
  141        attr_table->append_attr(
"Northernmost_Northing", 
"Float64", CPLSPrintf(
"%.16g", dfMaxY));
 
  142        attr_table->append_attr(
"Southernmost_Northing", 
"Float64", CPLSPrintf(
"%.16g", dfMinY));
 
  143        attr_table->append_attr(
"Easternmost_Easting", 
"Float64", CPLSPrintf(
"%.16g", dfMaxX));
 
  146        attr_table->append_attr(
"Westernmost_Northing", 
"Float64", CPLSPrintf(
"%.16g", dfMinX));
 
  148        attr_table->append_attr(
"Westernmost_Easting", 
"Float64", CPLSPrintf(
"%.16g", dfMinX));
 
  150        snprintf(szGeoTransform, 200, 
"%.16g %.16g %.16g %.16g %.16g %.16g", adfGeoTransform[0], adfGeoTransform[1],
 
  151            adfGeoTransform[2], adfGeoTransform[3], adfGeoTransform[4], adfGeoTransform[5]);
 
  153        attach_str_attr_item(attr_table, 
"GeoTransform", szGeoTransform);
 
  160    md = GDALGetMetadata(hDS, NULL);
 
  161    if (md != NULL) translate_metadata(md, attr_table);
 
  166    const char* pszWKT = GDALGetProjectionRef(hDS);
 
  167    if (pszWKT != NULL && strlen(pszWKT) > 0) attach_str_attr_item(attr_table, 
"spatial_ref", pszWKT);
 
  177static void build_variable_attributes(
const GDALDatasetH &hDS, AttrTable *band_attr, 
const int iBand)
 
  185    GDALRasterBandH hBand = GDALGetRasterBand(hDS, iBand + 1);
 
  187    dfValue = GDALGetRasterOffset(hBand, &bSuccess);
 
  189        snprintf(szValue, 128, 
"%.16g", dfValue);
 
  190        band_attr->append_attr(
"add_offset", 
"Float64", szValue);
 
  196    dfValue = GDALGetRasterScale(hBand, &bSuccess);
 
  198        snprintf(szValue, 128, 
"%.16g", dfValue);
 
  199        band_attr->append_attr(
"scale_factor", 
"Float64", szValue);
 
  205    dfValue = GDALGetRasterNoDataValue(hBand, &bSuccess);
 
  207        snprintf(szValue, 128, 
"%.16g", dfValue);
 
  208        band_attr->append_attr(
"missing_value", 
"Float64", szValue);
 
  214    if (GDALGetDescription(hBand) != NULL && strlen(GDALGetDescription(hBand)) > 0) {
 
  215        attach_str_attr_item(band_attr, 
"Description", GDALGetDescription(hBand));
 
  221    if (GDALGetRasterColorInterpretation(hBand) != GCI_Undefined) {
 
  222        attach_str_attr_item(band_attr, 
"PhotometricInterpretation",
 
  223            GDALGetColorInterpretationName(GDALGetRasterColorInterpretation(hBand)));
 
  229    char **md = GDALGetMetadata(hBand, NULL);
 
  230    if (md != NULL) translate_metadata(md, band_attr);
 
  237    hCT = GDALGetRasterColorTable(hBand);
 
  240        int iColor, nColorCount = GDALGetColorEntryCount(hCT);
 
  242        ct_attr = band_attr->append_container(
string(
"Colormap"));
 
  244        for (iColor = 0; iColor < nColorCount; iColor++) {
 
  246            AttrTable *color_attr;
 
  248            color_attr = ct_attr->append_container(
string(CPLSPrintf(
"color_%d", iColor)));
 
  250            GDALGetColorEntryAsRGB(hCT, iColor, &sRGB);
 
  252            color_attr->append_attr(
"red", 
"byte", CPLSPrintf(
"%d", sRGB.c1));
 
  253            color_attr->append_attr(
"green", 
"byte", CPLSPrintf(
"%d", sRGB.c2));
 
  254            color_attr->append_attr(
"blue", 
"byte", CPLSPrintf(
"%d", sRGB.c3));
 
  255            color_attr->append_attr(
"alpha", 
"byte", CPLSPrintf(
"%d", sRGB.c4));
 
  273void gdal_read_dataset_attributes(DAS &das, 
const GDALDatasetH &hDS)
 
  275    AttrTable *attr_table = das.add_table(
string(
"GLOBAL"), 
new AttrTable);
 
  277    build_global_attributes(hDS, attr_table);
 
  282    for (
int iBand = 0; iBand < GDALGetRasterCount(hDS); iBand++) {
 
  284        AttrTable *band_attr;
 
  289        snprintf(szName, 128, 
"band_%d", iBand + 1);
 
  290        band_attr = das.add_table(
string(szName), 
new AttrTable);
 
  292        build_variable_attributes(hDS, band_attr, iBand);
 
  306void gdal_read_dataset_variables(DDS *dds, 
const GDALDatasetH &hDS, 
const string &filename,
bool include_attrs)
 
  309    if(
true == include_attrs) {
 
  310        AttrTable *global_attr = dds->get_attr_table().append_container(
"GLOBAL");
 
  311        build_global_attributes(hDS, global_attr);
 
  318    GDALDataType eBufType;
 
  320    for (
int iBand = 0; iBand < GDALGetRasterCount(hDS); iBand++) {
 
  321        DBG(cerr << 
"In dgal_dds.cc  iBand" << endl);
 
  323        GDALRasterBandH hBand = GDALGetRasterBand(hDS, iBand + 1);
 
  326        oss << 
"band_" << iBand + 1;
 
  328        eBufType = GDALGetRasterDataType(hBand);
 
  331        switch (GDALGetRasterDataType(hBand)) {
 
  333            bt = factory.NewByte(oss.str());
 
  337            bt = factory.NewUInt16(oss.str());
 
  341            bt = factory.NewInt16(oss.str());
 
  345            bt = factory.NewUInt32(oss.str());
 
  349            bt = factory.NewInt32(oss.str());
 
  353            bt = factory.NewFloat32(oss.str());
 
  357            bt = factory.NewFloat64(oss.str());
 
  366            bt = factory.NewFloat64(oss.str());
 
  367            eBufType = GDT_Float64;
 
  375        grid = 
new GDALGrid(filename, oss.str());
 
  385        ar = 
new GDALArray(oss.str(), 0, filename, eBufType, iBand + 1);
 
  386        ar->add_var_nocopy(bt);
 
  387        ar->append_dim(GDALGetRasterYSize(hDS), 
"northing");
 
  388        ar->append_dim(GDALGetRasterXSize(hDS), 
"easting");
 
  390        grid->add_var_nocopy(ar, libdap::array);
 
  396        bt = factory.NewFloat64(
"northing");
 
  397        ar = 
new GDALArray(
"northing", 0, filename, GDT_Float64, iBand + 1);
 
  398        ar->add_var_nocopy(bt);
 
  399        ar->append_dim(GDALGetRasterYSize(hDS), 
"northing");
 
  401        grid->add_var_nocopy(ar, maps);
 
  404        bt = factory.NewFloat64(
"easting");
 
  405        ar = 
new GDALArray(
"easting", 0, filename, GDT_Float64, iBand + 1);
 
  406        ar->add_var_nocopy(bt);
 
  407        ar->append_dim(GDALGetRasterXSize(hDS), 
"easting");
 
  409        grid->add_var_nocopy(ar, maps);
 
  411        DBG(cerr << 
"Type of grid: " << 
typeid(grid).name() << endl);
 
  414        if(
true == include_attrs) {
 
  415            AttrTable &band_attr = grid->get_attr_table();
 
  416            build_variable_attributes(hDS, &band_attr, iBand);
 
  419        dds->add_var_nocopy(grid);
 
  436void gdal_read_dataset_variables(DMR *dmr, 
const GDALDatasetH &hDS, 
const string &filename)
 
  447    AttrTable *attr = 
new AttrTable();
 
  448    AttrTable *global_attr = attr->append_container(
"GLOBAL");
 
  450    build_global_attributes(hDS, global_attr);
 
  452    dmr->root()->attributes()->transform_to_dap4(*attr);
 
  453    delete attr; attr = 0;
 
  455    D4BaseTypeFactory factory;    
 
  470    int sdim_band_num = 1;
 
  471    for (; sdim_band_num <= GDALGetRasterCount(hDS); ++sdim_band_num) {
 
  472        if (GDALGetRasterBandYSize(GDALGetRasterBand(hDS, sdim_band_num)) == GDALGetRasterYSize(hDS)
 
  473            && GDALGetRasterBandXSize(GDALGetRasterBand(hDS, sdim_band_num)) == GDALGetRasterXSize(hDS)) {
 
  479    const string northing = 
"northing";
 
  481    D4Dimension *northing_dim = 
new D4Dimension(northing, GDALGetRasterYSize(hDS));
 
  482    dmr->root()->dims()->add_dim_nocopy(northing_dim);
 
  484    Array *northing_map = 
new GDALArray(northing, 0, filename, GDT_Float64, sdim_band_num);
 
  485    northing_map->add_var_nocopy(factory.NewFloat64(northing));
 
  486    northing_map->append_dim(northing_dim);
 
  488    dmr->root()->add_var_nocopy(northing_map);   
 
  490    const string easting = 
"easting";
 
  491    D4Dimension *easting_dim = 
new D4Dimension(easting, GDALGetRasterXSize(hDS));
 
  492    dmr->root()->dims()->add_dim_nocopy(easting_dim);
 
  493    Array *easting_map = 
new GDALArray(easting, 0, filename, GDT_Float64, sdim_band_num);
 
  494    easting_map->add_var_nocopy(factory.NewFloat64(easting));
 
  495    easting_map->append_dim(easting_dim);
 
  496    dmr->root()->add_var_nocopy(easting_map);   
 
  502    GDALDataType eBufType;
 
  504    for (
int iBand = 0; iBand < GDALGetRasterCount(hDS); iBand++) {
 
  505        DBG(cerr << 
"In dgal_dds.cc  iBand" << endl);
 
  507        GDALRasterBandH hBand = GDALGetRasterBand(hDS, iBand + 1);
 
  510        oss << 
"band_" << iBand + 1;
 
  512        eBufType = GDALGetRasterDataType(hBand);
 
  515        switch (GDALGetRasterDataType(hBand)) {
 
  517            bt = factory.NewByte(oss.str());
 
  521            bt = factory.NewUInt16(oss.str());
 
  525            bt = factory.NewInt16(oss.str());
 
  529            bt = factory.NewUInt32(oss.str());
 
  533            bt = factory.NewInt32(oss.str());
 
  537            bt = factory.NewFloat32(oss.str());
 
  541            bt = factory.NewFloat64(oss.str());
 
  551            bt = factory.NewFloat64(oss.str());
 
  552            eBufType = GDT_Float64;
 
  558        Array *ar = 
new GDALArray(oss.str(), 0, filename, eBufType, iBand + 1);
 
  559        ar->add_var_nocopy(bt); 
 
  565        if (GDALGetRasterBandYSize(hBand) == GDALGetRasterYSize(hDS)
 
  566            && GDALGetRasterBandXSize(hBand) == GDALGetRasterXSize(hDS)) {
 
  568            ar->append_dim(northing_dim);
 
  569            ar->append_dim(easting_dim);
 
  572            ar->maps()->add_map(
new D4Map(
string(
"/") + northing, northing_map, ar));
 
  573            ar->maps()->add_map(
new D4Map(
string(
"/") + easting, easting_map, ar));
 
  577            ar->append_dim(GDALGetRasterBandYSize(hBand), northing);
 
  578            ar->append_dim(GDALGetRasterBandXSize(hBand), easting);
 
  583        AttrTable &band_attr = ar->get_attr_table();
 
  584        build_variable_attributes(hDS, &band_attr, iBand);
 
  585        ar->attributes()->transform_to_dap4(band_attr);
 
  587        dmr->root()->add_var_nocopy(ar);        
 
  608void read_data_array(
GDALArray *array, 
const GDALRasterBandH &hBand)
 
  613    Array::Dim_iter p = array->dim_begin();
 
  614    int start = array->dimension_start(p, 
true);
 
  615    int stride = array->dimension_stride(p, 
true);
 
  616    int stop = array->dimension_stop(p, 
true);
 
  619    if (array->dimension_size(p, 
true) == 0) { 
 
  622        stop = GDALGetRasterBandYSize(hBand) - 1;
 
  626    int start_2 = array->dimension_start(p, 
true);
 
  627    int stride_2 = array->dimension_stride(p, 
true);
 
  628    int stop_2 = array->dimension_stop(p, 
true);
 
  630    if (array->dimension_size(p, 
true) == 0) { 
 
  633        stop_2 = GDALGetRasterBandXSize(hBand) - 1;
 
  639    int nWinXOff, nWinYOff, nWinXSize, nWinYSize, nBufXSize, nBufYSize;
 
  643    nWinXSize = stop_2 + 1 - start_2;
 
  644    nWinYSize = stop + 1 - start;
 
  646    nBufXSize = (stop_2 - start_2) / stride_2 + 1;
 
  647    nBufYSize = (stop - start) / stride + 1;
 
  652    int nPixelSize = GDALGetDataTypeSize(array->get_gdal_buf_type()) / 8;
 
  658    CPLErr eErr = GDALRasterIO(hBand, GF_Read, nWinXOff, nWinYOff, nWinXSize, nWinYSize, pData.data(), nBufXSize,
 
  659        nBufYSize, array->get_gdal_buf_type(), 0, 0);
 
  660    if (eErr != CE_None) 
throw Error(
"Error reading: " + array->name());
 
  662    array->val2buf(pData.data());
 
  683void read_map_array(Array *
map, 
const GDALRasterBandH &hBand, 
const GDALDatasetH &hDS)
 
  685    Array::Dim_iter p = 
map->dim_begin();
 
  686    int start = 
map->dimension_start(p, 
true);
 
  687    int stride = 
map->dimension_stride(p, 
true);
 
  688    int stop = 
map->dimension_stop(p, 
true);
 
  690    if (start + stop + stride == 0) { 
 
  693        if (
map->name() == 
"northing")
 
  694            stop = GDALGetRasterBandYSize(hBand) - 1;
 
  695        else if (
map->name() == 
"easting")
 
  696            stop = GDALGetRasterBandXSize(hBand) - 1;
 
  698            throw Error(
"Expected a map named 'northing' or 'easting' but got: " + 
map->name());
 
  701    int nBufSize = (stop - start) / stride + 1;
 
  708    double adfGeoTransform[6];
 
  710    if (GDALGetGeoTransform(hDS, adfGeoTransform) != CE_None) {
 
  711        adfGeoTransform[0] = 0.0;
 
  712        adfGeoTransform[1] = 1.0;
 
  713        adfGeoTransform[2] = 0.0;
 
  714        adfGeoTransform[3] = 0.0;
 
  715        adfGeoTransform[4] = 0.0;
 
  716        adfGeoTransform[5] = 1.0;
 
  724    if (
map->name() == 
"northing") {
 
  725        for (
int i = 0, iLine = start; iLine <= stop; iLine += stride) {
 
  726            padfMap[i++] = adfGeoTransform[3] + adfGeoTransform[5] * iLine;
 
  729    else if (
map->name() == 
"easting") {
 
  730        for (
int i = 0, iPixel = start; iPixel <= stop; iPixel += stride) {
 
  731            padfMap[i++] = adfGeoTransform[0] + iPixel * adfGeoTransform[1];
 
  735        throw Error(
"Expected a map named 'northing' or 'easting' but got: " + 
map->name());
 
  737    map->val2buf((
void *) padfMap.data());