Changeset 13829

Show
Ignore:
Timestamp:
02/21/08 14:09:39 (3 months ago)
Author:
rouault
Message:

Backport of recent changes done in trunk for GSAG driver (ticket #2224)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/1.5/gdal/frmts/gsg/gsagdataset.cpp

    r12155 r13829  
    8585 
    8686    static GDALDataset *Open( GDALOpenInfo * ); 
    87     static GDALDataset *Create( const char * pszFilename, 
    88                                 int nXSize, int nYSize, int nBands, 
    89                                 GDALDataType eType, 
    90                                 char **papszParmList ); 
    9187    static GDALDataset *CreateCopy( const char *pszFilename, 
    9288                                    GDALDataset *poSrcDS, 
     
    124120 
    125121    vsi_l_offset *panLineOffset; 
     122        int nLastReadLine; 
    126123 
    127124    double *padfRowMinZ; 
     
    183180 
    184181    panLineOffset = 
    185         (vsi_l_offset *)CPLCalloc( poDS->nRasterYSize+1, sizeof(vsi_l_offset) ); 
     182        (vsi_l_offset *)VSICalloc( poDS->nRasterYSize+1, sizeof(vsi_l_offset) ); 
    186183    if( panLineOffset == NULL ) 
     184    { 
     185        CPLError(CE_Failure, CPLE_OutOfMemory, 
     186                 "GSAGRasterBand::GSAGRasterBand : Out of memory allocating %d * %d bytes", 
     187                 poDS->nRasterYSize+1, sizeof(vsi_l_offset) ); 
    187188        return; 
    188  
    189     panLineOffset[0] = nDataStart; 
     189    } 
     190 
     191        panLineOffset[poDS->nRasterYSize-1] = nDataStart; 
     192        nLastReadLine = poDS->nRasterYSize; 
    190193} 
    191194 
     
    304307 
    305308    if( nBlockYOff < 0 || nBlockYOff > nRasterYSize - 1 || nBlockXOff != 0 ) 
    306        return CE_Failure; 
     309        return CE_Failure; 
    307310 
    308311    if( panLineOffset[nBlockYOff] == 0 ) 
    309         IReadBlock( nBlockXOff, nBlockYOff-1, NULL ); 
     312    { 
     313        // Discover the last read block 
     314        for ( int iFoundLine = nLastReadLine - 1; iFoundLine > nBlockYOff; iFoundLine--) 
     315        { 
     316            IReadBlock( nBlockXOff, iFoundLine, NULL); 
     317        } 
     318    } 
    310319 
    311320    if( panLineOffset[nBlockYOff] == 0 ) 
    312         return CE_Failure; 
    313  
     321        return CE_Failure; 
    314322    if( VSIFSeekL( poGDS->fp, panLineOffset[nBlockYOff], SEEK_SET ) != 0 ) 
    315323    { 
    316        CPLError( CE_Failure, CPLE_FileIO, 
    317                  "Can't seek to offset %ld to read grid row %d.", 
    318                  panLineOffset[nBlockYOff], nBlockYOff ); 
    319        return CE_Failure; 
     324        CPLError( CE_Failure, CPLE_FileIO, 
     325                  "Can't seek to offset %ld to read grid row %d.", 
     326                  panLineOffset[nBlockYOff], nBlockYOff ); 
     327        return CE_Failure; 
    320328    } 
    321329 
     
    325333    size_t nCharsExamined = 0; 
    326334    /* If we know the offsets, we can just read line directly */ 
    327     if( panLineOffset[nBlockYOff+1] != 0
    328     { 
    329         assert(panLineOffset[nBlockYOff+1] > panLineOffset[nBlockYOff]); 
    330         nLineBufSize = panLineOffset[nBlockYOff+1] 
    331                              - panLineOffset[nBlockYOff] + 1; 
     335    if( (nBlockYOff > 0) && ( panLineOffset[nBlockYOff-1] != 0 )
     336    { 
     337        assert(panLineOffset[nBlockYOff-1] > panLineOffset[nBlockYOff]); 
     338        nLineBufSize = panLineOffset[nBlockYOff-1] 
     339            - panLineOffset[nBlockYOff] + 1; 
    332340    } 
    333341    else 
     
    413421 
    414422                while( *szStart == '\0' && 
    415                        static_cast<size_t>(szStart - szLineBuf) < nCharsRead ) 
     423                       static_cast<size_t>(szStart - szLineBuf) < nCharsRead ) 
    416424                    szStart++; 
    417425 
     
    435443        } 
    436444        else if( *szEnd == '\0' 
    437                || (*szEnd == '.' && *(szEnd+1) == '\0') 
    438                || (*szEnd == '-' && *(szEnd+1) == '\0') 
    439                || (*szEnd == '+' && *(szEnd+1) == '\0') 
    440                || (*szEnd == 'E' && *(szEnd+1) == '\0') 
    441                || (*szEnd == 'E' && *(szEnd+1) == '-' && *(szEnd+2) == '\0') 
    442                || (*szEnd == 'E' && *(szEnd+1) == '+' && *(szEnd+2) == '\0') 
    443                || (*szEnd == 'e' && *(szEnd+1) == '\0') 
    444                || (*szEnd == 'e' && *(szEnd+1) == '-' && *(szEnd+2) == '\0') 
    445                || (*szEnd == 'e' && *(szEnd+1) == '+' && *(szEnd+2) == '\0')) 
     445                 || (*szEnd == '.' && *(szEnd+1) == '\0') 
     446                 || (*szEnd == '-' && *(szEnd+1) == '\0') 
     447                 || (*szEnd == '+' && *(szEnd+1) == '\0') 
     448                 || (*szEnd == 'E' && *(szEnd+1) == '\0') 
     449                 || (*szEnd == 'E' && *(szEnd+1) == '-' && *(szEnd+2) == '\0') 
     450                 || (*szEnd == 'E' && *(szEnd+1) == '+' && *(szEnd+2) == '\0') 
     451                 || (*szEnd == 'e' && *(szEnd+1) == '\0') 
     452                 || (*szEnd == 'e' && *(szEnd+1) == '-' && *(szEnd+2) == '\0') 
     453                 || (*szEnd == 'e' && *(szEnd+1) == '+' && *(szEnd+2) == '\0')) 
    446454        { 
    447455            /* Number was interrupted by a nul character */ 
     
    510518    if( *szEnd != '\0' && *szEnd != poGDS->szEOL[0] ) 
    511519        CPLDebug( "GSAG", "Grid row %d does not end with a newline.  " 
    512                         "Possible skew.\n", nBlockYOff ); 
     520                  "Possible skew.\n", nBlockYOff ); 
    513521 
    514522    while( isspace( *szEnd ) ) 
     
    520528        nMaxLineSize = nCharsExamined + 1; 
    521529 
    522     panLineOffset[nBlockYOff + 1] = panLineOffset[nBlockYOff] + nCharsExamined; 
     530    if( nBlockYOff > 0 ) 
     531        panLineOffset[nBlockYOff - 1] =  
     532            panLineOffset[nBlockYOff] + nCharsExamined; 
     533 
     534    nLastReadLine = nBlockYOff; 
    523535 
    524536    VSIFree( szLineBuf ); 
     
    551563        || nMinZRow < 0 || nMaxZRow < 0 ) 
    552564    { 
    553         padfRowMinZ = (double *)VSIMalloc( nRasterYSize*sizeof(double) ); 
     565        padfRowMinZ = (double *)VSIMalloc( nRasterYSize * sizeof(double) ); 
    554566        if( padfRowMinZ == NULL ) 
    555567        { 
     
    559571        } 
    560572 
    561         padfRowMaxZ = (double *)VSIMalloc( nRasterYSize*sizeof(double) ); 
     573        padfRowMaxZ = (double *)VSIMalloc( nRasterYSize * sizeof(double) ); 
    562574        if( padfRowMaxZ == NULL ) 
    563575        { 
     
    853865 
    854866        size_t nRead = VSIFReadL( pabyHeader, 1, nMAX_HEADER_SIZE-1, poDS->fp ); 
    855         pabyHeader[nRead+1] = '\0'; 
    856     } 
    857  
    858     const char *szErrorMsg
     867        pabyHeader[nRead] = '\0'; 
     868    } 
     869 
     870    const char *szErrorMsg = NULL
    859871    const char *szStart = pabyHeader + 5; 
    860872    char *szEnd; 
     
    880892        poDS->nRasterXSize = INT_MAX; 
    881893    } 
     894    else if ( nTemp == 0 ) 
     895    { 
     896        szErrorMsg = "Number of X axis grid columns is zero, which is invalid.\n"; 
     897        goto error; 
     898    } 
    882899    else 
    883900    { 
     
    898915                  "Number of Y axis grid rows not representable.\n" ); 
    899916        poDS->nRasterYSize = INT_MAX; 
     917    } 
     918    else if ( nTemp == 0) 
     919    { 
     920        szErrorMsg = "Number of Y axis grid rows is zero, which is invalid.\n"; 
     921        goto error; 
    900922    } 
    901923    else 
     
    9941016    { 
    9951017    GSAGRasterBand *poBand = new GSAGRasterBand( poDS, 1, szEnd-pabyHeader ); 
     1018    if( poBand->panLineOffset == NULL ) 
     1019    { 
     1020        delete poBand; 
     1021        goto error; 
     1022    } 
     1023 
    9961024    poBand->dfMinX = dfMinX; 
    9971025    poBand->dfMaxX = dfMaxX; 
     
    10251053    delete poDS; 
    10261054 
    1027     CPLError( CE_Failure, CPLE_AppDefined, szErrorMsg ); 
     1055    if (szErrorMsg) 
     1056        CPLError( CE_Failure, CPLE_AppDefined, szErrorMsg ); 
    10281057    return NULL; 
    10291058} 
     
    14411470 
    14421471/************************************************************************/ 
    1443 /*                               Create()                               */ 
    1444 /************************************************************************/ 
    1445  
    1446 GDALDataset *GSAGDataset::Create( const char * pszFilename, 
    1447                                   int nXSize, int nYSize, int nBands, 
    1448                                   GDALDataType eType, 
    1449                                   char **papszParmList ) 
    1450  
    1451 { 
    1452     if( nXSize <= 0 || nYSize <= 0 ) 
    1453     { 
    1454         CPLError( CE_Failure, CPLE_IllegalArg, 
    1455                   "Unable to create grid, both X and Y size must be " 
    1456                   "non-negative.\n" ); 
    1457  
    1458         return NULL; 
    1459     } 
    1460  
    1461     if( eType != GDT_Byte && eType != GDT_Float32 && eType != GDT_UInt16 
    1462         && eType != GDT_Int16 && eType != GDT_Float64 && eType != GDT_Int32 
    1463         && eType != GDT_UInt32 ) 
    1464     { 
    1465         CPLError( CE_Failure, CPLE_AppDefined, 
    1466                   "Golden Software ASCII Grid only supports Byte, Int16, " 
    1467                   "Uint16, Int32, Uint32, Float32, and Float64 datatypes.  " 
    1468                   "Unable to create with type %s.\n", 
    1469                   GDALGetDataTypeName( eType ) ); 
    1470  
    1471         return NULL; 
    1472     } 
    1473  
    1474     FILE *fp = VSIFOpenL( pszFilename, "w+b" ); 
    1475  
    1476     if( fp == NULL ) 
    1477     { 
    1478         CPLError( CE_Failure, CPLE_OpenFailed, 
    1479                   "Attempt to create file '%s' failed.\n", 
    1480                   pszFilename ); 
    1481         return NULL; 
    1482     } 
    1483  
    1484     std::ostringstream ssHeader; 
    1485  
    1486     ssHeader << "DSAA\x0D\x0A"; 
    1487     ssHeader << nXSize << " " << nYSize << "\x0D\x0A"; 
    1488     ssHeader << 0.0 << " " << nXSize << "\x0D\x0A"; 
    1489     ssHeader << 0.0 << " " << nYSize << "\x0D\x0A"; 
    1490     ssHeader << 0.0 << " " << 0.0 << "\x0D\x0A"; 
    1491  
    1492     if( VSIFWriteL( (void *)ssHeader.str().c_str(), 1, ssHeader.str().length(), 
    1493                     fp ) != ssHeader.str().length() ) 
    1494     { 
    1495         VSIFCloseL( fp ); 
    1496         CPLError( CE_Failure, CPLE_FileIO, 
    1497                   "Unable to create copy, writing header failed.\n" ); 
    1498         return NULL; 
    1499     } 
    1500  
    1501     /* grid data, row major, max 10 values per line (to mimic Surfer) */ 
    1502     std::ostringstream ssOutStream; 
    1503     ssOutStream.precision( nFIELD_PRECISION ); 
    1504     ssOutStream.setf( std::ios::uppercase ); 
    1505     ssOutStream << dfNODATA_VALUE << " "; 
    1506     CPLString sOut = ssOutStream.str(); 
    1507     const char *szOut = sOut.c_str(); 
    1508     size_t nOutLen = sOut.length(); 
    1509     for( int iRow=0; iRow<nYSize; iRow++ ) 
    1510     { 
    1511         for( int iLine=0; iLine<nXSize/10+1; iLine++ ) 
    1512         { 
    1513             for( int iCol=0; iCol<10 && iLine*10+iCol<nXSize; iCol++ ) 
    1514             { 
    1515                 if( VSIFWriteL( szOut, 1, nOutLen, fp ) != nOutLen ) 
    1516                 { 
    1517                     CPLError( CE_Failure, CPLE_FileIO, 
    1518                               "Unable to write grid cell.  Disk full?\n" ); 
    1519                     return NULL; 
    1520                 } 
    1521             } 
    1522  
    1523             if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 ) 
    1524             { 
    1525                 CPLError( CE_Failure, CPLE_FileIO, 
    1526                           "Unable to finish write of grid line. Disk full?\n" ); 
    1527                 return NULL; 
    1528             } 
    1529         } 
    1530  
    1531         if( VSIFWriteL( (void *)"\x0D\x0A", 1, 2, fp ) != 2 ) 
    1532         { 
    1533             CPLError( CE_Failure, CPLE_FileIO, 
    1534                       "Unable to finish write of grid row. Disk full?\n" ); 
    1535             return NULL; 
    1536         } 
    1537     } 
    1538  
    1539     VSIFCloseL( fp ); 
    1540  
    1541     return (GDALDataset *)GDALOpen( pszFilename, GA_Update ); 
    1542 } 
    1543  
    1544 /************************************************************************/ 
    15451472/*                             CreateCopy()                             */ 
    15461473/************************************************************************/ 
     
    16331560/*      Copy band data.                                                 */ 
    16341561/* -------------------------------------------------------------------- */ 
    1635     double *pdfData = (double *)VSIMalloc(nXSize * sizeof( double ) ); 
     1562    double *pdfData = (double *)VSIMalloc( nXSize * sizeof( double ) ); 
    16361563    if( pdfData == NULL ) 
    16371564    { 
     
    16491576    for( int iRow=0; iRow<nYSize; iRow++ ) 
    16501577    { 
    1651         CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, iRow
     1578        CPLErr eErr = poSrcBand->RasterIO( GF_Read, 0, nYSize-iRow-1
    16521579                                           nXSize, 1, pdfData, 
    16531580                                           nXSize, 1, GDT_Float64, 0, 0 ); 
     
    18921819                                   "Float32 Float64" ); 
    18931820 
    1894         poDriver->pfnOpen = GSAGDataset::Open; 
    1895         poDriver->pfnCreate = GSAGDataset::Create; 
     1821    poDriver->pfnOpen = GSAGDataset::Open; 
    18961822        poDriver->pfnCreateCopy = GSAGDataset::CreateCopy; 
    18971823        poDriver->pfnDelete = GSAGDataset::Delete;