Example #1
0
Handle<Value> DatasetBands::create(const Arguments& args)
{
	HandleScope scope;

	Handle<Object> parent = args.This()->GetHiddenValue(String::NewSymbol("parent_"))->ToObject();
	Dataset *ds = ObjectWrap::Unwrap<Dataset>(parent);
	
	if (ds->uses_ogr){
		return NODE_THROW("Dataset does not support getting creating bands");
	} 

	GDALDataset* raw = ds->getDataset();
	if (!raw) {
		return NODE_THROW("Dataset object has already been destroyed");
	}

	GDALDataType type;
	Handle<Array> band_options = Array::New(0);
	char **options = NULL;
	std::string *options_str = NULL;

	//NODE_ARG_ENUM(0, "data type", GDALDataType, type);
	if(args.Length() < 1) {
		return NODE_THROW("data type argument needed");
	}
	if(args[0]->IsString()){
		std::string type_name = TOSTR(args[0]);
		type = GDALGetDataTypeByName(type_name.c_str());
	} else if (args[0]->IsNull() || args[0]->IsUndefined()) {
		type = GDT_Unknown;
	} else {
		return NODE_THROW("data type must be string or undefined");
	}

	NODE_ARG_ARRAY_OPT(1, "band creation options", band_options);

	if (band_options->Length() > 0) {
		options     = new char* [band_options->Length()];
		options_str = new std::string [band_options->Length()];
		for (unsigned int i = 0; i < band_options->Length(); ++i) {
			options_str[i] = TOSTR(band_options->Get(i));
			options[i] = (char*) options_str[i].c_str();
		}
	}

	CPLErr err = raw->AddBand(type, options);

	if(options)	    delete [] options;
	if(options_str)	delete [] options_str;

	if (err) {
		return NODE_THROW_CPLERR(err);
	}

	return scope.Close(RasterBand::New(raw->GetRasterBand(raw->GetRasterCount()), raw));
}
Example #2
0
GDALDataset * RasterCreate( const char * pszFormat, const char * pszFilename, char ** papszOptions /*=NULL*/ )
{
	int nXSize = atoi(CSLFetchNameValue(papszOptions, "XSize"));
	int nYSize = atoi(CSLFetchNameValue(papszOptions, "YSize"));
	int nBands = atoi(CSLFetchNameValue(papszOptions, "Bands"));
	GDALDataType eBandType = GDALGetDataTypeByName(CSLFetchNameValue(papszOptions, "DataType"));

	char ** papszCreate = NULL;
	papszCreate = CSLSetNameValue(papszCreate, "BLOCKXSIZE", "256");
	papszCreate = CSLSetNameValue( papszCreate, "BLOCKYSIZE", "1" );

	GDALDriver * poDriver = GetRasterDriver(pszFormat);
	GDALDataset * poDS = poDriver->Create( pszFilename,
	                                       nXSize, nYSize, nBands,
	                                       eBandType, papszCreate) ;

	CSLDestroy(papszCreate);
	return poDS;
}
CPLErr VRTDerivedRasterBand::XMLInit(CPLXMLNode *psTree, 
				     const char *pszVRTPath)

{
    CPLErr eErr;
    const char *pszTypeName;

    eErr = VRTSourcedRasterBand::XMLInit( psTree, pszVRTPath );
    if( eErr != CE_None )
        return eErr;

    /* ---- Read derived pixel function type ---- */
    this->SetPixelFunctionName
	(CPLGetXMLValue(psTree, "PixelFunctionType", NULL));

    /* ---- Read optional source transfer data type ---- */
    pszTypeName = CPLGetXMLValue(psTree, "SourceTransferType", NULL);
    if (pszTypeName != NULL) {
	this->eSourceTransferType = GDALGetDataTypeByName(pszTypeName);
    }

    return CE_None;
}
Example #4
0
GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo *poOpenInfo,
                                      GridFormat eFormat )
{
    if( poOpenInfo->fpL == nullptr )
        return nullptr;

    // Create a corresponding GDALDataset.
    AAIGDataset *poDS = nullptr;

    if (eFormat == FORMAT_AAIG)
        poDS = new AAIGDataset();
    else
        poDS = new GRASSASCIIDataset();

    const char *pszDataTypeOption =
        eFormat == FORMAT_AAIG ?
        "AAIGRID_DATATYPE" : "GRASSASCIIGRID_DATATYPE";

    const char *pszDataType = CPLGetConfigOption(pszDataTypeOption, nullptr);
    if( pszDataType == nullptr )
        pszDataType =
            CSLFetchNameValue(poOpenInfo->papszOpenOptions, "DATATYPE");
    if (pszDataType != nullptr)
    {
        poDS->eDataType = GDALGetDataTypeByName(pszDataType);
        if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 ||
              poDS->eDataType == GDT_Float64))
        {
            CPLError(CE_Warning, CPLE_NotSupported,
                     "Unsupported value for %s : %s",
                     pszDataTypeOption, pszDataType);
            poDS->eDataType = GDT_Int32;
            pszDataType = nullptr;
        }
    }

    // Parse the header.
    if (!poDS->ParseHeader((const char *)poOpenInfo->pabyHeader, pszDataType))
    {
        delete poDS;
        return nullptr;
    }

    poDS->fp = poOpenInfo->fpL;
    poOpenInfo->fpL = nullptr;

    // Find the start of real data.
    int nStartOfData = 0;

    for( int i = 2; true; i++ )
    {
        if( poOpenInfo->pabyHeader[i] == '\0' )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Couldn't find data values in ASCII Grid file.");
            delete poDS;
            return nullptr;
        }

        if( poOpenInfo->pabyHeader[i - 1] == '\n' ||
            poOpenInfo->pabyHeader[i - 2] == '\n' ||
            poOpenInfo->pabyHeader[i - 1] == '\r' ||
            poOpenInfo->pabyHeader[i - 2] == '\r' )
        {
            if( !isalpha(poOpenInfo->pabyHeader[i]) &&
                poOpenInfo->pabyHeader[i] != '\n' &&
                poOpenInfo->pabyHeader[i] != '\r')
            {
                nStartOfData = i;

                // Beginning of real data found.
                break;
            }
        }
    }

    // Recognize the type of data.
    CPLAssert(nullptr != poDS->fp);

    if( pszDataType == nullptr &&
        poDS->eDataType != GDT_Float32 && poDS->eDataType != GDT_Float64)
    {
        // Allocate 100K chunk + 1 extra byte for NULL character.
        constexpr size_t nChunkSize = 1024 * 100;
        GByte *pabyChunk = static_cast<GByte *>(
            VSI_CALLOC_VERBOSE(nChunkSize + 1, sizeof(GByte)));
        if (pabyChunk == nullptr)
        {
            delete poDS;
            return nullptr;
        }
        pabyChunk[nChunkSize] = '\0';

        if( VSIFSeekL(poDS->fp, nStartOfData, SEEK_SET) < 0 )
        {
            delete poDS;
            VSIFree(pabyChunk);
            return nullptr;
        }

        // Scan for dot in subsequent chunks of data.
        while( !VSIFEofL(poDS->fp) )
        {
            CPL_IGNORE_RET_VAL(VSIFReadL(pabyChunk, nChunkSize, 1, poDS->fp));

            for( int i = 0; i < static_cast<int>(nChunkSize); i++)
            {
                GByte ch = pabyChunk[i];
                if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E')
                {
                    poDS->eDataType = GDT_Float32;
                    break;
                }
            }
        }

        // Deallocate chunk.
        VSIFree(pabyChunk);
    }

    // Create band information objects.
    AAIGRasterBand *band = new AAIGRasterBand(poDS, nStartOfData);
    poDS->SetBand(1, band);
    if (band->panLineOffset == nullptr)
    {
        delete poDS;
        return nullptr;
    }

    // Try to read projection file.
    char *const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename));
    char *const pszBasename =
        CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename));

    poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "prj");
    int nRet = 0;
    {
        VSIStatBufL sStatBuf;
        nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf);
    }
    if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) )
    {
        poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "PRJ");

        VSIStatBufL sStatBuf;
        nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf);
    }

    if( nRet == 0 )
    {
        poDS->papszPrj = CSLLoad(poDS->osPrjFilename);

        CPLDebug("AAIGrid", "Loaded SRS from %s", poDS->osPrjFilename.c_str());

        OGRSpatialReference oSRS;
        if( oSRS.importFromESRI(poDS->papszPrj) == OGRERR_NONE )
        {
            // If geographic values are in seconds, we must transform.
            // Is there a code for minutes too?
            if( oSRS.IsGeographic() &&
                EQUAL(OSR_GDS(poDS->papszPrj, "Units", ""), "DS") )
            {
                poDS->adfGeoTransform[0] /= 3600.0;
                poDS->adfGeoTransform[1] /= 3600.0;
                poDS->adfGeoTransform[2] /= 3600.0;
                poDS->adfGeoTransform[3] /= 3600.0;
                poDS->adfGeoTransform[4] /= 3600.0;
                poDS->adfGeoTransform[5] /= 3600.0;
            }

            CPLFree(poDS->pszProjection);
            oSRS.exportToWkt(&(poDS->pszProjection));
        }
    }

    CPLFree(pszDirname);
    CPLFree(pszBasename);

    // Initialize any PAM information.
    poDS->SetDescription(poOpenInfo->pszFilename);
    poDS->TryLoadXML();

    // Check for external overviews.
    poDS->oOvManager.Initialize(
        poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles());

    return poDS;
}
Example #5
0
CPLErr VRTDataset::AddBand( GDALDataType eType, char **papszOptions )

{
    int i;

    const char *pszSubClass = CSLFetchNameValue(papszOptions, "subclass");

    bNeedsFlush = 1;

/* ==================================================================== */
/*      Handle a new raw band.                                          */
/* ==================================================================== */
    if( pszSubClass != NULL && EQUAL(pszSubClass,"VRTRawRasterBand") )
    {
        int nWordDataSize = GDALGetDataTypeSize( eType ) / 8;
        vsi_l_offset nImageOffset = 0;
        int nPixelOffset = nWordDataSize;
        int nLineOffset = nWordDataSize * GetRasterXSize();
        const char *pszFilename;
        const char *pszByteOrder = NULL;
        int bRelativeToVRT = FALSE;

/* -------------------------------------------------------------------- */
/*      Collect required information.                                   */
/* -------------------------------------------------------------------- */
        if( CSLFetchNameValue(papszOptions, "ImageOffset") != NULL )
            nImageOffset = atoi(CSLFetchNameValue(papszOptions, "ImageOffset"));

        if( CSLFetchNameValue(papszOptions, "PixelOffset") != NULL )
            nPixelOffset = atoi(CSLFetchNameValue(papszOptions,"PixelOffset"));

        if( CSLFetchNameValue(papszOptions, "LineOffset") != NULL )
            nLineOffset = atoi(CSLFetchNameValue(papszOptions, "LineOffset"));

        if( CSLFetchNameValue(papszOptions, "ByteOrder") != NULL )
            pszByteOrder = CSLFetchNameValue(papszOptions, "ByteOrder");

        if( CSLFetchNameValue(papszOptions, "SourceFilename") != NULL )
            pszFilename = CSLFetchNameValue(papszOptions, "SourceFilename");
        else
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "AddBand() requires a SourceFilename option for VRTRawRasterBands." );
            return CE_Failure;
        }
        
        bRelativeToVRT = 
            CSLFetchBoolean( papszOptions, "RelativeToVRT", FALSE );

/* -------------------------------------------------------------------- */
/*      Create and initialize the band.                                 */
/* -------------------------------------------------------------------- */
        CPLErr eErr;

        VRTRawRasterBand *poBand = 
            new VRTRawRasterBand( this, GetRasterCount() + 1, eType );

        eErr = 
            poBand->SetRawLink( pszFilename, NULL, FALSE, 
                                nImageOffset, nPixelOffset, nLineOffset, 
                                pszByteOrder );
        if( eErr != CE_None )
        {
            delete poBand;
            return eErr;
        }

        SetBand( GetRasterCount() + 1, poBand );

        return CE_None;
    }

/* ==================================================================== */
/*      Handle a new "sourced" band.                                    */
/* ==================================================================== */
    else
    {
        VRTSourcedRasterBand *poBand;

	/* ---- Check for our sourced band 'derived' subclass ---- */
        if(pszSubClass != NULL && EQUAL(pszSubClass,"VRTDerivedRasterBand")) {

            /* We'll need a pointer to the subclass in case we need */
            /* to set the new band's pixel function below. */
            VRTDerivedRasterBand* poDerivedBand;

            poDerivedBand = new VRTDerivedRasterBand
                (this, GetRasterCount() + 1, eType,
                 GetRasterXSize(), GetRasterYSize());

            /* Set the pixel function options it provided. */
            const char* pszFuncName =
                CSLFetchNameValue(papszOptions, "PixelFunctionType");
            if (pszFuncName != NULL)
                poDerivedBand->SetPixelFunctionName(pszFuncName);

            const char* pszTransferTypeName =
                CSLFetchNameValue(papszOptions, "SourceTransferType");
            if (pszTransferTypeName != NULL) {
                GDALDataType eTransferType =
                    GDALGetDataTypeByName(pszTransferTypeName);
                if (eTransferType == GDT_Unknown) {
                    CPLError( CE_Failure, CPLE_AppDefined,
                              "invalid SourceTransferType: \"%s\".",
                              pszTransferTypeName);
                    delete poDerivedBand;
                    return CE_Failure;
                }
                poDerivedBand->SetSourceTransferType(eTransferType);
            }

            /* We're done with the derived band specific stuff, so */
            /* we can assigned the base class pointer now. */
            poBand = poDerivedBand;
        }
	else {

	    /* ---- Standard sourced band ---- */
	    poBand = new VRTSourcedRasterBand
		(this, GetRasterCount() + 1, eType, 
		 GetRasterXSize(), GetRasterYSize());
	}

        SetBand( GetRasterCount() + 1, poBand );

        for( i=0; papszOptions != NULL && papszOptions[i] != NULL; i++ )
        {
            if( EQUALN(papszOptions[i],"AddFuncSource=", 14) )
            {
                VRTImageReadFunc pfnReadFunc = NULL;
                void             *pCBData = NULL;
                double           dfNoDataValue = VRT_NODATA_UNSET;

                char **papszTokens = CSLTokenizeStringComplex( papszOptions[i]+14,
                                                               ",", TRUE, FALSE );

                if( CSLCount(papszTokens) < 1 )
                {
                    CPLError( CE_Failure, CPLE_AppDefined, 
                              "AddFuncSource() ... required argument missing." );
                }

                sscanf( papszTokens[0], "%p", &pfnReadFunc );
                if( CSLCount(papszTokens) > 1 )
                    sscanf( papszTokens[1], "%p", &pCBData );
                if( CSLCount(papszTokens) > 2 )
                    dfNoDataValue = atof( papszTokens[2] );

                poBand->AddFuncSource( pfnReadFunc, pCBData, dfNoDataValue );
            }
        }

        return CE_None;
    }
}
Example #6
0
GDALDataset *GXFDataset::Open( GDALOpenInfo * poOpenInfo )

{
    GXFHandle	l_hGXF;
    int		i, bFoundKeyword, bFoundIllegal;

/* -------------------------------------------------------------------- */
/*      Before trying GXFOpen() we first verify that there is at        */
/*      least one "\n#keyword" type signature in the first chunk of     */
/*      the file.                                                       */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->nHeaderBytes < 50 )
        return NULL;

    bFoundKeyword = FALSE;
    bFoundIllegal = FALSE;
    for( i = 0; i < poOpenInfo->nHeaderBytes-1; i++ )
    {
        if( (poOpenInfo->pabyHeader[i] == 10
             || poOpenInfo->pabyHeader[i] == 13)
            && poOpenInfo->pabyHeader[i+1] == '#' )
        {
            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "include") )
                return NULL;
            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "define") )
                return NULL;
            if( STARTS_WITH((const char*)poOpenInfo->pabyHeader + i + 2, "ifdef") )
                return NULL;
            bFoundKeyword = TRUE;
        }
        if( poOpenInfo->pabyHeader[i] == 0 )
        {
            bFoundIllegal = TRUE;
            break;
        }
    }

    if( !bFoundKeyword || bFoundIllegal )
        return NULL;

/* -------------------------------------------------------------------- */
/*      At this point it is plausible that this is a GXF file, but      */
/*      we also now verify that there is a #GRID keyword before         */
/*      passing it off to GXFOpen().  We check in the first 50K.        */
/* -------------------------------------------------------------------- */
#define BIGBUFSIZE 50000
    int nBytesRead, bGotGrid = FALSE;
    FILE *fp;

    fp = VSIFOpen( poOpenInfo->pszFilename, "rb" );
    if( fp == NULL )
        return NULL;

    char *pszBigBuf = (char *) CPLMalloc(BIGBUFSIZE);
    nBytesRead = static_cast<int>(VSIFRead( pszBigBuf, 1, BIGBUFSIZE, fp ));
    VSIFClose( fp );

    for( i = 0; i < nBytesRead - 5 && !bGotGrid; i++ )
    {
        if( pszBigBuf[i] == '#' && STARTS_WITH_CI(pszBigBuf+i+1, "GRID") )
            bGotGrid = TRUE;
    }

    CPLFree( pszBigBuf );

    if( !bGotGrid )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Try opening the dataset.                                        */
/* -------------------------------------------------------------------- */

    l_hGXF = GXFOpen( poOpenInfo->pszFilename );

    if( l_hGXF == NULL )
        return( NULL );

/* -------------------------------------------------------------------- */
/*      Confirm the requested access is supported.                      */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->eAccess == GA_Update )
    {
        GXFClose(l_hGXF);
        CPLError( CE_Failure, CPLE_NotSupported,
                  "The GXF driver does not support update access to existing"
                  " datasets.\n" );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    GXFDataset 	*poDS;

    poDS = new GXFDataset();

    const char* pszGXFDataType = CPLGetConfigOption("GXF_DATATYPE", "Float32");
    GDALDataType eDT = GDALGetDataTypeByName(pszGXFDataType);
    if (!(eDT == GDT_Float32 || eDT == GDT_Float64))
    {
        CPLError(CE_Warning, CPLE_NotSupported,
                 "Unsupported value for GXF_DATATYPE : %s", pszGXFDataType);
        eDT = GDT_Float32;
    }

    poDS->hGXF = l_hGXF;
    poDS->eDataType = eDT;

/* -------------------------------------------------------------------- */
/*	Establish the projection.					*/
/* -------------------------------------------------------------------- */
    poDS->pszProjection = GXFGetMapProjectionAsOGCWKT( l_hGXF );

/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
    GXFGetRawInfo( l_hGXF, &(poDS->nRasterXSize), &(poDS->nRasterYSize), NULL,
                   NULL, NULL, &(poDS->dfNoDataValue) );

    if  (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Invalid dimensions : %d x %d",
                  poDS->nRasterXSize, poDS->nRasterYSize);
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    poDS->nBands = 1;
    poDS->SetBand( 1, new GXFRasterBand( poDS, 1 ));

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );
    poDS->TryLoadXML();

/* -------------------------------------------------------------------- */
/*      Check for external overviews.                                   */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() );

    return( poDS );
}
Example #7
0
CPLErr VRTRasterBand::XMLInit( CPLXMLNode * psTree, 
                               const char *pszVRTPath )

{
/* -------------------------------------------------------------------- */
/*      Validate a bit.                                                 */
/* -------------------------------------------------------------------- */
    if( psTree == NULL || psTree->eType != CXT_Element
        || !EQUAL(psTree->pszValue,"VRTRasterBand") )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Invalid node passed to VRTRasterBand::XMLInit()." );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Set the band if provided as an attribute.                       */
/* -------------------------------------------------------------------- */
    const char* pszBand = CPLGetXMLValue( psTree, "band", NULL);
    if( pszBand != NULL )
    {
        nBand = atoi(pszBand);
    }

/* -------------------------------------------------------------------- */
/*      Set the band if provided as an attribute.                       */
/* -------------------------------------------------------------------- */
    const char *pszDataType = CPLGetXMLValue( psTree, "dataType", NULL);
    if( pszDataType != NULL )
    {
        eDataType = GDALGetDataTypeByName(pszDataType);
    }

/* -------------------------------------------------------------------- */
/*      Apply any band level metadata.                                  */
/* -------------------------------------------------------------------- */
    oMDMD.XMLInit( psTree, TRUE );

/* -------------------------------------------------------------------- */
/*      Collect various other items of metadata.                        */
/* -------------------------------------------------------------------- */
    SetDescription( CPLGetXMLValue( psTree, "Description", "" ) );
    
    if( CPLGetXMLValue( psTree, "NoDataValue", NULL ) != NULL )
        SetNoDataValue( CPLAtofM(CPLGetXMLValue( psTree, "NoDataValue", "0" )) );

    if( CPLGetXMLValue( psTree, "HideNoDataValue", NULL ) != NULL )
        bHideNoDataValue = CSLTestBoolean( CPLGetXMLValue( psTree, "HideNoDataValue", "0" ) );

    SetUnitType( CPLGetXMLValue( psTree, "UnitType", NULL ) );

    SetOffset( atof(CPLGetXMLValue( psTree, "Offset", "0.0" )) );
    SetScale( atof(CPLGetXMLValue( psTree, "Scale", "1.0" )) );

    if( CPLGetXMLValue( psTree, "ColorInterp", NULL ) != NULL )
    {
        const char *pszInterp = CPLGetXMLValue( psTree, "ColorInterp", NULL );
        SetColorInterpretation(GDALGetColorInterpretationByName(pszInterp));
    }

/* -------------------------------------------------------------------- */
/*      Category names.                                                 */
/* -------------------------------------------------------------------- */
    if( CPLGetXMLNode( psTree, "CategoryNames" ) != NULL )
    {
        CPLXMLNode *psEntry;

        CSLDestroy( papszCategoryNames );
        papszCategoryNames = NULL;

        CPLStringList oCategoryNames;

        for( psEntry = CPLGetXMLNode( psTree, "CategoryNames" )->psChild;
             psEntry != NULL; psEntry = psEntry->psNext )
        {
            if( psEntry->eType != CXT_Element 
                || !EQUAL(psEntry->pszValue,"Category") 
                || (psEntry->psChild != NULL && psEntry->psChild->eType != CXT_Text) )
                continue;
            
            oCategoryNames.AddString(
                                (psEntry->psChild) ? psEntry->psChild->pszValue : "");
        }

        papszCategoryNames = oCategoryNames.StealList();
    }

/* -------------------------------------------------------------------- */
/*      Collect a color table.                                          */
/* -------------------------------------------------------------------- */
    if( CPLGetXMLNode( psTree, "ColorTable" ) != NULL )
    {
        CPLXMLNode *psEntry;
        GDALColorTable oTable;
        int        iEntry = 0;

        for( psEntry = CPLGetXMLNode( psTree, "ColorTable" )->psChild;
             psEntry != NULL; psEntry = psEntry->psNext )
        {
            GDALColorEntry sCEntry;

            sCEntry.c1 = (short) atoi(CPLGetXMLValue( psEntry, "c1", "0" ));
            sCEntry.c2 = (short) atoi(CPLGetXMLValue( psEntry, "c2", "0" ));
            sCEntry.c3 = (short) atoi(CPLGetXMLValue( psEntry, "c3", "0" ));
            sCEntry.c4 = (short) atoi(CPLGetXMLValue( psEntry, "c4", "255" ));

            oTable.SetColorEntry( iEntry++, &sCEntry );
        }
        
        SetColorTable( &oTable );
    }

/* -------------------------------------------------------------------- */
/*      Histograms                                                      */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psHist = CPLGetXMLNode( psTree, "Histograms" );
    if( psHist != NULL )
    {
        CPLXMLNode *psNext = psHist->psNext;
        psHist->psNext = NULL;

        psSavedHistograms = CPLCloneXMLTree( psHist );
        psHist->psNext = psNext;
    }

/* ==================================================================== */
/*      Overviews                                                       */
/* ==================================================================== */
    CPLXMLNode *psNode;

    for( psNode = psTree->psChild; psNode != NULL; psNode = psNode->psNext )
    {
        if( psNode->eType != CXT_Element
            || !EQUAL(psNode->pszValue,"Overview") )
            continue;

/* -------------------------------------------------------------------- */
/*      Prepare filename.                                               */
/* -------------------------------------------------------------------- */
        char *pszSrcDSName = NULL;
        CPLXMLNode* psFileNameNode=CPLGetXMLNode(psNode,"SourceFilename");
        const char *pszFilename = 
            psFileNameNode ? CPLGetXMLValue(psFileNameNode,NULL, NULL) : NULL;

        if( pszFilename == NULL )
        {
            CPLError( CE_Warning, CPLE_AppDefined, 
                      "Missing <SourceFilename> element in Overview." );
            return CE_Failure;
        }

        if (EQUALN(pszFilename, "MEM:::", 6) && pszVRTPath != NULL &&
            !CSLTestBoolean(CPLGetConfigOption("VRT_ALLOW_MEM_DRIVER", "NO")))
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                    "<SourceFilename> points to a MEM dataset, which is rather suspect! "
                    "If you know what you are doing, define the VRT_ALLOW_MEM_DRIVER configuration option to YES" );
            return CE_Failure;
        }

        if( pszVRTPath != NULL
            && atoi(CPLGetXMLValue( psFileNameNode, "relativetoVRT", "0")) )
        {
            pszSrcDSName = CPLStrdup(
                CPLProjectRelativeFilename( pszVRTPath, pszFilename ) );
        }
        else
            pszSrcDSName = CPLStrdup( pszFilename );

/* -------------------------------------------------------------------- */
/*      Get the raster band.                                            */
/* -------------------------------------------------------------------- */
        int nSrcBand = atoi(CPLGetXMLValue(psNode,"SourceBand","1"));

        apoOverviews.resize( apoOverviews.size() + 1 );
        apoOverviews[apoOverviews.size()-1].osFilename = pszSrcDSName;
        apoOverviews[apoOverviews.size()-1].nBand = nSrcBand;
        
        CPLFree( pszSrcDSName );
    }

/* ==================================================================== */
/*      Mask band (specific to that raster band)                        */
/* ==================================================================== */
    CPLXMLNode* psMaskBandNode = CPLGetXMLNode(psTree, "MaskBand");
    if (psMaskBandNode)
        psNode = psMaskBandNode->psChild;
    else
        psNode = NULL;
    for( ; psNode != NULL; psNode = psNode->psNext )
    {
        if( psNode->eType != CXT_Element
            || !EQUAL(psNode->pszValue,"VRTRasterBand") )
            continue;

        if( ((VRTDataset*)poDS)->poMaskBand != NULL)
        {
            CPLError( CE_Warning, CPLE_AppDefined,
                       "Illegal mask band at raster band level when a dataset mask band already exists." );
            break;
        }

        const char *pszSubclass = CPLGetXMLValue( psNode, "subclass",
                                                    "VRTSourcedRasterBand" );
        VRTRasterBand  *poBand = NULL;

        if( EQUAL(pszSubclass,"VRTSourcedRasterBand") )
            poBand = new VRTSourcedRasterBand( GetDataset(), 0 );
        else if( EQUAL(pszSubclass, "VRTDerivedRasterBand") )
            poBand = new VRTDerivedRasterBand( GetDataset(), 0 );
        else if( EQUAL(pszSubclass, "VRTRawRasterBand") )
            poBand = new VRTRawRasterBand( GetDataset(), 0 );
        else if( EQUAL(pszSubclass, "VRTWarpedRasterBand") )
            poBand = new VRTWarpedRasterBand( GetDataset(), 0 );
        else
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                        "VRTRasterBand of unrecognised subclass '%s'.",
                        pszSubclass );
            break;
        }


        if( poBand->XMLInit( psNode, pszVRTPath ) == CE_None )
        {
            SetMaskBand(poBand);
        }

        break;
    }

    return CE_None;
}
Example #8
0
CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
    CPLErr ret = CE_None;

    char* pszXML = CPLSerializeXMLTree( config );
    if (pszXML)
    {
        m_osXML = pszXML;
        CPLFree(pszXML);
    }

    // Initialize the minidriver, which can set parameters for the dataset using member functions
    CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
    if (service_node != NULL)
    {
        const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
        if (!service_name.empty())
        {
            GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
            GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
            if (mdf != NULL)
            {
                m_mini_driver = mdf->New();
                m_mini_driver->m_parent_dataset = this;
                if (m_mini_driver->Initialize(service_node) == CE_None)
                {
                    m_mini_driver_caps.m_capabilities_version = -1;
                    m_mini_driver->GetCapabilities(&m_mini_driver_caps);
                    if (m_mini_driver_caps.m_capabilities_version == -1)
                    {
                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
                        ret = CE_Failure;
                    }
                }
                else
                {
                    delete m_mini_driver;
                    m_mini_driver = NULL;

                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
                    ret = CE_Failure;
                }
            }
            else
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
                ret = CE_Failure;
            }
        }
        else
        {
            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
            ret = CE_Failure;
        }
    }
    else
    {
        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
        ret = CE_Failure;
    }


    /*
      Parameters that could be set by minidriver already, based on server side information.
      If the size is set, minidriver has done this already
      A "server" side minidriver needs to set at least:
      - Blocksize (x and y)
      - Clamp flag (defaults to true)
      - DataWindow
      - Band Count
      - Data Type
      It should also initialize and register the bands and overviews.
    */

    if (m_data_window.m_sx<1)
    {
        int nOverviews = 0;

        if (ret == CE_None)
        {
            m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
            m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
            if (m_block_size_x <= 0 || m_block_size_y <= 0)
            {
                CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
                ret = CE_Failure;
            }
        }

        if (ret == CE_None)
        {
            m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
            if (m_clamp_requests<0)
            {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
                ret = CE_Failure;
            }
        }

        if (ret == CE_None)
        {
            CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
            if (data_window_node == NULL && m_bNeedsDataWindow)
            {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
                ret = CE_Failure;
            }
            else
            {
                CPLString osDefaultX0, osDefaultX1, osDefaultY0, osDefaultY1;
                CPLString osDefaultTileCountX, osDefaultTileCountY, osDefaultTileLevel;
                CPLString osDefaultOverviewCount;
                osDefaultX0.Printf("%.8f", m_default_data_window.m_x0);
                osDefaultX1.Printf("%.8f", m_default_data_window.m_x1);
                osDefaultY0.Printf("%.8f", m_default_data_window.m_y0);
                osDefaultY1.Printf("%.8f", m_default_data_window.m_y1);
                osDefaultTileCountX.Printf("%d", m_default_tile_count_x);
                osDefaultTileCountY.Printf("%d", m_default_tile_count_y);
                if (m_default_data_window.m_tlevel >= 0)
                    osDefaultTileLevel.Printf("%d", m_default_data_window.m_tlevel);
                if (m_default_overview_count >= 0)
                    osDefaultOverviewCount.Printf("%d", m_default_overview_count);
                const char *overview_count = CPLGetXMLValue(config, "OverviewCount", osDefaultOverviewCount);
                const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", osDefaultX0);
                const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", osDefaultY0);
                const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", osDefaultX1);
                const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", osDefaultY1);
                const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
                const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
                const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
                const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
                const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
                const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
                const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
                const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");

                if (ret == CE_None)
                {
                    if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0'))
                    {
                        m_data_window.m_x0 = CPLAtof(ulx);
                        m_data_window.m_y0 = CPLAtof(uly);
                        m_data_window.m_x1 = CPLAtof(lrx);
                        m_data_window.m_y1 = CPLAtof(lry);
                    }
                    else
                    {
                        CPLError(CE_Failure, CPLE_AppDefined,
                                 "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
                        ret = CE_Failure;
                    }
                }

                m_data_window.m_tlevel = atoi(tlevel);

                if (ret == CE_None)
                {
                    if ((sx[0] != '\0') && (sy[0] != '\0'))
                    {
                        m_data_window.m_sx = atoi(sx);
                        m_data_window.m_sy = atoi(sy);
                    }
                    else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0'))
                    {
                        int tile_count_x = atoi(str_tile_count_x);
                        int tile_count_y = atoi(str_tile_count_y);
                        m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
                        m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
                    }
                    else
                    {
                        CPLError(CE_Failure, CPLE_AppDefined,
                                 "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
                        ret = CE_Failure;
                    }
                }
                if (ret == CE_None)
                {
                    if ((tx[0] != '\0') && (ty[0] != '\0'))
                    {
                        m_data_window.m_tx = atoi(tx);
                        m_data_window.m_ty = atoi(ty);
                    }
                    else
                    {
                        CPLError(CE_Failure, CPLE_AppDefined,
                                 "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
                        ret = CE_Failure;
                    }
                }

                if (ret == CE_None)
                {
                    if (overview_count[0] != '\0')
                    {
                        nOverviews = atoi(overview_count);
                    }
                    else if (tlevel[0] != '\0')
                    {
                        nOverviews = m_data_window.m_tlevel;
                    }
                    else
                    {
                        const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
                        double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0)
                            - log(static_cast<double>(min_overview_size)) / log(2.0);
                        nOverviews = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
                    }
                }
                if (ret == CE_None)
                {
                    CPLString y_origin_str = y_origin;
                    if (y_origin_str == "top") {
                        m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
                    } else if (y_origin_str == "bottom") {
                        m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
                    } else if (y_origin_str == "default") {
                        m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
                    } else {
                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to "
                                 "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
                        ret = CE_Failure;
                    }
                }
            }
        }

        if (ret == CE_None)
        {
            if (nBands<1)
                nBands=atoi(CPLGetXMLValue(config,"BandsCount","3"));
            if (nBands<1)
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "GDALWMS: Bad number of bands.");
                ret = CE_Failure;
            }
        }

        if (ret == CE_None)
        {
            const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
            m_data_type = GDALGetDataTypeByName( data_type );
            if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
            {
                CPLError( CE_Failure, CPLE_AppDefined,
                          "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
                ret = CE_Failure;
            }
        }

        // Initialize the bands and the overviews.  Assumes overviews are powers of two
        if (ret == CE_None)
        {
            nRasterXSize = m_data_window.m_sx;
            nRasterYSize = m_data_window.m_sy;

            if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
                !GDALCheckBandCount(nBands, TRUE))
            {
                return CE_Failure;
            }

            GDALColorInterp default_color_interp[4][4] = {
                { GCI_GrayIndex, GCI_Undefined, GCI_Undefined, GCI_Undefined },
                { GCI_GrayIndex, GCI_AlphaBand, GCI_Undefined, GCI_Undefined },
                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_Undefined },
                { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand }
            };
            for (int i = 0; i < nBands; ++i)
            {
                GDALColorInterp color_interp = (nBands <= 4 && i <= 3 ? default_color_interp[nBands - 1][i] : GCI_Undefined);
                GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
                band->m_color_interp = color_interp;
                SetBand(i + 1, band);
                double scale = 0.5;
                for (int j = 0; j < nOverviews; ++j)
                {
                    band->AddOverview(scale);
                    band->m_color_interp = color_interp;
                    scale *= 0.5;
                }
            }
        }
    }
    
    // UserPwd 
    const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
    if (pszUserPwd[0] != '\0')
        m_osUserPwd = pszUserPwd;

    const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
    if (pszUserAgent[0] != '\0')
        m_osUserAgent = pszUserAgent;
    
    const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
    if (pszReferer[0] != '\0')
        m_osReferer = pszReferer;
    
    if (ret == CE_None) {
        const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
        if(pszHttpZeroBlockCodes[0] == '\0') {
            m_http_zeroblock_codes.push_back(204);
        } else {
            char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
            int nCount = CSLCount(kv);
            for(int i=0; i<nCount; i++) {
                int code = atoi(kv[i]);
                if(code <= 0) {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
                             kv[i]);
                    ret = CE_Failure;
                    break;
                }
                m_http_zeroblock_codes.push_back(code);
            }
            CSLDestroy(kv);
        }
    }

    if (ret == CE_None) {
        const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
        if(pszZeroExceptions[0] != '\0') {
            m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
            if (m_zeroblock_on_serverexceptions == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
                         pszZeroExceptions);
                ret = CE_Failure;
            }
        }
    }

    if (ret == CE_None) {
        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
        if (max_conn[0] != '\0') {
            m_http_max_conn = atoi(max_conn);
        } else {
            m_http_max_conn = 2;
        }
    }
    if (ret == CE_None) {
        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
        if (timeout[0] != '\0') {
            m_http_timeout = atoi(timeout);
        } else {
            m_http_timeout = 300;
        }
    }
    if (ret == CE_None) {
        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
        if (offline_mode[0] != '\0') {
            const int offline_mode_bool = StrToBool(offline_mode);
            if (offline_mode_bool == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
                ret = CE_Failure;
            } else {
                m_offline_mode = offline_mode_bool;
            }
        } else {
            m_offline_mode = 0;
        }
    }

    if (ret == CE_None) {
        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
        if (advise_read[0] != '\0') {
            const int advise_read_bool = StrToBool(advise_read);
            if (advise_read_bool == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
                ret = CE_Failure;
            } else {
                m_use_advise_read = advise_read_bool;
            }
        } else {
            m_use_advise_read = 0;
        }
    }

    if (ret == CE_None) {
        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
        if (m_use_advise_read) {
            if (verify_advise_read[0] != '\0') {
                const int verify_advise_read_bool = StrToBool(verify_advise_read);
                if (verify_advise_read_bool == -1) {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
                    ret = CE_Failure;
                } else {
                    m_verify_advise_read = verify_advise_read_bool;
                }
            } else {
                m_verify_advise_read = 1;
            }
        }
    }

    // Let the local configuration override the minidriver supplied projection

    if (ret == CE_None) {
        const char *proj = CPLGetXMLValue(config, "Projection", "");
        if (proj[0] != '\0') {
            m_projection = ProjToWKT(proj);
            if (m_projection.size() == 0) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
                ret = CE_Failure;
            }
        }
    }

    // Same for Min, Max and NoData, defined per band or per dataset
    // If they are set as null strings, they clear the server declared values
    if (ret == CE_None) {
        // Data values are attributes, they include NoData Min and Max
        // TODO: document those options
        if (0!=CPLGetXMLNode(config,"DataValues")) {
            const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
            if (nodata!=NULL) WMSSetNoDataValue(nodata);
            const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
            if (min!=NULL) WMSSetMinValue(min);
            const char *max=CPLGetXMLValue(config,"DataValues.max",NULL);
            if (max!=NULL) WMSSetMaxValue(max);
        }
    }

    if (ret == CE_None) {
        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
        if (cache_node != NULL) {
            m_cache = new GDALWMSCache();
            if (m_cache->Initialize(cache_node) != CE_None) {
                delete m_cache;
                m_cache = NULL;
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
                ret = CE_Failure;
            }
        }
    }
    
    if (ret == CE_None) {
    	const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
    	if (v == -1) {
	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
	    ret = CE_Failure;
	} else {
	    m_unsafeSsl = v;
	}
    }

    if (ret == CE_None) {
        /* If we dont have projection already set ask mini-driver. */
        if (!m_projection.size()) {
            const char *proj = m_mini_driver->GetProjectionInWKT();
            if (proj != NULL) {
                m_projection = proj;
            }
        }
    }

    return ret;
}
CPLErr GDALWMSMiniDriver_TiledWMS::Initialize(CPLXMLNode *config, CPL_UNUSED char **OpenOptions)
{
    CPLErr ret = CE_None;
    CPLXMLNode *tileServiceConfig=NULL;
    CPLHTTPResult *psResult=NULL;
    CPLXMLNode *TG=NULL;

    char **requests=NULL;
    char **substs=NULL;
    char **keys=NULL;

    for (int once=1;once;once--) { // Something to break out of
        // Parse info from the service

        m_end_url = CPLGetXMLValue(config,"AdditionalArgs","");
        m_base_url = CPLGetXMLValue(config, "ServerURL", "");
        if (m_base_url.empty()) {
            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s ServerURL missing.",SIG);
            break;
        }

        CPLString tiledGroupName (CPLGetXMLValue(config, "TiledGroupName", ""));
        if (tiledGroupName.empty()) {
            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s TiledGroupName missing.",SIG);
            break;
        }

        // Change strings, key is an attribute, value is the value of the Change node
        // Multiple substitutions are possible
        TG=CPLSearchXMLNode(config, "Change");
        while(TG!=NULL) {
            CPLString name=CPLGetXMLValue(TG,"key","");
            if (name.empty()) {
                CPLError(ret=CE_Failure, CPLE_AppDefined,
                    "%s Change element needs a non-empty \"key\" attribute",SIG);
                break;
            }
            substs=CSLSetNameValue(substs,name,CPLGetXMLValue(TG,"",""));
            TG=SearchXMLSiblings(TG,"Change");
        }
        if (ret!=CE_None) break;

        CPLString getTileServiceUrl = m_base_url + "request=GetTileService";
        psResult = CPLHTTPFetch(getTileServiceUrl, NULL);

        if (NULL==psResult) {
            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Can't use HTTP", SIG);
            break;
        }

        if ((psResult->nStatus!=0)||(NULL==psResult->pabyData)||('\0'==psResult->pabyData[0])) {
            CPLError(ret=CE_Failure, CPLE_AppDefined, "%s Server response error on GetTileService.",SIG);
            break;
        }

        if (NULL==(tileServiceConfig=CPLParseXMLString((const char*)psResult->pabyData))) {
            CPLError(ret=CE_Failure,CPLE_AppDefined, "%s Error parsing the GetTileService response.",SIG);
            break;
        }

        if (NULL==(TG=CPLSearchXMLNode(tileServiceConfig, "TiledPatterns"))) {
            CPLError(ret=CE_Failure,CPLE_AppDefined,
                "%s Can't locate TiledPatterns in server response.",SIG);
            break;
        }

        // Get the global base_url and bounding box, these can be overwritten at the tileGroup level
        // They are just pointers into existing structures, cleanup is not required
        const char *global_base_url=CPLGetXMLValue(tileServiceConfig,"TiledPatterns.OnlineResource.xlink:href","");
        CPLXMLNode *global_latlonbbox=CPLGetXMLNode(tileServiceConfig, "TiledPatterns.LatLonBoundingBox");
        CPLXMLNode *global_bbox=CPLGetXMLNode(tileServiceConfig, "TiledPatterns.BoundingBox");

        if (NULL==(TG=SearchLeafGroupName(TG->psChild,tiledGroupName))) {
            CPLError(ret=CE_Failure,CPLE_AppDefined,
                "%s Can't locate TiledGroup ""%s"" in server response.",SIG,
                tiledGroupName.c_str());
            break;
        }

        int band_count=atoi(CPLGetXMLValue(TG, "Bands", "3"));

        if (!GDALCheckBandCount(band_count, FALSE)) {
            CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
                "Invalid number of bands in server response");
            break;
        }

        // Collect all keys defined by this tileset
        if (NULL!=CPLGetXMLNode(TG,"Key")) {
            CPLXMLNode *node=CPLGetXMLNode(TG,"Key");
                while (NULL!=node) {
                    const char *val=CPLGetXMLValue(node,NULL,NULL);
                    if (val) keys=CSLAddString(keys,val);
                    node=SearchXMLSiblings(node,"Key");
                }
        }

       // Data values are attributes, they include NoData Min and Max
       if (NULL!=CPLGetXMLNode(TG,"DataValues")) {
           const char *nodata=CPLGetXMLValue(TG,"DataValues.NoData",NULL);
           if (nodata!=NULL) m_parent_dataset->WMSSetNoDataValue(nodata);
           const char *min=CPLGetXMLValue(TG,"DataValues.min",NULL);
           if (min!=NULL) m_parent_dataset->WMSSetMinValue(min);
           const char *max=CPLGetXMLValue(TG,"DataValues.max",NULL);
           if (max!=NULL) m_parent_dataset->WMSSetMaxValue(max);
       }

        m_parent_dataset->WMSSetBandsCount(band_count);
        m_parent_dataset->WMSSetDataType(GDALGetDataTypeByName(CPLGetXMLValue(TG, "DataType", "Byte")));
        m_projection_wkt=CPLGetXMLValue(TG, "Projection","");

        m_base_url=CPLGetXMLValue(TG,"OnlineResource.xlink:href",global_base_url);
        if (m_base_url[0]=='\0') {
            CPLError(ret=CE_Failure,CPLE_AppDefined, "%s%s",SIG,
                "Can't locate OnlineResource in the server response.");
            break;
        }

        // Bounding box, local, global, local lat-lon, global lat-lon, in this order
        CPLXMLNode *bbox = CPLGetXMLNode(TG, "BoundingBox");
        if (NULL==bbox) bbox=global_bbox;
        if (NULL==bbox) bbox=CPLGetXMLNode(TG, "LatLonBoundingBox");
        if (NULL==bbox) bbox=global_latlonbbox;

        if (NULL==bbox) {
            CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
                "Can't locate the LatLonBoundingBox in server response.");
            break;
        }

        m_data_window.m_x0=CPLAtof(CPLGetXMLValue(bbox,"minx","0"));
        m_data_window.m_x1=CPLAtof(CPLGetXMLValue(bbox,"maxx","-1"));
        m_data_window.m_y0=CPLAtof(CPLGetXMLValue(bbox,"maxy","0"));
        m_data_window.m_y1=CPLAtof(CPLGetXMLValue(bbox,"miny","-1"));

        if ((m_data_window.m_x1-m_data_window.m_x0)<0) {
            CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s", SIG,
                "Coordinate order in BBox, problem in server response");
            break;
        }

        // Is there a palette?
        //
        // Format is
        // <Palette>
        //   <Size>N</Size> : Optional
        //   <Model>RGBA|RGB|CMYK|HSV|HLS|L</Model> :mandatory
        //   <Entry idx=i c1=v1 c2=v2 c3=v3 c4=v4/> :Optional
        //   <Entry .../>
        // </Palette>
        // the idx attribute is optional, it autoincrements
        // The entries are actually vertices, interpolation takes place inside
        // The palette starts initialized with zeros
        // HSV and HLS are the similar, with c2 and c3 swapped
        // RGB or RGBA are same
        //

        GDALColorTable *poColorTable=NULL;

        if ((band_count==1) && CPLGetXMLNode(TG,"Palette")) {

            CPLXMLNode *node=CPLGetXMLNode(TG,"Palette");

            int entries=static_cast<int>(getXMLNum(node,"Size","255"));
            GDALPaletteInterp eInterp=GPI_RGB;

            CPLString pModel=CPLGetXMLValue(node,"Model","RGB");
            if (!pModel.empty() && pModel.find("RGB")!=std::string::npos)
                eInterp=GPI_RGB;
            else {
                CPLError(CE_Failure, CPLE_AppDefined,
                    "%s Palette Model %s is unknown, use RGB or RGBA",
                    SIG, pModel.c_str());
                return CE_Failure;
            }

            if ((entries>0)&&(entries<257)) {
                int start_idx, end_idx;
                GDALColorEntry ce_start={0,0,0,255},ce_end={0,0,0,255};

                // Create it and initialize it to nothing
                poColorTable = new GDALColorTable(eInterp);
                poColorTable->CreateColorRamp(0,&ce_start,entries-1,&ce_end);
                // Read the values
                CPLXMLNode *p=CPLGetXMLNode(node,"Entry");
                if (p) {
                    // Initialize the first entry
                    start_idx=static_cast<int>(getXMLNum(p,"idx","0"));
                    ce_start=GetXMLColorEntry(p);
                    if (start_idx<0) {
                        CPLError(CE_Failure, CPLE_AppDefined,
                            "%s Palette index %d not allowed",SIG,start_idx);
                        delete poColorTable;
                        return CE_Failure;
                    }
                    poColorTable->SetColorEntry(start_idx,&ce_start);
                    while (NULL!=(p=SearchXMLSiblings(p,"Entry"))) {
                        // For every entry, create a ramp
                        ce_end=GetXMLColorEntry(p);
                        end_idx=static_cast<int>(getXMLNum(p,"idx",CPLString().FormatC(start_idx+1).c_str()));
                        if ((end_idx<=start_idx)||(start_idx>=entries)) {
                            CPLError(CE_Failure, CPLE_AppDefined,
                                "%s Index Error at index %d",SIG,end_idx);
                            delete poColorTable;
                            return CE_Failure;
                        }
                        poColorTable->CreateColorRamp(start_idx,&ce_start,
                            end_idx,&ce_end);
                        ce_start=ce_end;
                        start_idx=end_idx;
                    }
                }
                m_parent_dataset->SetColorTable(poColorTable);
            } else {
                CPLError(CE_Failure, CPLE_AppDefined,"%s Palette definition error",SIG);
                return CE_Failure;
            }
        }

        int overview_count=0;
        CPLXMLNode *Pattern=TG->psChild;

        m_bsx=m_bsy=-1;
        m_data_window.m_sx=m_data_window.m_sy=0;

        for (int once2=1;once2;once2--) { // Something to break out of
            while ((NULL!=Pattern)&&(NULL!=(Pattern=SearchXMLSiblings(Pattern,"=TilePattern")))) {
                int mbsx,mbsy;

                CPLString request;
                FindChangePattern(Pattern->psChild->pszValue,substs,keys,request);

                char **papszTokens=CSLTokenizeString2(request,"&",0);

                const char* pszWIDTH = CSLFetchNameValue(papszTokens,"WIDTH");
                const char* pszHEIGHT = CSLFetchNameValue(papszTokens,"HEIGHT");
                if (pszWIDTH == NULL || pszHEIGHT == NULL)
                {
                    CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
                        "Cannot find width and/or height parameters.");
                    overview_count=0;
                    CSLDestroy(papszTokens);
                    break;
                }

                mbsx=atoi(pszWIDTH);
                mbsy=atoi(pszHEIGHT);
                if (m_projection_wkt.empty()) {
                    m_projection_wkt = CSLFetchNameValueDef(papszTokens,"SRS", "");
                    if (!m_projection_wkt.empty())
                        m_projection_wkt=ProjToWKT(m_projection_wkt);
                }

                if (-1==m_bsx) m_bsx=mbsx;
                if (-1==m_bsy) m_bsy=mbsy;
                if ((m_bsx!=mbsx)||(m_bsy!=mbsy)) {
                    CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
                        "Tileset uses different block sizes.");
                    overview_count=0;
                    CSLDestroy(papszTokens);
                    break;
                }

                double x,y,X,Y;
                if (CPLsscanf(CSLFetchNameValueDef(papszTokens,"BBOX", ""),"%lf,%lf,%lf,%lf",&x,&y,&X,&Y)!=4)
                {
                    CPLError(ret=CE_Failure,CPLE_AppDefined,
                        "%s Error parsing BBOX, pattern %d\n",SIG,overview_count+1);
                    CSLDestroy(papszTokens);
                    break;
                }
                // Pick the largest size
                int sx=static_cast<int>((m_data_window.m_x1-m_data_window.m_x0)/(X-x)*m_bsx);
                int sy=static_cast<int>(fabs((m_data_window.m_y1-m_data_window.m_y0)/(Y-y)*m_bsy));
                if (sx>m_data_window.m_sx) m_data_window.m_sx=sx;
                if (sy>m_data_window.m_sy) m_data_window.m_sy=sy;
                CSLDestroy(papszTokens);

                // Only use overlays where the top coordinate is within a pixel from the top of coverage
                double pix_off,temp;
                pix_off=m_bsy*modf(fabs((Y-m_data_window.m_y0)/(Y-y)),&temp);
                if ((pix_off<1)||((m_bsy-pix_off)<1)) {
                    requests=CSLAddString(requests,request);
                    overview_count++;
                } else
                    CPLError(CE_Warning,CPLE_AppDefined,
                    "%s Overlay size %dX%d can't be used due to alignment",SIG,sx,sy);

                Pattern=Pattern->psNext;

            }

            // The tlevel is needed, the tx and ty are not used by this minidriver
            m_data_window.m_tlevel = 0;
            m_data_window.m_tx = 0;
            m_data_window.m_ty = 0;

            // Make sure the parent_dataset values are set before creating the bands
            m_parent_dataset->WMSSetBlockSize(m_bsx,m_bsy);
            m_parent_dataset->WMSSetRasterSize(m_data_window.m_sx,m_data_window.m_sy);

            m_parent_dataset->WMSSetDataWindow(m_data_window);
            //m_parent_dataset->WMSSetOverviewCount(overview_count);
            m_parent_dataset->WMSSetClamp(false);

            // Ready for the Rasterband creation
            for (int i=0;i<overview_count;i++) {
                CPLString request=GetLowestScale(requests,i);
                double scale=Scale(request);

                // Base scale should be very close to 1
                if ((0==i)&&(fabs(scale-1) > 1e-6)) {
                    CPLError(ret=CE_Failure,CPLE_AppDefined,"%s%s",SIG,
                        "Base resolution pattern missing.");
                    break;
                }

                // Prepare the request and insert it back into the list
                // Find returns an answer relative to the original string start!
                size_t startBbox=FindBbox(request);
                size_t endBbox=request.find('&',startBbox);
                if (endBbox==std::string::npos) endBbox=request.size();
                request.replace(startBbox,endBbox-startBbox,"${GDAL_BBOX}");
                requests = CSLInsertString(requests,i,request);

                // Create the Rasterband or overview
                for (int j = 1; j <= band_count; j++) {
                    if (i!=0)
                        m_parent_dataset->mGetBand(j)->AddOverview(scale);
                    else { // Base resolution
                        GDALWMSRasterBand *band=new
                            GDALWMSRasterBand(m_parent_dataset,j,1);
                        if (poColorTable!=NULL) band->SetColorInterpretation(GCI_PaletteIndex);
                        else band->SetColorInterpretation(BandInterp(band_count,j));
                        m_parent_dataset->mSetBand(j, band);
                    };
                }
            }
            if ((overview_count==0)||(m_bsx<1)||(m_bsy<1)) {
                CPLError(ret=CE_Failure,CPLE_AppDefined,
                    "%s No usable TilePattern elements found",SIG);
                break;
            }
        }
    }

    CSLDestroy(keys);
    CSLDestroy(substs);
    if (tileServiceConfig) CPLDestroyXMLNode(tileServiceConfig);
    if (psResult) CPLHTTPDestroyResult(psResult);

    m_requests=requests;
    return ret;
}
Example #10
0
CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
    CPLErr ret = CE_None;

    if (ret == CE_None) {
        const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
        if (max_conn[0] != '\0') {
            m_http_max_conn = atoi(max_conn);
        } else {
            m_http_max_conn = 2;
        }
    }
    if (ret == CE_None) {
        const char *timeout = CPLGetXMLValue(config, "Timeout", "");
        if (timeout[0] != '\0') {
            m_http_timeout = atoi(timeout);
        } else {
            m_http_timeout = 300;
        }
    }
    if (ret == CE_None) {
        const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
        if (offline_mode[0] != '\0') {
            const int offline_mode_bool = StrToBool(offline_mode);
            if (offline_mode_bool == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
                ret = CE_Failure;
            } else {
                m_offline_mode = offline_mode_bool;
            }
        } else {
            m_offline_mode = 0;
        }
    }
    if (ret == CE_None) {
        const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
        if (advise_read[0] != '\0') {
            const int advise_read_bool = StrToBool(advise_read);
            if (advise_read_bool == -1) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
                ret = CE_Failure;
            } else {
                m_use_advise_read = advise_read_bool;
            }
        } else {
            m_use_advise_read = 0;
        }
    }
    if (ret == CE_None) {
        const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
        if (m_use_advise_read) {
            if (verify_advise_read[0] != '\0') {
                const int verify_advise_read_bool = StrToBool(verify_advise_read);
                if (verify_advise_read_bool == -1) {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
                    ret = CE_Failure;
                } else {
                    m_verify_advise_read = verify_advise_read_bool;
                }
            } else {
                m_verify_advise_read = 1;
            }
        }
    }
    if (ret == CE_None) {
        const char *block_size_x = CPLGetXMLValue(config, "BlockSizeX", "1024");
        const char *block_size_y = CPLGetXMLValue(config, "BlockSizeY", "1024");
        m_block_size_x = atoi(block_size_x);
        m_block_size_y = atoi(block_size_y);
        if (m_block_size_x <= 0 || m_block_size_y <= 0)
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
            ret = CE_Failure;
        }
    }
    if (ret == CE_None)
    {
        const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
        m_data_type = GDALGetDataTypeByName( data_type );
        if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
            ret = CE_Failure;
        }
    }
    if (ret == CE_None) {
    	const int clamp_requests_bool = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
    	if (clamp_requests_bool == -1) {
	    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true / false expected.");
	    ret = CE_Failure;
	} else {
	    m_clamp_requests = clamp_requests_bool;
	}
    }
    if (ret == CE_None) {
        CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
        if (data_window_node == NULL) {
            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
            ret = CE_Failure;
        } else {
            const char *overview_count = CPLGetXMLValue(config, "OverviewCount", "");
            const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", "-180.0");
            const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", "90.0");
            const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", "180.0");
            const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", "-90.0");
            const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
            const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
            const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
            const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
            const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", "");
            const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", "1");
            const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", "1");
            const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");

            if (ret == CE_None) {
                if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0')) {
                    m_data_window.m_x0 = atof(ulx);
                    m_data_window.m_y0 = atof(uly);
                    m_data_window.m_x1 = atof(lrx);
                    m_data_window.m_y1 = atof(lry);
                } else {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
                    ret = CE_Failure;
                }
            }
            if (ret == CE_None) {
                if (tlevel[0] != '\0') {
                    m_data_window.m_tlevel = atoi(tlevel);
                } else {
                    m_data_window.m_tlevel = 0;
                }
            }
            if (ret == CE_None) {
                if ((sx[0] != '\0') && (sy[0] != '\0')) {
                    m_data_window.m_sx = atoi(sx);
                    m_data_window.m_sy = atoi(sy);
                } else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0')) {
                    int tile_count_x = atoi(str_tile_count_x);
                    int tile_count_y = atoi(str_tile_count_y);
                    m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
                    m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
                } else {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
                    ret = CE_Failure;
                }
            }
            if (ret == CE_None) {
                if ((tx[0] != '\0') && (ty[0] != '\0')) {
                    m_data_window.m_tx = atoi(tx);
                    m_data_window.m_ty = atoi(ty);
                } else {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
                    ret = CE_Failure;
                }
            }
            if (ret == CE_None) {
                if (overview_count[0] != '\0') {
                    m_overview_count = atoi(overview_count);
                } else if (tlevel[0] != '\0') {
                    m_overview_count = m_data_window.m_tlevel;
                } else {
                    const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
                    double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0) 
                                - log(static_cast<double>(min_overview_size)) / log(2.0);
                    m_overview_count = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
                }
            }
            if (ret == CE_None) {
                CPLString y_origin_str = y_origin;
                if (y_origin_str == "top") {
                    m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
                } else if (y_origin_str == "bottom") {
                    m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
                } else if (y_origin_str == "default") {
                    m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
                } else {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to " 
                                "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
                    ret = CE_Failure;
                }
            }
        }
    }
    if (ret == CE_None) {
        const char *proj = CPLGetXMLValue(config, "Projection", "");
        if (proj[0] != '\0') {
            m_projection = ProjToWKT(proj);
            if (m_projection.size() == 0) {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
                ret = CE_Failure;
            }
        }
    }
    
    const char *bands_count = CPLGetXMLValue(config, "BandsCount", "3");
    int nBandCount = atoi(bands_count);
    
    if (ret == CE_None) {
        CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
        if (cache_node != NULL) {
            m_cache = new GDALWMSCache();
            if (m_cache->Initialize(cache_node) != CE_None) {
                delete m_cache;
                m_cache = NULL;
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
                ret = CE_Failure;
            }
        }
    }
    if (ret == CE_None) {
        CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
        if (service_node != NULL) {
            const char *service_name = CPLGetXMLValue(service_node, "name", "");
            if (service_name[0] != '\0') {
                GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
                GDALWMSMiniDriverFactory *const mdf = mdm->Find(CPLString(service_name));
                if (mdf != NULL) {
                    m_mini_driver = mdf->New();
                    m_mini_driver->m_parent_dataset = this;
                    if (m_mini_driver->Initialize(service_node) == CE_None) {
                        m_mini_driver_caps.m_capabilities_version = -1;
                        m_mini_driver->GetCapabilities(&m_mini_driver_caps);
                        if (m_mini_driver_caps.m_capabilities_version == -1) {
                            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
                            ret = CE_Failure;
                        }
                    } else {
                        delete m_mini_driver;
                        m_mini_driver = NULL;

                        CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
                        ret = CE_Failure;
                    }
                } else {
                    CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No mini-driver registered for '%s'.", service_name);
                    ret = CE_Failure;
                }
            } else {
                CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
                ret = CE_Failure;
            }
        } else {
            CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
            ret = CE_Failure;
        }
    }
    if (ret == CE_None) {
        nRasterXSize = m_data_window.m_sx;
        nRasterYSize = m_data_window.m_sy;

        if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
            !GDALCheckBandCount(nBandCount, TRUE))
        {
            return CE_Failure;
        }

        for (int i = 0; i < nBandCount; ++i) {
            GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
            SetBand(i + 1, band);
            double scale = 0.5;
            for (int j = 0; j < m_overview_count; ++j) {
                band->AddOverview(scale);
                scale *= 0.5;
            }
        }
    }

    if (ret == CE_None) {
        /* If we dont have projection already set ask mini-driver. */
        if (!m_projection.size()) {
            const char *proj = m_mini_driver->GetProjectionInWKT();
            if (proj != NULL) {
                m_projection = proj;
            }
        }
    }

    return ret;
}
Example #11
0
GDALDataset *ISCEDataset::Open( GDALOpenInfo *poOpenInfo )
{
/* -------------------------------------------------------------------- */
/*      Confirm that the header is compatible with a ISCE dataset.    */
/* -------------------------------------------------------------------- */
    if ( !Identify(poOpenInfo) )
    {
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Open and parse the .xml file                                    */
/* -------------------------------------------------------------------- */
    const CPLString osXMLFilename = getXMLFilename( poOpenInfo );
    CPLXMLNode *psNode = CPLParseXMLFile( osXMLFilename );
    if ( psNode == NULL || CPLGetXMLNode( psNode, "=imageFile" ) == NULL )
    {
        CPLDestroyXMLNode( psNode );
        return NULL;
    }
    CPLXMLNode *psCur  = CPLGetXMLNode( psNode, "=imageFile" )->psChild;
    char **papszXmlProps = NULL;
    while ( psCur != NULL ) {
        const char *name, *value;
        if ( strcmp(psCur->pszValue, "property") != 0) {
            psCur = psCur->psNext;
            continue;
        }
        name = CPLGetXMLValue( psCur, "name", NULL );
        value = CPLGetXMLValue( psCur, "value.", NULL );
        papszXmlProps = CSLSetNameValue( papszXmlProps,
                                         name, value );
        psCur = psCur->psNext;
    }
    /* TODO: extract <component name=Coordinate[12]> for georeferencing */
    CPLDestroyXMLNode( psNode );

/* -------------------------------------------------------------------- */
/*      Fetch required fields.                                          */
/* -------------------------------------------------------------------- */
    if ( CSLFetchNameValue( papszXmlProps, "WIDTH" ) == NULL
        || CSLFetchNameValue( papszXmlProps, "LENGTH" ) == NULL
        || CSLFetchNameValue( papszXmlProps, "NUMBER_BANDS" ) == NULL
        || CSLFetchNameValue( papszXmlProps, "DATA_TYPE" ) == NULL
        || CSLFetchNameValue( papszXmlProps, "SCHEME" ) == NULL )
    {
        CSLDestroy( papszXmlProps );
        return NULL;
    }
    const int nWidth = atoi( CSLFetchNameValue( papszXmlProps, "WIDTH" ) );
    const int nFileLength = atoi( CSLFetchNameValue( papszXmlProps, "LENGTH" ) );

/* -------------------------------------------------------------------- */
/*      Update byte order info if image specify something.              */
/* -------------------------------------------------------------------- */
    bool bNativeOrder = true;

    if ( CSLFetchNameValue( papszXmlProps, "BYTE_ORDER" ) != NULL )
    {
        const char *sByteOrder = CSLFetchNameValue( papszXmlProps,
                                                    "BYTE_ORDER" );
#ifdef CPL_LSB
        if ( EQUAL( sByteOrder, "b" ) )
#else
        if ( EQUAL( sByteOrder, "l" ) )
#endif
            bNativeOrder = false;
    }

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    ISCEDataset *poDS = new ISCEDataset();
    poDS->nRasterXSize = nWidth;
    poDS->nRasterYSize = nFileLength;
    poDS->eAccess = poOpenInfo->eAccess;
    poDS->pszXMLFilename = CPLStrdup( osXMLFilename.c_str() );

/* -------------------------------------------------------------------- */
/*      Reopen file in update mode if necessary.                        */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->eAccess == GA_Update )
    {
        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );
    }
    else
    {
        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    }
    if( poDS->fpImage == NULL )
    {
        CSLDestroy( papszXmlProps );
        delete poDS;
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Failed to re-open %s within ISCE driver.\n",
                  poOpenInfo->pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    const char *sDataType =
        CSLFetchNameValue( (char **)apszISCE2GDALDatatypes,
                           CSLFetchNameValue( papszXmlProps, "DATA_TYPE" ) );
    const GDALDataType eDataType = GDALGetDataTypeByName( sDataType );
    const int nBands = atoi( CSLFetchNameValue( papszXmlProps, "NUMBER_BANDS" ) );
    const char *sScheme = CSLFetchNameValue( papszXmlProps, "SCHEME" );
    int nPixelOffset, nLineOffset, nBandOffset;
    if ( EQUAL( sScheme, "BIL" ) )
    {
                poDS->eScheme = BIL;
        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
        nLineOffset = nPixelOffset * nWidth * nBands;
        nBandOffset = GDALGetDataTypeSize(eDataType)/8 * nWidth;
    }
    else if ( EQUAL( sScheme, "BIP" ) )
    {
        poDS->eScheme = BIP;
        nPixelOffset = GDALGetDataTypeSize(eDataType)/8 * nBands;
        nLineOffset = nPixelOffset * nWidth;
        if( nBands > 1 )
        {
            // GDAL 2.1.0 had a value of nLineOffset that was equal to the theoretical
            // nLineOffset multiplied by nBands...
            VSIFSeekL( poDS->fpImage, 0, SEEK_END );
            const GUIntBig nWrongFileSize = GDALGetDataTypeSizeBytes(eDataType) *
              nWidth * (static_cast<GUIntBig>(nFileLength - 1) * nBands * nBands + nBands);
            if( VSIFTellL( poDS->fpImage ) == nWrongFileSize )
            {
                CPLError(CE_Warning, CPLE_AppDefined,
                         "This file has been incorrectly generated by an older "
                         "GDAL version whose line offset computation was erroneous. "
                         "Taking that into account, but the file should be re-encoded ideally");
                nLineOffset = nLineOffset * nBands;
            }
        }
        nBandOffset = GDALGetDataTypeSize(eDataType)/8;
    }
    else if ( EQUAL( sScheme, "BSQ" ) )
    {
        poDS->eScheme = BSQ;
        nPixelOffset = GDALGetDataTypeSize(eDataType)/8;
        nLineOffset = nPixelOffset * nWidth;
        nBandOffset = nLineOffset * nFileLength;
    }
    else
    {
        CSLDestroy( papszXmlProps );
        delete poDS;
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Unknown scheme \"%s\" within ISCE raster.\n",
                  CSLFetchNameValue( papszXmlProps, "SCHEME" ) );
        return NULL;
    }
    poDS->nBands = nBands;
    for (int b = 0; b < nBands; b++)
    {
        poDS->SetBand( b + 1,
                       new ISCERasterBand( poDS, b + 1, poDS->fpImage,
                                             nBandOffset * b,
                                             nPixelOffset, nLineOffset,
                                             eDataType, TRUE,
                                             bNativeOrder, FALSE ) );
    }

/* -------------------------------------------------------------------- */
/*      Interpret georeferencing, if present.                           */
/* -------------------------------------------------------------------- */
   /* TODO */

/* -------------------------------------------------------------------- */
/*      Set all the other header metadata into the ISCE domain       */
/* -------------------------------------------------------------------- */
    for (int i = 0; papszXmlProps != NULL && papszXmlProps[i] != NULL; i++)
    {
        char **papszTokens;
        papszTokens = CSLTokenizeString2( papszXmlProps[i],
                                          "=",
                                          CSLT_STRIPLEADSPACES
                                            | CSLT_STRIPENDSPACES);
        if ( strcmp( papszTokens[0], "WIDTH" ) == 0
              || strcmp( papszTokens[0], "LENGTH" ) == 0
              || strcmp( papszTokens[0], "NUMBER_BANDS" ) == 0
              || strcmp( papszTokens[0], "DATA_TYPE" ) == 0
              || strcmp( papszTokens[0], "SCHEME" ) == 0 )
        {
            CSLDestroy( papszTokens );
            continue;
        }
        poDS->SetMetadataItem(papszTokens[0], papszTokens[1], "ISCE");
        CSLDestroy( papszTokens );
    }

/* -------------------------------------------------------------------- */
/*      Free papszXmlProps                                              */
/* -------------------------------------------------------------------- */
    CSLDestroy( papszXmlProps );

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );
    poDS->TryLoadXML();

/* -------------------------------------------------------------------- */
/*      Check for overviews.                                            */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

    return( poDS );
}
Example #12
0
/** Apply a vertical shift grid to a source (DEM typically) dataset.
 * 
 * hGridDataset will typically use WGS84 as horizontal datum (but this is
 * not a requirement) and its values are the values to add to go from geoid
 * elevations to WGS84 ellipsoidal heights.
 * 
 * hGridDataset will be on-the-fly reprojected and resampled to the projection
 * and resolution of hSrcDataset, using bilinear resampling by default.
 * 
 * Both hSrcDataset and hGridDataset must be single band datasets, and have
 * a valid geotransform and projection.
 *
 * On success, a reference will be taken on hSrcDataset and hGridDataset.
 * Reference counting semantics on the source and grid datasets should be
 * honoured. That is, don't just GDALClose() it, unless it was opened with
 * GDALOpenShared(), but rather use GDALReleaseDataset() if wanting to
 * immediately release the reference(s) and make the returned dataset the
 * owner of them.
 *
 * Valid use cases:
 * 
 * \code
 * hSrcDataset = GDALOpen(...)
 * hGridDataset = GDALOpen(...)
 * hDstDataset = GDALApplyVerticalShiftGrid(hSrcDataset, hGridDataset, ...)
 * GDALReleaseDataset(hSrcDataset);
 * GDALReleaseDataset(hGridDataset);
 * if( hDstDataset )
 * {
 *     // Do things with hDstDataset 
 *     GDALClose(hDstDataset) // will close hSrcDataset and hGridDataset
 * }
 * \endcode

 *
 * @param hSrcDataset source (DEM) dataset. Must not be NULL.
 * @param hGridDataset vertical grid shift dataset. Must not be NULL.
 * @param bInverse if set to FALSE, hGridDataset values will be added to
 *                 hSrcDataset. If set to TRUE, they will be subtracted.
 * @param dfSrcUnitToMeter the factor to convert values from hSrcDataset to
 *                         meters (1.0 if source values are in meter).
 * @param dfDstUnitToMeter the factor to convert shifted values from meter
 *                          (1.0 if output values must be in meter).
 * @param papszOptions list of options, or NULL. Supported options are:
 * <ul>
 * <li>RESAMPLING=NEAREST/BILINEAR/CUBIC. Defaults to BILINEAR.</li>
 * <li>MAX_ERROR=val. Maximum error measured in input pixels that is allowed in
 * approximating the transformation (0.0 for exact calculations). Defaults
 * to 0.125</li>
 * <li>DATATYPE=Byte/UInt16/Int16/Float32/Float64. Output data type. If not
 * specified will be the same as the one of hSrcDataset.
 * <li>ERROR_ON_MISSING_VERT_SHIFT=YES/NO. Whether a missing/nodata value in
 * hGridDataset should cause I/O requests to fail. Default is NO (in which case
 * 0 will be used)
 * <li>SRC_SRS=srs_def. Override projection on hSrcDataset;
 * </ul>
 *
 * @return a new dataset corresponding to hSrcDataset adjusted with
 * hGridDataset, or NULL. If not NULL, it must be closed with GDALClose().
 *
 * @since GDAL 2.2
 */
GDALDatasetH GDALApplyVerticalShiftGrid( GDALDatasetH hSrcDataset,
                                         GDALDatasetH hGridDataset,
                                         int bInverse,
                                         double dfSrcUnitToMeter,
                                         double dfDstUnitToMeter,
                                         const char* const* papszOptions )
{
    VALIDATE_POINTER1( hSrcDataset, "GDALApplyVerticalShiftGrid", nullptr );
    VALIDATE_POINTER1( hGridDataset, "GDALApplyVerticalShiftGrid", nullptr );

    double adfSrcGT[6];
    if( GDALGetGeoTransform(hSrcDataset, adfSrcGT) != CE_None )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Source dataset has no geotransform.");
        return nullptr;
    }
    const char* pszSrcProjection = CSLFetchNameValueDef(papszOptions,
                                            "SRC_SRS",
                                            GDALGetProjectionRef(hSrcDataset));
    if( pszSrcProjection == nullptr || pszSrcProjection[0] == '\0' )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Source dataset has no projection.");
        return nullptr;
    }
    if(  GDALGetRasterCount(hSrcDataset) != 1 )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Only single band source dataset is supported.");
        return nullptr;
    }

    double adfGridGT[6];
    if( GDALGetGeoTransform(hGridDataset, adfGridGT) != CE_None )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Grid dataset has no geotransform.");
        return nullptr;
    }
    const char* pszGridProjection = GDALGetProjectionRef(hGridDataset);
    if( pszGridProjection == nullptr || pszGridProjection[0] == '\0' )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Grid dataset has no projection.");
        return nullptr;
    }
    if(  GDALGetRasterCount(hGridDataset) != 1 )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Only single band grid dataset is supported.");
        return nullptr;
    }

    GDALDataType eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDataset,1));
    const char* pszDataType = CSLFetchNameValue(papszOptions, "DATATYPE");
    if( pszDataType )
        eDT = GDALGetDataTypeByName(pszDataType);
    if( eDT == GDT_Unknown )
    {
        CPLError(CE_Failure, CPLE_NotSupported,
                 "Invalid DATATYPE=%s", pszDataType);
        return nullptr;
    }

    const int nSrcXSize = GDALGetRasterXSize(hSrcDataset);
    const int nSrcYSize = GDALGetRasterYSize(hSrcDataset);

    OGRSpatialReference oSRS;
    CPLString osSrcProjection(pszSrcProjection);
    oSRS.SetFromUserInput(osSrcProjection);
    if( oSRS.IsCompound() )
    {
        OGR_SRSNode* poNode = oSRS.GetRoot()->GetChild(1);
        if( poNode != nullptr )
        {
            char* pszWKT = nullptr;
            poNode->exportToWkt(&pszWKT);
            osSrcProjection = pszWKT;
            CPLFree(pszWKT);
        }
    }

    void* hTransform = GDALCreateGenImgProjTransformer3( pszGridProjection,
                                                         adfGridGT,
                                                         osSrcProjection,
                                                         adfSrcGT );
    if( hTransform == nullptr )
        return nullptr;
    GDALWarpOptions* psWO = GDALCreateWarpOptions();
    psWO->hSrcDS = hGridDataset;
    psWO->eResampleAlg = GRA_Bilinear;
    const char* pszResampling = CSLFetchNameValue(papszOptions, "RESAMPLING");
    if( pszResampling )
    {
        if( EQUAL(pszResampling, "NEAREST") )
            psWO->eResampleAlg = GRA_NearestNeighbour;
        else if( EQUAL(pszResampling, "BILINEAR") )
            psWO->eResampleAlg = GRA_Bilinear;
        else if( EQUAL(pszResampling, "CUBIC") )
            psWO->eResampleAlg = GRA_Cubic;
    }
    psWO->eWorkingDataType = GDT_Float32;
    int bHasNoData = FALSE;
    const double dfSrcNoData = GDALGetRasterNoDataValue(
        GDALGetRasterBand(hGridDataset, 1), &bHasNoData );
    if( bHasNoData )
    {
        psWO->padfSrcNoDataReal =
                static_cast<double*>(CPLMalloc(sizeof(double)));
        psWO->padfSrcNoDataReal[0] = dfSrcNoData;
    }

    psWO->padfDstNoDataReal = static_cast<double*>(CPLMalloc(sizeof(double)));
    const bool bErrorOnMissingShift = CPLFetchBool( papszOptions,
                                              "ERROR_ON_MISSING_VERT_SHIFT",
                                              false );
    psWO->padfDstNoDataReal[0] = 
        (bErrorOnMissingShift) ? -std::numeric_limits<float>::infinity() : 0.0;
    psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
                                                 "INIT_DEST",
                                                 "NO_DATA");

    psWO->pfnTransformer = GDALGenImgProjTransform;
    psWO->pTransformerArg = hTransform;
    const double dfMaxError = CPLAtof(CSLFetchNameValueDef(papszOptions,
                                                           "MAX_ERROR",
                                                           "0.125"));
    if( dfMaxError > 0.0 )
    {
        psWO->pTransformerArg =
            GDALCreateApproxTransformer( psWO->pfnTransformer,
                                         psWO->pTransformerArg,
                                         dfMaxError );
        psWO->pfnTransformer = GDALApproxTransform;
        GDALApproxTransformerOwnsSubtransformer(psWO->pTransformerArg, TRUE);
    }
    psWO->nBandCount = 1;
    psWO->panSrcBands = static_cast<int *>(CPLMalloc(sizeof(int)));
    psWO->panSrcBands[0] = 1;
    psWO->panDstBands = static_cast<int *>(CPLMalloc(sizeof(int)));
    psWO->panDstBands[0] = 1;

    VRTWarpedDataset* poReprojectedGrid =
                new VRTWarpedDataset(nSrcXSize, nSrcYSize);
    // This takes a reference on hGridDataset
    CPLErr eErr = poReprojectedGrid->Initialize(psWO);
    CPLAssert(eErr == CE_None);
    CPL_IGNORE_RET_VAL(eErr);
    GDALDestroyWarpOptions(psWO);
    poReprojectedGrid->SetGeoTransform(adfSrcGT);
    poReprojectedGrid->AddBand(GDT_Float32, nullptr);

    GDALApplyVSGDataset* poOutDS = new GDALApplyVSGDataset(
        reinterpret_cast<GDALDataset*>(hSrcDataset),
        poReprojectedGrid,
        eDT,
        CPL_TO_BOOL(bInverse),
        dfSrcUnitToMeter,
        dfDstUnitToMeter,
        // Undocumented option. For testing only
        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKSIZE", "256")) );

    poReprojectedGrid->ReleaseRef();

    if( !poOutDS->IsInitOK() )
    {
        delete poOutDS;
        return nullptr;
    }
    poOutDS->SetDescription( GDALGetDescription( hSrcDataset ) );
    return reinterpret_cast<GDALDatasetH>(poOutDS);
}