Changeset 11890

Show
Ignore:
Timestamp:
08/17/07 12:20:04 (11 months ago)
Author:
warmerdam
Message:

back port WCS 1.1 support

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • sandbox/warmerdam/1.4-esri/gdal/frmts/wcs/cpl_http.cpp

    r10646 r11890  
    198198} 
    199199 
     200/************************************************************************/ 
     201/*                     CPLHTTPParseMultipartMime()                      */ 
     202/************************************************************************/ 
     203 
     204int CPLHTTPParseMultipartMime( CPLHTTPResult *psResult ) 
     205 
     206{ 
     207/* -------------------------------------------------------------------- */ 
     208/*      Is it already done?                                             */ 
     209/* -------------------------------------------------------------------- */ 
     210    if( psResult->nMimePartCount > 0 ) 
     211        return TRUE; 
     212 
     213/* -------------------------------------------------------------------- */ 
     214/*      Find the boundary setting in the content type.                  */ 
     215/* -------------------------------------------------------------------- */ 
     216    const char *pszBound = NULL; 
     217 
     218    if( psResult->pszContentType != NULL ) 
     219        pszBound = strstr(psResult->pszContentType,"boundary="); 
     220 
     221    if( pszBound == NULL ) 
     222    { 
     223        CPLError( CE_Failure, CPLE_AppDefined, 
     224                  "Unable to parse multi-part mime, no boundary setting." ); 
     225        return FALSE; 
     226    } 
     227 
     228    CPLString osBoundary; 
     229    char **papszTokens =  
     230        CSLTokenizeStringComplex( pszBound + 9, "\n ;",  
     231                                  TRUE, FALSE ); 
     232 
     233    if( CSLCount(papszTokens) == 0 || strlen(papszTokens[0]) == 0 ) 
     234    { 
     235        CPLError( CE_Failure, CPLE_AppDefined, 
     236                  "Unable to parse multi-part mime, boundary not parsable." ); 
     237        return FALSE; 
     238    } 
     239     
     240    osBoundary = "--"; 
     241    osBoundary += papszTokens[0]; 
     242    CSLDestroy( papszTokens ); 
     243 
     244/* -------------------------------------------------------------------- */ 
     245/*      Find the start of the first chunk.                              */ 
     246/* -------------------------------------------------------------------- */ 
     247    char *pszNext; 
     248    pszNext = strstr((const char *) psResult->pabyData,osBoundary.c_str()); 
     249     
     250    if( pszNext == NULL ) 
     251    { 
     252        CPLError( CE_Failure, CPLE_AppDefined, "No parts found." ); 
     253        return FALSE; 
     254    } 
     255 
     256    pszNext += strlen(osBoundary); 
     257    while( *pszNext != '\n' && *pszNext != '\0' ) 
     258        pszNext++; 
     259    if( *pszNext == '\n' ) 
     260        pszNext++; 
     261 
     262/* -------------------------------------------------------------------- */ 
     263/*      Loop over parts...                                              */ 
     264/* -------------------------------------------------------------------- */ 
     265    while( TRUE ) 
     266    { 
     267        psResult->nMimePartCount++; 
     268        psResult->pasMimePart = (CPLMimePart *) 
     269            CPLRealloc(psResult->pasMimePart, 
     270                       sizeof(CPLMimePart) * psResult->nMimePartCount ); 
     271 
     272        CPLMimePart *psPart = psResult->pasMimePart+psResult->nMimePartCount-1; 
     273 
     274        memset( psPart, 0, sizeof(CPLMimePart) ); 
     275 
     276/* -------------------------------------------------------------------- */ 
     277/*      Collect headers.                                                */ 
     278/* -------------------------------------------------------------------- */ 
     279        while( *pszNext != '\n' && *pszNext != '\0' ) 
     280        { 
     281            char *pszEOL = strstr(pszNext,"\n"); 
     282 
     283            if( pszEOL == NULL ) 
     284            { 
     285                CPLAssert( FALSE ); 
     286                break; 
     287            } 
     288 
     289            *pszEOL = '\0'; 
     290            psPart->papszHeaders =  
     291                CSLAddString( psPart->papszHeaders, pszNext ); 
     292            *pszEOL = '\n'; 
     293             
     294            pszNext = pszEOL + 1; 
     295        } 
     296 
     297        if( *pszNext == '\n' ) 
     298            pszNext++; 
     299             
     300/* -------------------------------------------------------------------- */ 
     301/*      Work out the data block size.                                   */ 
     302/* -------------------------------------------------------------------- */ 
     303        psPart->pabyData = (GByte *) pszNext; 
     304 
     305        int nBytesAvail = psResult->nDataLen -  
     306            (pszNext - (const char *) psResult->pabyData); 
     307 
     308        while( nBytesAvail > 0 
     309               && (*pszNext != '-'  
     310                   || strncmp(pszNext,osBoundary,strlen(osBoundary)) != 0) ) 
     311        { 
     312            pszNext++; 
     313            nBytesAvail--; 
     314        } 
     315         
     316        if( nBytesAvail == 0 ) 
     317        { 
     318            CPLAssert( FALSE ); 
     319            break; 
     320        } 
     321 
     322        psPart->nDataLen = pszNext - (const char *) psPart->pabyData; 
     323        pszNext += strlen(osBoundary); 
     324 
     325        if( strncmp(pszNext,"--",2) == 0 ) 
     326        { 
     327            break; 
     328        } 
     329        else if( *pszNext == '\n' ) 
     330            pszNext++; 
     331        else 
     332        { 
     333            CPLAssert( FALSE ); 
     334            break; 
     335        } 
     336    } 
     337 
     338    return TRUE; 
     339} 
  • sandbox/warmerdam/1.4-esri/gdal/frmts/wcs/cpl_http.h

    r10646 r11890  
    3838 
    3939typedef struct { 
     40    char **papszHeaders; 
     41     
     42    GByte *pabyData; 
     43    int    nDataLen; 
     44} CPLMimePart; 
     45 
     46typedef struct { 
    4047    int     nStatus;            /* 200=success, value < 0 if request failed */ 
    4148    char    *pszContentType;    /* Content-Type of the response */ 
     
    4552    int     nDataAlloc; 
    4653    GByte   *pabyData; 
     54 
     55    int     nMimePartCount; 
     56    CPLMimePart *pasMimePart; 
    4757} CPLHTTPResult; 
    4858 
     
    5161void CPL_DLL  CPLHTTPCleanup( void ); 
    5262void CPL_DLL  CPLHTTPDestroyResult( CPLHTTPResult *psResult ); 
     63int  CPL_DLL  CPLHTTPParseMultipartMime( CPLHTTPResult *psResult ); 
    5364 
    5465CPL_C_END 
  • sandbox/warmerdam/1.4-esri/gdal/frmts/wcs/wcsdataset.cpp

    r11642 r11890  
    3636CPL_CVSID("$Id$"); 
    3737 
    38  
    3938/************************************************************************/ 
    4039/* ==================================================================== */ 
     
    5150    int         bServiceDirty; 
    5251    CPLXMLNode *psService; 
     52 
     53    int         nVersion;  // eg 100 for 1.0.0, 110 for 1.1.0 
    5354 
    5455    CPLString   osCRS; 
     
    6364                                void *, int, int, GDALDataType, 
    6465                                int, int *, int, int, int ); 
     66    CPLErr      GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize, 
     67                             int nBufXSize, int nBufYSize,  
     68                             int nBandCount, int *panBandList, 
     69                             CPLHTTPResult **ppsResult ); 
    6570 
    6671    virtual CPLErr IRasterIO( GDALRWFlag, int, int, int, int, 
     
    6974 
    7075    int         DescribeCoverage(); 
     76    int         ExtractGridInfo100(); 
    7177    int         ExtractGridInfo(); 
    7278    int         EstablishRasterDetails(); 
     
    7682    void        FlushMemoryResult(); 
    7783    CPLString   osResultFilename; 
     84    GByte      *pabySavedDataBuffer; 
    7885     
    7986  public: 
     
    99106    int            iOverview; 
    100107    int            nResFactor; 
    101     double         adfGeoTransform[6]; 
    102108 
    103109    WCSDataset    *poODS; 
     
    166172            nBlockYSize = nRasterYSize; 
    167173    } 
    168  
    169 /* -------------------------------------------------------------------- */ 
    170 /*      Establish possibly reduced resolution geotransform.             */ 
    171 /* -------------------------------------------------------------------- */ 
    172     adfGeoTransform[0] = poODS->adfGeoTransform[0]; 
    173     adfGeoTransform[1] = poODS->adfGeoTransform[1] * nResFactor; 
    174     adfGeoTransform[2] = poODS->adfGeoTransform[2] * nResFactor; 
    175     adfGeoTransform[3] = poODS->adfGeoTransform[3]; 
    176     adfGeoTransform[4] = poODS->adfGeoTransform[4] * nResFactor; 
    177     adfGeoTransform[5] = poODS->adfGeoTransform[5] * nResFactor; 
    178174 
    179175/* -------------------------------------------------------------------- */ 
     
    234230 
    235231{ 
    236 /* -------------------------------------------------------------------- */ 
    237 /*      Figure out the georeferenced extents.                           */ 
    238 /* -------------------------------------------------------------------- */ 
    239     double dfMinX, dfMaxX, dfMinY, dfMaxY; 
    240      
    241     dfMinX = adfGeoTransform[0] +  
    242         (nBlockXOff * nBlockXSize + 0.5) * adfGeoTransform[1]; 
    243     dfMaxX = adfGeoTransform[0] +  
    244         ((nBlockXOff+1) * nBlockXSize + 0.5) * adfGeoTransform[1]; 
    245     dfMaxY = adfGeoTransform[3] +  
    246         (nBlockYOff * nBlockYSize + 0.5) * adfGeoTransform[5]; 
    247     dfMinY = adfGeoTransform[3] +  
    248         ((nBlockYOff+1) * nBlockYSize + 0.5) * adfGeoTransform[5]; 
    249      
    250  
    251 /* -------------------------------------------------------------------- */ 
    252 /*      Construct a simple GetCoverage request.                         */ 
    253 /* -------------------------------------------------------------------- */ 
    254     CPLString osRequest; 
    255  
    256     osRequest.Printf(  
    257         "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s" 
    258         "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s", 
    259         CPLGetXMLValue( poODS->psService, "ServiceURL", "" ), 
    260         CPLGetXMLValue( poODS->psService, "CoverageName", "" ), 
    261         CPLGetXMLValue( poODS->psService, "PreferredFormat", "" ), 
    262         dfMinX, dfMinY, dfMaxX, dfMaxY, 
    263         nBlockXSize, nBlockYSize, 
    264         poODS->osCRS.c_str(), 
    265         CPLGetXMLValue( poODS->psService, "GetCoverageExtra", "" ) ); 
    266  
    267 /* -------------------------------------------------------------------- */ 
    268 /*      Append band selector if we have one.                            */ 
    269 /* -------------------------------------------------------------------- */ 
    270     CPLString osBandIdentifier = poODS->osBandIdentifier; 
    271  
    272     if( strlen(osBandIdentifier) ) 
    273     { 
    274         CPLString osBS; 
    275  
    276         osBS.Printf( "&%s=%d", osBandIdentifier.c_str(), GetBand() ); 
    277         osRequest += osBS; 
    278     } 
    279  
    280 /* -------------------------------------------------------------------- */ 
    281 /*      Fetch the result.                                               */ 
    282 /* -------------------------------------------------------------------- */ 
    283     CPLString osTimeout = "TIMEOUT="; 
    284     osTimeout += CPLGetXMLValue( poODS->psService, "Timeout", "30" ); 
    285     char *apszOptions[] = {  
    286         (char *) osTimeout.c_str(), 
    287         NULL  
    288     }; 
    289  
    290     CPLErrorReset(); 
    291      
    292     CPLHTTPResult *psResult = CPLHTTPFetch( osRequest, apszOptions ); 
    293  
    294     if( poODS->ProcessError( psResult ) ) 
    295         return CE_Failure; 
     232    CPLErr eErr; 
     233    CPLHTTPResult *psResult = NULL; 
     234 
     235    eErr = poODS->GetCoverage( nBlockXOff * nBlockXSize * nResFactor,  
     236                               nBlockYOff * nBlockYSize * nResFactor, 
     237                               nBlockXSize * nResFactor,  
     238                               nBlockYSize * nResFactor,  
     239                               nBlockXSize, nBlockYSize,  
     240                               1, &nBand, &psResult ); 
     241    if( eErr != CE_None ) 
     242        return eErr; 
    296243 
    297244/* -------------------------------------------------------------------- */ 
     
    309256        || poTileDS->GetRasterYSize() != nBlockYSize ) 
    310257    { 
     258        CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.",  
     259                  poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(), 
     260                  nBlockXSize, nBlockYSize ); 
     261 
    311262        CPLError( CE_Failure, CPLE_AppDefined,  
    312263                  "Returned tile does not match expected configuration." ); 
     
    314265    } 
    315266 
    316     if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != 1) 
    317         || (!strlen(osBandIdentifier)  
     267    if( (strlen(poODS->osBandIdentifier) && poTileDS->GetRasterCount() != 1) 
     268        || (!strlen(poODS->osBandIdentifier)  
    318269            && poTileDS->GetRasterCount() != poODS->GetRasterCount()) ) 
    319270    { 
     
    328279/* -------------------------------------------------------------------- */ 
    329280    int iBand; 
    330     CPLErr eErr = CE_None; 
     281    eErr = CE_None; 
    331282     
    332283    for( iBand = 0;  
     
    336287        GDALRasterBand *poTileBand = poTileDS->GetRasterBand( iBand+1 ); 
    337288 
    338         if( iBand+1 == GetBand() || strlen(osBandIdentifier) ) 
     289        if( iBand+1 == GetBand() || strlen(poODS->osBandIdentifier) ) 
    339290        { 
    340291            eErr = poTileBand->RasterIO( GF_Read,  
     
    391342    else 
    392343        return poODS->DirectRasterIO(  
    393             eRWFlag, nXOff, nYOff, nXSize, nYSize, 
     344            eRWFlag,  
     345            nXOff * nResFactor, nYOff * nResFactor,  
     346            nXSize * nResFactor, nYSize * nResFactor, 
    394347            pData, nBufXSize, nBufYSize, eBufType,  
    395348            1, &nBand, nPixelSpace, nLineSpace, 0 ); 
     
    462415    adfGeoTransform[4] = 0.0; 
    463416    adfGeoTransform[5] = 1.0; 
     417 
     418    pabySavedDataBuffer = NULL; 
    464419} 
    465420 
     
    559514 
    560515/* -------------------------------------------------------------------- */ 
     516/*      Get the coverage.                                               */ 
     517/* -------------------------------------------------------------------- */ 
     518    CPLHTTPResult *psResult = NULL; 
     519    CPLErr eErr =  
     520        GetCoverage( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,  
     521                     nBandCount, panBandMap, &psResult ); 
     522 
     523    if( eErr != CE_None ) 
     524        return eErr; 
     525 
     526/* -------------------------------------------------------------------- */ 
     527/*      Try and open result as a dataseat.                               */ 
     528/* -------------------------------------------------------------------- */ 
     529    GDALDataset *poTileDS = GDALOpenResult( psResult ); 
     530 
     531    if( poTileDS == NULL ) 
     532        return CE_Failure; 
     533 
     534/* -------------------------------------------------------------------- */ 
     535/*      Verify configuration.                                           */ 
     536/* -------------------------------------------------------------------- */ 
     537    if( poTileDS->GetRasterXSize() != nBufXSize 
     538        || poTileDS->GetRasterYSize() != nBufYSize ) 
     539    { 
     540        CPLDebug( "WCS", "Got size=%dx%d instead of %dx%d.",  
     541                  poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(), 
     542                  nBufXSize, nBufYSize ); 
     543 
     544        CPLError( CE_Failure, CPLE_AppDefined,  
     545                  "Returned tile does not match expected configuration." ); 
     546        return CE_Failure; 
     547    } 
     548 
     549    if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != nBandCount) 
     550        || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() !=  
     551            GetRasterCount() ) ) 
     552    { 
     553        CPLError( CE_Failure, CPLE_AppDefined,  
     554                  "Returned tile does not match expected band count." ); 
     555        return CE_Failure; 
     556    } 
     557     
     558/* -------------------------------------------------------------------- */ 
     559/*      Pull requested bands from the downloaded dataset.               */ 
     560/* -------------------------------------------------------------------- */ 
     561    int iBand; 
     562 
     563    eErr = CE_None; 
     564     
     565    for( iBand = 0;  
     566         iBand < nBandCount && eErr == CE_None;  
     567         iBand++ ) 
     568    { 
     569        GDALRasterBand *poTileBand; 
     570 
     571        if( strlen(osBandIdentifier) ) 
     572            poTileBand = poTileDS->GetRasterBand( iBand + 1 ); 
     573        else 
     574            poTileBand = poTileDS->GetRasterBand( panBandMap[iBand] ); 
     575 
     576        eErr = poTileBand->RasterIO( GF_Read,  
     577                                     0, 0, nBufXSize, nBufYSize, 
     578                                     ((GByte *) pData) +  
     579                                     iBand * nBandSpace, nBufXSize, nBufYSize,  
     580                                     eBufType, nPixelSpace, nLineSpace ); 
     581    } 
     582     
     583/* -------------------------------------------------------------------- */ 
     584/*      Cleanup                                                         */ 
     585/* -------------------------------------------------------------------- */ 
     586    delete poTileDS; 
     587     
     588    FlushMemoryResult(); 
     589 
     590    return eErr; 
     591} 
     592 
     593/************************************************************************/ 
     594/*                            GetCoverage()                             */ 
     595/*                                                                      */ 
     596/*      Issue the appropriate version of request for a given window,    */ 
     597/*      buffer size and band list.                                      */ 
     598/************************************************************************/ 
     599 
     600CPLErr WCSDataset::GetCoverage( int nXOff, int nYOff, int nXSize, int nYSize, 
     601                                int nBufXSize, int nBufYSize,  
     602                                int nBandCount, int *panBandList, 
     603                                CPLHTTPResult **ppsResult ) 
     604 
     605{ 
     606/* -------------------------------------------------------------------- */ 
    561607/*      Figure out the georeferenced extents.                           */ 
    562608/* -------------------------------------------------------------------- */ 
     
    566612        (nXOff + 0.5) * adfGeoTransform[1]; 
    567613    dfMaxX = adfGeoTransform[0] +  
    568         (nXOff+nXSize + 0.5) * adfGeoTransform[1]; 
     614        (nXOff + nXSize + 0.5) * adfGeoTransform[1]; 
    569615    dfMaxY = adfGeoTransform[3] +  
    570616        (nYOff + 0.5) * adfGeoTransform[5]; 
     
    573619 
    574620/* -------------------------------------------------------------------- */ 
    575 /*      Construct a simple GetCoverage request.                         */ 
     621/*      Build band list if we have the band identifier.                 */ 
     622/* -------------------------------------------------------------------- */ 
     623    CPLString osBandList; 
     624    int       bSelectingBands = FALSE; 
     625     
     626    if( strlen(osBandIdentifier) && nBandCount > 0 ) 
     627    { 
     628        int iBand; 
     629 
     630        for( iBand = 0; iBand < nBandCount; iBand++ ) 
     631        { 
     632            if( iBand > 0 ) 
     633                osBandList += ","; 
     634            osBandList += CPLString().Printf( "%d", panBandList[iBand] ); 
     635        } 
     636 
     637        bSelectingBands = TRUE; 
     638    } 
     639     
     640/* -------------------------------------------------------------------- */ 
     641/*      Construct a "simple" GetCoverage request (WCS 1.0).             */ 
    576642/* -------------------------------------------------------------------- */ 
    577643    CPLString osRequest; 
    578644 
    579     osRequest.Printf(  
    580         "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s" 
    581         "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s", 
    582         CPLGetXMLValue( psService, "ServiceURL", "" ), 
    583         CPLGetXMLValue( psService, "CoverageName", "" ), 
    584         CPLGetXMLValue( psService, "PreferredFormat", "" ), 
    585         dfMinX, dfMinY, dfMaxX, dfMaxY, 
    586         nBufXSize, nBufYSize, 
    587         osCRS.c_str(), 
    588         CPLGetXMLValue( psService, "GetCoverageExtra", "" ) ); 
    589  
    590     if( CPLGetXMLValue( psService, "Resample", NULL ) ) 
    591     { 
    592         osRequest += "&RESAMPLE="; 
    593         osRequest += CPLGetXMLValue( psService, "Resample", "" ); 
    594     } 
    595  
    596 /* -------------------------------------------------------------------- */ 
    597 /*      Select our band list if we have a band identifier.              */ 
    598 /* -------------------------------------------------------------------- */ 
    599     int iBand; 
    600  
    601     if( strlen(osBandIdentifier) ) 
    602     { 
    603         osRequest += "&"; 
    604         osRequest += osBandIdentifier; 
    605  
    606         for( iBand = 0; iBand < nBandCount; iBand++ ) 
    607         { 
    608             char szItem[32]; 
     645    if( nVersion == 100 ) 
     646    { 
     647        osRequest.Printf(  
     648            "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=%s" 
     649            "&FORMAT=%s&BBOX=%.15g,%.15g,%.15g,%.15g&WIDTH=%d&HEIGHT=%d&CRS=%s%s", 
     650            CPLGetXMLValue( psService, "ServiceURL", "" ), 
     651            CPLGetXMLValue( psService, "CoverageName", "" ), 
     652            CPLGetXMLValue( psService, "PreferredFormat", "" ), 
     653            dfMinX, dfMinY, dfMaxX, dfMaxY, 
     654            nBufXSize, nBufYSize,  
     655            osCRS.c_str(), 
     656            CPLGetXMLValue( psService, "GetCoverageExtra", "" ) ); 
     657  
     658        if( bSelectingBands ) 
     659        { 
     660            osRequest += CPLString().Printf( "&%s=%s",  
     661                                             osBandIdentifier.c_str(), 
     662                                             osBandList.c_str() ); 
     663        } 
     664    } 
     665 
     666/* -------------------------------------------------------------------- */ 
     667/*      Construct a "simple" GetCoverage request (WCS 1.1+).            */ 
     668/* -------------------------------------------------------------------- */ 
     669    else 
     670    { 
     671        CPLString osRangeSubset; 
     672 
     673        osRangeSubset.Printf("&RangeSubset=%s",  
     674                             CPLGetXMLValue(psService,"FieldName","")); 
     675         
     676        if( CPLGetXMLValue( psService, "Resample", NULL ) ) 
     677        { 
     678            osRangeSubset += ":"; 
     679            osRangeSubset += CPLGetXMLValue( psService, "Resample", ""); 
     680        } 
     681 
     682        if( bSelectingBands ) 
     683        { 
     684            osRangeSubset +=  
     685                CPLString().Printf( "[%s[%s]]", 
     686                                    osBandIdentifier.c_str(),  
     687                                    osBandList.c_str() ); 
     688        } 
     689 
     690        dfMaxX -= adfGeoTransform[1]; 
     691        dfMinY -= adfGeoTransform[5]; 
     692 
     693        // Carefully adjust bounds for pixel centered values at new  
     694        // sampling density. 
     695 
     696        double dfXStep = adfGeoTransform[1]; 
     697        double dfYStep = adfGeoTransform[5]; 
     698 
     699        if( nBufXSize != nXSize || nBufYSize != nYSize ) 
     700        { 
     701            dfXStep = (nXSize/(double)nBufXSize) * adfGeoTransform[1]; 
     702            dfYStep = (nYSize/(double)nBufYSize) * adfGeoTransform[5]; 
    609703             
    610             if( iBand == 0 ) 
    611                 osRequest += "="; 
    612             else 
    613                 osRequest += ","; 
    614  
    615             sprintf( szItem, "%d", panBandMap[iBand] ); 
    616             osRequest += szItem; 
     704            dfMinX = adfGeoTransform[0] + dfXStep * 0.5; 
     705            dfMaxX = dfMinX + dfXStep * (nBufXSize-1); 
     706            dfMaxY = adfGeoTransform[3] + dfYStep * 0.5; 
     707            dfMinY = dfMaxY + dfYStep * (nBufYSize-1); 
     708        } 
     709 
     710        osRequest.Printf(  
     711            "%sSERVICE=WCS&VERSION=%s&REQUEST=GetCoverage&IDENTIFIER=%s" 
     712            "&FORMAT=%s&BOUNDINGBOX=%.15g,%.15g,%.15g,%.15g,%s%s%s", 
     713            CPLGetXMLValue( psService, "ServiceURL", "" ), 
     714            CPLGetXMLValue( psService, "Version", "" ), 
     715            CPLGetXMLValue( psService, "CoverageName", "" ), 
     716            CPLGetXMLValue( psService, "PreferredFormat", "" ), 
     717            dfMinX, dfMinY, dfMaxX, dfMaxY, 
     718            osCRS.c_str(), 
     719            osRangeSubset.c_str(), 
     720            CPLGetXMLValue( psService, "GetCoverageExtra", "" ) ); 
     721 
     722        if( nBufXSize != nXSize || nBufYSize != nYSize ) 
     723        { 
     724            osRequest += CPLString().Printf(  
     725                "&GridBaseCRS=%s" 
     726                "&GridCS=%s" 
     727                "&GridType=urn:ogc:def:method:WCS:1.1:2dGridIn2dCrs" 
     728                "&GridOrigin=%.15g,%.15g" 
     729                "&GridOffsets=%.15g,%.15g", 
     730                osCRS.c_str(),  
     731                osCRS.c_str(),  
     732                dfMinX, dfMaxY, 
     733                dfXStep, dfYStep ); 
    617734        } 
    618735    } 
     
    629746 
    630747    CPLErrorReset(); 
    631      
    632     CPLHTTPResult *psResult = CPLHTTPFetch( osRequest, apszOptions ); 
    633  
    634     if( ProcessError( psResult ) ) 
     748 
     749    *ppsResult = CPLHTTPFetch( osRequest, apszOptions ); 
     750 
     751    if( ProcessError( *ppsResult ) ) 
    635752        return CE_Failure; 
    636  
    637 /* -------------------------------------------------------------------- */ 
    638 /*      Try and open result as a dataseat.                               */ 
    639 /* -------------------------------------------------------------------- */ 
    640     GDALDataset *poTileDS = GDALOpenResult( psResult ); 
    641  
    642     if( poTileDS == NULL ) 
    643         return CE_Failure; 
    644  
    645 /* -------------------------------------------------------------------- */ 
    646 /*      Verify configuration.                                           */ 
    647 /* -------------------------------------------------------------------- */ 
    648     if( poTileDS->GetRasterXSize() != nBufXSize 
    649         || poTileDS->GetRasterYSize() != nBufYSize ) 
    650     { 
    651         CPLError( CE_Failure, CPLE_AppDefined,  
    652                   "Returned tile does not match expected configuration." ); 
    653         return CE_Failure; 
    654     } 
    655  
    656     if( (strlen(osBandIdentifier) && poTileDS->GetRasterCount() != nBandCount) 
    657         || (!strlen(osBandIdentifier) && poTileDS->GetRasterCount() !=  
    658             GetRasterCount() ) ) 
    659     { 
    660         CPLError( CE_Failure, CPLE_AppDefined,  
    661                   "Returned tile does not match expected band count." ); 
    662         return CE_Failure; 
    663     } 
    664      
    665 /* -------------------------------------------------------------------- */ 
    666 /*      Pull requested bands from the downloaded dataset.               */ 
    667 /* -------------------------------------------------------------------- */ 
    668     CPLErr eErr = CE_None; 
    669      
    670     for( iBand = 0;  
    671          iBand < nBandCount && eErr == CE_None;  
    672          iBand++ ) 
    673     { 
    674         GDALRasterBand *poTileBand; 
    675  
    676         if( strlen(osBandIdentifier) ) 
    677             poTileBand = poTileDS->GetRasterBand( iBand + 1 ); 
    678         else 
    679             poTileBand = poTileDS->GetRasterBand( panBandMap[iBand] ); 
    680  
    681         eErr = poTileBand->RasterIO( GF_Read,  
    682                                      0, 0, nBufXSize, nBufYSize, 
    683                                      ((GByte *) pData) +  
    684                                      iBand * nBandSpace, nBufXSize, nBufYSize,  
    685                                      eBufType, nPixelSpace, nLineSpace ); 
    686     } 
    687      
    688 /* -------------------------------------------------------------------- */ 
    689 /*      Cleanup                                                         */ 
    690 /* -------------------------------------------------------------------- */ 
    691     delete poTileDS; 
    692      
    693     FlushMemoryResult(); 
    694  
    695     return eErr; 
     753    else 
     754        return CE_None; 
    696755} 
    697756 
     
    711770/*      Fetch coverage description for this coverage.                   */ 
    712771/* -------------------------------------------------------------------- */ 
    713     osRequest.Printf(  
    714         "%sSERVICE=WCS&VERSION=1.0.0&REQUEST=DescribeCoverage&COVERAGE=%s%s",  
    715         CPLGetXMLValue( psService, "ServiceURL", "" ), 
    716         CPLGetXMLValue( psService, "CoverageName", "" ), 
    717         CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) ); 
     772    if( nVersion == 100 ) 
     773        osRequest.Printf(  
     774            "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&COVERAGE=%s%s",  
     775            CPLGetXMLValue( psService, "ServiceURL", "" ), 
     776            CPLGetXMLValue( psService, "Version", "1.0.0" ), 
     777            CPLGetXMLValue( psService, "CoverageName", "" ), 
     778            CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) ); 
     779    else 
     780        osRequest.Printf(  
     781            "%sSERVICE=WCS&REQUEST=DescribeCoverage&VERSION=%s&IDENTIFIERS=%s%s",  
     782            CPLGetXMLValue( psService, "ServiceURL", "" ), 
     783            CPLGetXMLValue( psService, "Version", "1.0.0" ), 
     784            CPLGetXMLValue( psService, "CoverageName", "" ), 
     785            CPLGetXMLValue( psService, "DescribeCoverageExtra", "" ) ); 
    718786 
    719787    CPLErrorReset(); 
     
    736804/*      Did we get a CoverageOffering?                                  */ 
    737805/* -------------------------------------------------------------------- */ 
    738     CPLXMLNode *psCO =  
    739         CPLGetXMLNode( psDC, "=CoverageDescription.CoverageOffering" ); 
     806    CPLXMLNode *psCO; 
     807 
     808    if( nVersion == 100 ) 
     809        psCO = CPLGetXMLNode( psDC, "=CoverageDescription.CoverageOffering" ); 
     810    else 
     811        psCO =CPLGetXMLNode( psDC,"=CoverageDescriptions.CoverageDescription"); 
    740812 
    741813    if( !psCO ) 
     
    765837 
    766838/************************************************************************/ 
    767 /*                          ExtractGridInfo()                           */ 
    768 /************************************************************************/ 
    769  
    770 int WCSDataset::ExtractGridInfo() 
     839/*                         ExtractGridInfo100()                         */ 
     840/*                                                                      */ 
     841/*      Collect info about grid from describe coverage for WCS 1.0.0    */ 
     842/*      and above.                                                      */ 
     843/************************************************************************/ 
     844 
     845int WCSDataset::ExtractGridInfo100() 
    771846 
    772847{ 
     
    9951070 
    9961071/************************************************************************/ 
     1072/*                          ParseBoundingBox()                          */ 
     1073/************************************************************************/ 
     1074 
     1075static int ParseBoundingBox( CPLXMLNode *psBoundingBox, CPLString &osCRS,  
     1076                             double &dfLowerX, double &dfLowerY,  
     1077                             double &dfUpperX, double &dfUpperY ) 
     1078 
     1079{ 
     1080    int nRet = TRUE; 
     1081 
     1082    osCRS = CPLGetXMLValue( psBoundingBox, "crs", "" ); 
     1083 
     1084    char **papszLC = CSLTokenizeStringComplex(  
     1085        CPLGetXMLValue( psBoundingBox, "LowerCorner", ""), 
     1086        " ", FALSE, FALSE ); 
     1087    char **papszUC = CSLTokenizeStringComplex(  
     1088        CPLGetXMLValue( psBoundingBox, "UpperCorner", ""), 
     1089        " ", FALSE, FALSE ); 
     1090 
     1091    if( CSLCount(papszLC) >= 2 && CSLCount(papszUC) >= 2 ) 
     1092    { 
     1093        dfLowerX = atof(papszLC[0]); 
     1094        dfLowerY = atof(papszLC[1]); 
     1095        dfUpperX = atof(papszUC[0]); 
     1096        dfUpperY = atof(papszUC[1]); 
     1097    } 
     1098    else 
     1099        nRet = FALSE; 
     1100     
     1101    CSLDestroy( papszUC ); 
     1102    CSLDestroy( papszLC ); 
     1103 
     1104    return nRet; 
     1105} 
     1106 
     1107/************************************************************************/ 
     1108/*                          ExtractGridInfo()                           */ 
     1109/*                                                                      */ 
     1110/*      Collect info about grid from describe coverage for WCS 1.1      */ 
     1111/*      and above.                                                      */ 
     1112/************************************************************************/ 
     1113 
     1114int WCSDataset::ExtractGridInfo() 
     1115 
     1116{ 
     1117    if( nVersion == 100 ) 
     1118        return ExtractGridInfo100(); 
     1119 
     1120    CPLXMLNode * psCO = CPLGetXMLNode( psService, "CoverageDescription" ); 
     1121 
     1122    if( psCO == NULL ) 
     1123        return FALSE; 
     1124 
     1125/* -------------------------------------------------------------------- */ 
     1126/*      We need to strip off name spaces so it is easier to             */ 
     1127/*      searchfor plain gml names.                                      */ 
     1128/* -------------------------------------------------------------------- */ 
     1129    CPLStripXMLNamespace( psCO, NULL, TRUE ); 
     1130 
     1131/* -------------------------------------------------------------------- */ 
     1132/*      Verify we have a SpatialDomain and GridCRS.                     */ 
     1133/* -------------------------------------------------------------------- */ 
     1134    CPLXMLNode *psSD =  
     1135        CPLGetXMLNode( psCO, "Domain.SpatialDomain" ); 
     1136    CPLXMLNode *psGCRS =  
     1137        CPLGetXMLNode( psSD, "GridCRS" ); 
     1138 
     1139    if( psSD == NULL || psGCRS == NULL ) 
     1140    { 
     1141        CPLError( CE_Failure, CPLE_AppDefined,  
     1142                  "Unable to find GridCRS in CoverageDescription,\n" 
     1143                  "unable to process WCS Coverage." ); 
     1144        return FALSE; 
     1145    } 
     1146 
     1147/* -------------------------------------------------------------------- */ 
     1148/*      Extract Geotransform from GridCRS.                              */ 
     1149/* -------------------------------------------------------------------- */ 
     1150    const char *pszGridType = CPLGetXMLValue( psGCRS, "GridType", 
     1151                                              "urn:ogc:def:method:WCS::2dSimpleGrid" ); 
     1152 
     1153    char **papszOriginTokens =  
     1154        CSLTokenizeStringComplex( CPLGetXMLValue( psGCRS, "GridOrigin", ""), 
     1155                                  " ", FALSE, FALSE ); 
     1156    char **papszOffsetTokens =  
     1157        CSLTokenizeStringComplex( CPLGetXMLValue( psGCRS, "GridOffsets", ""), 
     1158                                  " ", FALSE, FALSE ); 
     1159 
     1160    if( strstr(pszGridType,":2dGridIn2dCrs") ) 
     1161    { 
     1162        if( CSLCount(papszOffsetTokens) == 4 
     1163            && CSLCount(papszOriginTokens) == 2 ) 
     1164        { 
     1165            adfGeoTransform[0] = atof(papszOriginTokens[0]); 
     1166            adfGeoTransform[1] = atof(papszOffsetTokens[0]); 
     1167            adfGeoTransform[2] = atof(papszOffsetTokens[1]); 
     1168            adfGeoTransform[3] = atof(papszOriginTokens[1]); 
     1169            adfGeoTransform[4] = atof(papszOffsetTokens[2]); 
     1170            adfGeoTransform[5] = atof(papszOffsetTokens[3]); 
     1171        } 
     1172        else 
     1173        { 
     1174            CPLError( CE_Failure, CPLE_AppDefined,  
     1175                      "2dGridIn2dCrs does not have expected GridOrigin or\n" 
     1176                      "GridOffsets values - unable to process WCS coverage."); 
     1177            return FALSE; 
     1178        } 
     1179    } 
     1180 
     1181    else if( strstr(pszGridType,":2dGridIn3dCrs") ) 
     1182    { 
     1183        if( CSLCount(papszOffsetTokens) == 6 
     1184            && CSLCount(papszOriginTokens) == 3 ) 
     1185        { 
     1186            adfGeoTransform[0] = atof(papszOriginTokens[0]); 
     1187            adfGeoTransform[1] = atof(papszOffsetTokens[0]); 
     1188            adfGeoTransform[2] = atof(papszOffsetTokens[1]); 
     1189            adfGeoTransform[3] = atof(papszOriginTokens[1]); 
     1190            adfGeoTransform[4] = atof(papszOffsetTokens[3]); 
     1191            adfGeoTransform[5] = atof(papszOffsetTokens[4]); 
     1192        } 
     1193        else 
     1194        { 
     1195            CPLError( CE_Failure, CPLE_AppDefined,  
     1196                      "2dGridIn3dCrs does not have expected GridOrigin or\n" 
     1197                      "GridOffsets values - unable to process WCS coverage."); 
     1198            return FALSE; 
     1199        } 
     1200    } 
     1201     
     1202    else if( strstr(pszGridType,":2dSimpleGrid") ) 
     1203    { 
     1204        if( CSLCount(papszOffsetTokens) == 2 
     1205            && CSLCount(papszOriginTokens) == 2 ) 
     1206        { 
     1207            adfGeoTransform[0] = atof(papszOriginTokens[0]); 
     1208            adfGeoTransform[1] = atof(papszOffsetTokens[0]); 
     1209            adfGeoTransform[2] = 0.0; 
     1210            adfGeoTransform[3] = atof(papszOriginTokens[1]); 
     1211            adfGeoTransform[4] = 0.0; 
     1212            adfGeoTransform[5] = atof(papszOffsetTokens[1]); 
     1213        } 
     1214        else 
     1215        { 
     1216            CPLError( CE_Failure, CPLE_AppDefined,  
     1217                      "2dSimpleGrid does not have expected GridOrigin or\n" 
     1218                      "GridOffsets values - unable to process WCS coverage."); 
     1219            return FALSE; 
     1220        } 
     1221    } 
     1222 
     1223    else 
     1224    { 
     1225        CPLError( CE_Failure, CPLE_AppDefined,  
     1226                  "Unrecognised GridCRS.GridType value '%s',\n" 
     1227                  "unable to process WCS coverage.", 
     1228                  pszGridType ); 
     1229        return FALSE; 
     1230    } 
     1231 
     1232    CSLDestroy( papszOffsetTokens ); 
     1233    CSLDestroy( papszOriginTokens ); 
     1234 
     1235    // GridOrigin is center of pixel ... offset half pixel to adjust.  
     1236 
     1237    adfGeoTransform[0] -= (adfGeoTransform[1]+adfGeoTransform[2]) * 0.5;  
     1238    adfGeoTransform[3] -= (adfGeoTransform[4]+adfGeoTransform[5]) * 0.5;  
     1239 
     1240/* -------------------------------------------------------------------- */ 
     1241/*      Establish our coordinate system.                                */ 
     1242/* -------------------------------------------------------------------- */ 
     1243    osCRS = CPLGetXMLValue( psGCRS, "GridBaseCRS", "" ); 
     1244     
     1245    if( strlen(osCRS) == 0 ) 
     1246    { 
     1247        CPLError( CE_Failure, CPLE_AppDefined, 
     1248                  "Unable to find GridCRS.GridBaseCRS" ); 
     1249        return FALSE; 
     1250    } 
     1251    else if( strstr(osCRS,":imageCRS") ) 
     1252    { 
     1253        // raw image. 
     1254    } 
     1255    else 
     1256    { 
     1257        OGRSpatialReference oSRS; 
     1258        if( oSRS.importFromURN( osCRS ) == OGRERR_NONE ) 
     1259        { 
     1260            CPLFree( pszProjection ); 
     1261            oSRS.exportToWkt( &pszProjection ); 
     1262        } 
     1263        else 
     1264        { 
     1265            CPLError( CE_Failure, CPLE_AppDefined, 
     1266                      "Unable to interprete GridBaseCRS '%s'.", 
     1267                      osCRS.c_str() ); 
     1268            return FALSE; 
     1269        } 
     1270    } 
     1271 
     1272/* -------------------------------------------------------------------- */ 
     1273/*      Search for an ImageCRS for raster size.                         */ 
     1274/* -------------------------------------------------------------------- */ 
     1275    CPLXMLNode *psNode; 
     1276 
     1277    nRasterXSize = -1; 
     1278    nRasterYSize = -1; 
     1279    for( psNode = psSD->psChild;  
     1280         psNode != NULL && nRasterXSize == -1; 
     1281         psNode = psNode->psNext ) 
     1282    { 
     1283        if( psNode->eType != CXT_Element 
     1284            || !EQUAL(psNode->pszVal