Changeset 13893

Show
Ignore:
Timestamp:
02/28/08 16:08:37 (3 months ago)
Author:
rouault
Message:

Modify GDALChecksum to give it a deterministic behaviour when given a GDT_[C]Float[32|64] rasterband with NaN and Inf values. The result is backward compatible with previous implementations with finite values

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/gdal/alg/gdalchecksum.cpp

    r13669 r13893  
    6565 
    6666    int  iLine, i, nChecksum = 0, iPrime = 0, nCount; 
    67     int  *panLineData; 
    68     int  bComplex = GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ); 
     67    GDALDataType eDataType = GDALGetRasterDataType( hBand ); 
     68    int  bComplex = GDALDataTypeIsComplex( eDataType ); 
     69     
     70    if (eDataType == GDT_Float32 || eDataType == GDT_Float64 || 
     71        eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64) 
     72    { 
     73        double* padfLineData; 
     74        GDALDataType eDstDataType = (bComplex) ? GDT_CFloat64 : GDT_Float64; 
    6975 
    70     panLineData = (GInt32 *) VSIMalloc2(nXSize, sizeof(GInt32) * 2); 
    71     if (panLineData == NULL) 
    72    
    73         CPLError( CE_Failure, CPLE_OutOfMemory, 
    74                   "VSIMalloc2(): Out of memory in GDALChecksumImage. " 
    75                   "Checksum value couldn't be computed\n"); 
    76         return 0; 
    77    
     76        padfLineData = (double *) VSIMalloc2(nXSize, sizeof(double) * 2); 
     77        if (padfLineData == NULL) 
     78       
     79            CPLError( CE_Failure, CPLE_OutOfMemory, 
     80                    "VSIMalloc2(): Out of memory in GDALChecksumImage. " 
     81                    "Checksum value couldn't be computed\n"); 
     82            return 0; 
     83       
    7884 
    79     for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ ) 
    80     { 
    81         if( bComplex ) 
     85        for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ ) 
    8286        { 
    8387            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,  
    84                               panLineData, nXSize, 1, GDT_CInt32, 0, 0 ) != CE_None) 
     88                              padfLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None) 
    8589            { 
    8690                CPLError( CE_Failure, CPLE_FileIO, 
    87                           "Checksum value couldn't be computed due to I/O read error.\n"); 
     91                        "Checksum value couldn't be computed due to I/O read error.\n"); 
    8892                break; 
    8993            } 
    90             nCount = nXSize * 2; 
     94            nCount = (bComplex) ? nXSize * 2 : nXSize; 
     95 
     96            for( i = 0; i < nCount; i++ ) 
     97            { 
     98                double dfVal = padfLineData[i]; 
     99                int nVal; 
     100                if (CPLIsNan(dfVal) || CPLIsInf(dfVal)) 
     101                { 
     102                    /* Most compilers seem to cast NaN or Inf to 0x80000000. */ 
     103                    /* but VC7 is an exception. So we force the result */ 
     104                    /* of such a cast */ 
     105                    nVal = 0x80000000; 
     106                } 
     107                else 
     108                { 
     109                    /* Standard behaviour of GDALCopyWords when converting */ 
     110                    /* from floating point to Int32 */ 
     111                    dfVal += 0.5; 
     112 
     113                    if( dfVal < -2147483647.0 ) 
     114                        nVal = -2147483647; 
     115                    else if( dfVal > 2147483647 ) 
     116                        nVal = 2147483647; 
     117                    else 
     118                        nVal = (GInt32) floor(dfVal); 
     119                } 
     120 
     121                nChecksum += (nVal % anPrimes[iPrime++]); 
     122                if( iPrime > 10 ) 
     123                    iPrime = 0; 
     124 
     125                nChecksum &= 0xffff; 
     126            } 
    91127        } 
    92         else 
     128 
     129        CPLFree(padfLineData); 
     130    } 
     131    else 
     132    { 
     133        int  *panLineData; 
     134        GDALDataType eDstDataType = (bComplex) ? GDT_CInt32 : GDT_Int32; 
     135 
     136        panLineData = (GInt32 *) VSIMalloc2(nXSize, sizeof(GInt32) * 2); 
     137        if (panLineData == NULL) 
     138        { 
     139            CPLError( CE_Failure, CPLE_OutOfMemory, 
     140                    "VSIMalloc2(): Out of memory in GDALChecksumImage. " 
     141                    "Checksum value couldn't be computed\n"); 
     142            return 0; 
     143        } 
     144 
     145        for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ ) 
    93146        { 
    94147            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1,  
    95                               panLineData, nXSize, 1, GDT_Int32, 0, 0 ) != CE_None) 
     148                            panLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None) 
    96149            { 
    97150                CPLError( CE_Failure, CPLE_FileIO, 
    98                           "Checksum value couldn't be computed due to I/O read error.\n"); 
     151                        "Checksum value couldn't be computed due to I/O read error.\n"); 
    99152                break; 
    100153            } 
    101             nCount = nXSize; 
     154            nCount = (bComplex) ? nXSize * 2 : nXSize; 
     155 
     156            for( i = 0; i < nCount; i++ ) 
     157            { 
     158                nChecksum += (panLineData[i] % anPrimes[iPrime++]); 
     159                if( iPrime > 10 ) 
     160                    iPrime = 0; 
     161 
     162                nChecksum &= 0xffff; 
     163            } 
    102164        } 
    103165 
    104         for( i = 0; i < nCount; i++ ) 
    105         { 
    106             nChecksum += (panLineData[i] % anPrimes[iPrime++]); 
    107             if( iPrime > 10 ) 
    108                 iPrime = 0; 
    109  
    110             nChecksum &= 0xffff; 
    111         } 
     166        CPLFree( panLineData ); 
    112167    } 
    113  
    114     CPLFree( panLineData ); 
    115168 
    116169    return nChecksum;