Beispiel #1
0
int Raster::Uniform(const char * pOutputRaster, double fValue)
{

    // Open up the Input File
    GDALDataset * pInputDS = (GDALDataset*) GDALOpen(m_sFilePath, GA_ReadOnly);
    if (pInputDS == NULL)
        throw RasterManagerException( INPUT_FILE_ERROR, "Input file could not be opened");

    GDALRasterBand * pRBInput = pInputDS->GetRasterBand(1);

    // Create the output dataset for writing
    GDALDataset * pOutputDS = CreateOutputDS(pOutputRaster, this);
    GDALRasterBand * pOutputRB = pOutputDS->GetRasterBand(1);

    // Assign our buffers
    double * pInputLine = (double*) CPLMalloc(sizeof(double) * GetCols());
    double * pOutputLine = (double*) CPLMalloc(sizeof(double) * GetCols());

    // Loop over rows
    for (int i=0; i < GetRows(); i++)
    {
        // Populate the buffer
        pRBInput->RasterIO(GF_Read, 0,  i, GetCols(), 1, pInputLine, GetCols(), 1, GDT_Float64, 0, 0);

        // Loop over columns
        for (int j=0; j < GetCols(); j++)
        {
            if (pInputLine[j] != GetNoDataValue()){
                pOutputLine[j] = fValue;
            }
            else {
                pOutputLine[j] = GetNoDataValue();
            }

        }
        // Write the row
        pOutputRB->RasterIO(GF_Write, 0, i, GetCols(), 1, pOutputLine, GetCols(), 1, GDT_Float64, 0, 0 );
    }

    CPLFree(pOutputLine);
    CPLFree(pInputLine);

    CalculateStats(pOutputDS->GetRasterBand(1));

    if ( pInputDS != NULL)
        GDALClose(pInputDS);
    if ( pOutputDS != NULL)
        GDALClose(pOutputDS);

    return PROCESS_OK;

}
/***********************************************************************
 * \brief Set the block data to the null value if it is set, or zero if
 * there is no null data value.
 * Parameters:
 *  - void *: the block data
 * Returns: nothing
 **********************************************************************/
void PostGISRasterRasterBand::NullBlock(void *pData)
{
    int nWords = nBlockXSize * nBlockYSize;
    int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;

    int bNoDataSet;
    double dfNoData = GetNoDataValue(&bNoDataSet);
    if (!bNoDataSet) {
        memset(pData, 0, nWords * nDataTypeSize);
    }

    else {
        GDALCopyWords(&dfNoData, GDT_Float64, 0,
                      pData, eDataType, nDataTypeSize,
                      nWords);
    }
}
Beispiel #3
0
CPLErr GDALPamRasterBand::CloneInfo( GDALRasterBand *poSrcBand, 
                                     int nCloneFlags )

{
    int bOnlyIfMissing = nCloneFlags & GCIF_ONLY_IF_MISSING;
    int bSuccess;
    int nSavedMOFlags = GetMOFlags();

    PamInitialize();

/* -------------------------------------------------------------------- */
/*      Supress NotImplemented error messages - mainly needed if PAM    */
/*      disabled.                                                       */
/* -------------------------------------------------------------------- */
    SetMOFlags( nSavedMOFlags | GMO_IGNORE_UNIMPLEMENTED );

/* -------------------------------------------------------------------- */
/*      Metadata                                                        */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_BAND_METADATA )
    {
        if( poSrcBand->GetMetadata() != NULL )
        {
            if( !bOnlyIfMissing 
             || CSLCount(GetMetadata()) != CSLCount(poSrcBand->GetMetadata()) )
            {
                SetMetadata( poSrcBand->GetMetadata() );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Band description.                                               */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_BAND_DESCRIPTION )
    {
        if( strlen(poSrcBand->GetDescription()) > 0 )
        {
            if( !bOnlyIfMissing || strlen(GetDescription()) == 0 )
                GDALPamRasterBand::SetDescription( poSrcBand->GetDescription());
        }
    }

/* -------------------------------------------------------------------- */
/*      NODATA                                                          */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_NODATA )
    {
        double dfNoData = poSrcBand->GetNoDataValue( &bSuccess );
        
        if( bSuccess )
        {
            if( !bOnlyIfMissing 
                || GetNoDataValue( &bSuccess ) != dfNoData 
                || !bSuccess )
                GDALPamRasterBand::SetNoDataValue( dfNoData );
        }
    }

/* -------------------------------------------------------------------- */
/*      Offset/scale                                                    */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_SCALEOFFSET )
    {
        double dfOffset = poSrcBand->GetOffset( &bSuccess );
        
        if( bSuccess )
        {
            if( !bOnlyIfMissing || GetOffset() != dfOffset )
                GDALPamRasterBand::SetOffset( dfOffset );
        }

        double dfScale = poSrcBand->GetScale( &bSuccess );
        
        if( bSuccess )
        {
            if( !bOnlyIfMissing || GetScale() != dfScale )
                GDALPamRasterBand::SetScale( dfScale );
        }
    }

/* -------------------------------------------------------------------- */
/*      Unittype.                                                       */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_UNITTYPE )
    {
        if( strlen(poSrcBand->GetUnitType()) > 0 )
        {
            if( !bOnlyIfMissing 
                || !EQUAL(GetUnitType(),poSrcBand->GetUnitType()) )
            {
                GDALPamRasterBand::SetUnitType( poSrcBand->GetUnitType() );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      ColorInterp                                                     */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_COLORINTERP )
    {
        if( poSrcBand->GetColorInterpretation() != GCI_Undefined )
        {
            if( !bOnlyIfMissing
                || poSrcBand->GetColorInterpretation() 
                != GetColorInterpretation() )
                GDALPamRasterBand::SetColorInterpretation( 
                    poSrcBand->GetColorInterpretation() );
        }
    }

/* -------------------------------------------------------------------- */
/*      color table.                                                    */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_COLORTABLE )
    {
        if( poSrcBand->GetColorTable() != NULL )
        {
            if( !bOnlyIfMissing || GetColorTable() == NULL )
            {
                GDALPamRasterBand::SetColorTable( 
                    poSrcBand->GetColorTable() );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Raster Attribute Table.                                         */
/* -------------------------------------------------------------------- */
    if( nCloneFlags & GCIF_RAT )
    {
        const GDALRasterAttributeTable *poRAT = poSrcBand->GetDefaultRAT();

        if( poRAT != NULL )
        {
            if( !bOnlyIfMissing || GetDefaultRAT() == NULL )
            {
                GDALPamRasterBand::SetDefaultRAT( poRAT );
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Restore MO flags.                                               */
/* -------------------------------------------------------------------- */
    SetMOFlags( nSavedMOFlags );

    return CE_None;
}
Beispiel #4
0
CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                  int nBlockYOff,
                                  void * pImage )
{
    XYZDataset *poGDS = (XYZDataset *) poDS;

    if (poGDS->fp == NULL)
        return CE_Failure;

    if( pImage )
    {
        int bSuccess = FALSE;
        double dfNoDataValue = GetNoDataValue(&bSuccess);
        if( !bSuccess )
            dfNoDataValue = 0.0;
        GDALCopyWords(&dfNoDataValue, GDT_Float64, 0,
                      pImage, eDataType, GDALGetDataTypeSize(eDataType) / 8,
                      nRasterXSize);
    }

    int nLineInFile = nBlockYOff * nBlockXSize; // only valid if bSameNumberOfValuesPerLine
    if ( (poGDS->bSameNumberOfValuesPerLine && poGDS->nDataLineNum > nLineInFile) ||
         (!poGDS->bSameNumberOfValuesPerLine && (nLastYOff == -1 || nBlockYOff == 0)) )
    {
        poGDS->nDataLineNum = 0;
        poGDS->nLineNum = 0;
        VSIFSeekL(poGDS->fp, 0, SEEK_SET);

        for(int i=0;i<poGDS->nCommentLineCount;i++)
        {
            CPLReadLine2L(poGDS->fp, 100, NULL);
            poGDS->nLineNum ++;
        }

        if (poGDS->bHasHeaderLine)
        {
            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
            if (pszLine == NULL)
                return CE_Failure;
            poGDS->nLineNum ++;
        }
    }

    if( !poGDS->bSameNumberOfValuesPerLine && nBlockYOff != nLastYOff + 1 )
    {
        int iY;
        if( nBlockYOff < nLastYOff )
        {
            nLastYOff = -1;
            for(iY = 0; iY < nBlockYOff; iY++)
            {
                if( IReadBlock(0, iY, NULL) != CE_None )
                    return CE_Failure;
            }
        }
        else
        {
            for(iY = nLastYOff + 1; iY < nBlockYOff; iY++)
            {
                if( IReadBlock(0, iY, NULL) != CE_None )
                    return CE_Failure;
            }
        }
    }
    else if( poGDS->bSameNumberOfValuesPerLine )
    {
        while(poGDS->nDataLineNum < nLineInFile)
        {
            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
            if (pszLine == NULL)
                return CE_Failure;
            poGDS->nLineNum ++;

            const char* pszPtr = pszLine;
            char ch;
            int nCol = 0;
            int bLastWasSep = TRUE;
            while((ch = *pszPtr) != '\0')
            {
                if (ch == ' ')
                {
                    if (!bLastWasSep)
                        nCol ++;
                    bLastWasSep = TRUE;
                }
                else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
                {
                    nCol ++;
                    bLastWasSep = TRUE;
                }
                else
                {
                    bLastWasSep = FALSE;
                }
                pszPtr ++;
            }

            /* Skip empty line */
            if (nCol == 0 && bLastWasSep)
                continue;

            poGDS->nDataLineNum ++;
        }
    }

    double dfExpectedY = poGDS->adfGeoTransform[3] + (0.5 + nBlockYOff) * poGDS->adfGeoTransform[5];
    int idx = -1;
    while(TRUE)
    {
        int nCol;
        int bLastWasSep;
        do
        {
            vsi_l_offset nOffsetBefore = VSIFTellL(poGDS->fp);
            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, 0);
            if (pszLine == NULL)
            {
                if( poGDS->bSameNumberOfValuesPerLine )
                {
                    CPLError(CE_Failure, CPLE_AppDefined, "Cannot read line %d", poGDS->nLineNum + 1);
                    return CE_Failure;
                }
                else
                {
                    nLastYOff = nBlockYOff;
                    return CE_None;
                }
            }
            poGDS->nLineNum ++;

            const char* pszPtr = pszLine;
            char ch;
            nCol = 0;
            bLastWasSep = TRUE;
            double dfX = 0.0, dfY = 0.0, dfZ = 0.0;
            int bUsefulColsFound = 0;
            while((ch = *pszPtr) != '\0')
            {
                if (ch == ' ')
                {
                    if (!bLastWasSep)
                        nCol ++;
                    bLastWasSep = TRUE;
                }
                else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
                {
                    nCol ++;
                    bLastWasSep = TRUE;
                }
                else
                {
                    if (bLastWasSep)
                    {
                        if (nCol == poGDS->nXIndex)
                        {
                            bUsefulColsFound ++;
                            if( !poGDS->bSameNumberOfValuesPerLine )
                                dfX = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                        }
                        else if (nCol == poGDS->nYIndex)
                        {
                            bUsefulColsFound ++;
                            if( !poGDS->bSameNumberOfValuesPerLine )
                                dfY = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                        }
                        else if( nCol == poGDS->nZIndex)
                        {
                            bUsefulColsFound ++;
                            dfZ = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                        }
                    }
                    bLastWasSep = FALSE;
                }
                pszPtr ++;
            }
            nCol ++;

            if( bUsefulColsFound == 3 )
            {
                if( poGDS->bSameNumberOfValuesPerLine )
                {
                    idx ++;
                }
                else
                {
                    if( fabs(dfY - dfExpectedY) > 1e-8 )
                    {
                        if( idx < 0 )
                        {
                            CPLError(CE_Failure, CPLE_AppDefined, "At line %d, found %f instead of %f for nBlockYOff = %d",
                                    poGDS->nLineNum, dfY, dfExpectedY, nBlockYOff);
                            return CE_Failure;
                        }
                        VSIFSeekL(poGDS->fp, nOffsetBefore, SEEK_SET);
                        nLastYOff = nBlockYOff;
                        poGDS->nLineNum --;
                        return CE_None;
                    }

                    idx = (int)((dfX - 0.5 * poGDS->adfGeoTransform[1] - poGDS->adfGeoTransform[0]) / poGDS->adfGeoTransform[1] + 0.5);
                }
                CPLAssert(idx >= 0 && idx < nRasterXSize);

                if( pImage )
                {
                    if (eDataType == GDT_Float32)
                    {
                        ((float*)pImage)[idx] = (float)dfZ;
                    }
                    else if (eDataType == GDT_Int32)
                    {
                        ((GInt32*)pImage)[idx] = (GInt32)dfZ;
                    }
                    else if (eDataType == GDT_Int16)
                    {
                        ((GInt16*)pImage)[idx] = (GInt16)dfZ;
                    }
                    else
                    {
                        ((GByte*)pImage)[idx] = (GByte)dfZ;
                    }
                }
            }
            /* Skip empty line */
        }
        while (nCol == 1 && bLastWasSep);

        poGDS->nDataLineNum ++;
        if (nCol < poGDS->nMinTokens)
            return CE_Failure;

        if( idx + 1 == nRasterXSize )
            break;
    }

    if( poGDS->bSameNumberOfValuesPerLine ) {
        CPLAssert(poGDS->nDataLineNum == (nBlockYOff + 1) * nBlockXSize);
    }

    nLastYOff = nBlockYOff;

    return CE_None;
}
Beispiel #5
0
CPLErr XYZRasterBand::IReadBlock( CPL_UNUSED int nBlockXOff,
                                  int nBlockYOff,
                                  void * pImage )
{
    XYZDataset *poGDS = reinterpret_cast<XYZDataset *>( poDS );

    if (poGDS->fp == NULL)
        return CE_Failure;

    if( pImage )
    {
        int bSuccess = FALSE;
        double dfNoDataValue = GetNoDataValue(&bSuccess);
        if( !bSuccess )
            dfNoDataValue = 0.0;
        GDALCopyWords(&dfNoDataValue, GDT_Float64, 0,
                      pImage, eDataType, GDALGetDataTypeSize(eDataType) / 8,
                      nRasterXSize);
    }

    // Only valid if bSameNumberOfValuesPerLine.
    const GIntBig nLineInFile = static_cast<GIntBig>(nBlockYOff) * nBlockXSize;
    if ( (poGDS->bSameNumberOfValuesPerLine && poGDS->nDataLineNum > nLineInFile) ||
         (!poGDS->bSameNumberOfValuesPerLine && (nLastYOff == -1 || nBlockYOff == 0)) )
    {
        poGDS->nDataLineNum = 0;
        poGDS->nLineNum = 0;
        poGDS->bEOF = false;
        VSIFSeekL(poGDS->fp, 0, SEEK_SET);

        for(int i=0;i<poGDS->nCommentLineCount;i++)
        {
            if( CPLReadLine2L(poGDS->fp, 100, NULL) == NULL )
            {
                poGDS->bEOF = true;
                return CE_Failure;
            }
            poGDS->nLineNum ++;
        }

        if (poGDS->bHasHeaderLine)
        {
            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, NULL);
            if (pszLine == NULL)
            {
                poGDS->bEOF = true;
                return CE_Failure;
            }
            poGDS->nLineNum ++;
        }
    }

    if( !poGDS->bSameNumberOfValuesPerLine )
    {
        if( nBlockYOff < nLastYOff )
        {
            nLastYOff = -1;
            for( int iY = 0; iY < nBlockYOff; iY++ )
            {
                if( IReadBlock(0, iY, NULL) != CE_None )
                    return CE_Failure;
            }
        }
        else
        {
            if( poGDS->bEOF )
            {
                return CE_Failure;
            }
            for( int iY = nLastYOff + 1; iY < nBlockYOff; iY++ )
            {
                if( IReadBlock(0, iY, NULL) != CE_None )
                    return CE_Failure;
            }
        }
    }
    else
    {
        if( poGDS->bEOF )
        {
            return CE_Failure;
        }
        while(poGDS->nDataLineNum < nLineInFile)
        {
            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, NULL);
            if (pszLine == NULL)
            {
                poGDS->bEOF = true;
                return CE_Failure;
            }
            poGDS->nLineNum ++;

            const char* pszPtr = pszLine;
            char ch;
            int nCol = 0;
            bool bLastWasSep = true;
            while((ch = *pszPtr) != '\0')
            {
                if (ch == ' ')
                {
                    if (!bLastWasSep)
                        nCol ++;
                    bLastWasSep = true;
                }
                else if ((ch == ',' && poGDS->chDecimalSep != ',') || ch == '\t' || ch == ';')
                {
                    nCol ++;
                    bLastWasSep = true;
                }
                else
                {
                    bLastWasSep = false;
                }
                pszPtr ++;
            }

            /* Skip empty line */
            if (nCol == 0 && bLastWasSep)
                continue;

            poGDS->nDataLineNum ++;
        }
    }

    const double dfExpectedY
        = poGDS->adfGeoTransform[3] +
        (0.5 + nBlockYOff) * poGDS->adfGeoTransform[5];

    int idx = -1;
    while(true)
    {
        int nCol;
        bool bLastWasSep;
        do
        {
            const vsi_l_offset nOffsetBefore = VSIFTellL(poGDS->fp);
            const char* pszLine = CPLReadLine2L(poGDS->fp, 100, NULL);
            if (pszLine == NULL)
            {
                poGDS->bEOF = true;
                if( poGDS->bSameNumberOfValuesPerLine )
                {
                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Cannot read line " CPL_FRMT_GIB, poGDS->nLineNum + 1);
                    return CE_Failure;
                }
                else
                {
                    nLastYOff = nBlockYOff;
                    return CE_None;
                }
            }
            poGDS->nLineNum ++;

            const char* pszPtr = pszLine;
            char ch;
            nCol = 0;
            bLastWasSep = true;
            double dfX = 0.0;
            double dfY = 0.0;
            double dfZ = 0.0;
            int nUsefulColsFound = 0;
            while((ch = *pszPtr) != '\0')
            {
                if (ch == ' ')
                {
                    if (!bLastWasSep)
                        nCol ++;
                    bLastWasSep = true;
                }
                else if ( ( ch == ',' && poGDS->chDecimalSep != ',' )
                          || ch == '\t' || ch == ';' )
                {
                    nCol ++;
                    bLastWasSep = true;
                }
                else
                {
                    if (bLastWasSep)
                    {
                        if (nCol == poGDS->nXIndex)
                        {
                            nUsefulColsFound ++;
                            if( !poGDS->bSameNumberOfValuesPerLine )
                                dfX = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                        }
                        else if (nCol == poGDS->nYIndex)
                        {
                            nUsefulColsFound ++;
                            if( !poGDS->bSameNumberOfValuesPerLine )
                                dfY = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                        }
                        else if( nCol == poGDS->nZIndex)
                        {
                            nUsefulColsFound ++;
                            dfZ = CPLAtofDelim(pszPtr, poGDS->chDecimalSep);
                        }
                    }
                    bLastWasSep = false;
                }
                pszPtr ++;
            }
            nCol ++;

            if( nUsefulColsFound == 3 )
            {
                if( poGDS->bSameNumberOfValuesPerLine )
                {
                    idx ++;
                }
                else
                {
                    if( fabs( (dfY - dfExpectedY) / poGDS->adfGeoTransform[5] ) > RELATIVE_ERROR )
                    {
                        if( idx < 0 )
                        {
                            CPLError( CE_Failure, CPLE_AppDefined,
                                      "At line " CPL_FRMT_GIB", found %f instead of %f "
                                      "for nBlockYOff = %d",
                                      poGDS->nLineNum, dfY, dfExpectedY,
                                      nBlockYOff);
                            return CE_Failure;
                        }
                        VSIFSeekL(poGDS->fp, nOffsetBefore, SEEK_SET);
                        nLastYOff = nBlockYOff;
                        poGDS->nLineNum --;
                        return CE_None;
                    }

                    idx = static_cast<int>(
                        ( dfX - 0.5 * poGDS->adfGeoTransform[1]
                          - poGDS->adfGeoTransform[0] )
                        / poGDS->adfGeoTransform[1] + 0.5 );
                }
                CPLAssert(idx >= 0 && idx < nRasterXSize);

                if( pImage )
                {
                    if (eDataType == GDT_Float32)
                    {
                        reinterpret_cast<float *>( pImage )[idx]
                            = static_cast<float>(dfZ);
                    }
                    else if (eDataType == GDT_Int32)
                    {
                        reinterpret_cast<GInt32 *>( pImage )[idx]
                            = static_cast<GInt32>( dfZ );
                    }
                    else if (eDataType == GDT_Int16)
                    {
                        reinterpret_cast<GInt16 *>( pImage )[idx]
                            = static_cast<GInt16>( dfZ );
                    }
                    else
                    {
                        reinterpret_cast<GByte *>( pImage )[idx]
                            = static_cast<GByte>( dfZ );
                    }
                }
            }
            /* Skip empty line */
        }
        while (nCol == 1 && bLastWasSep);

        poGDS->nDataLineNum ++;
        if (nCol < poGDS->nMinTokens)
            return CE_Failure;

        if( idx + 1 == nRasterXSize )
            break;
    }

    if( poGDS->bSameNumberOfValuesPerLine ) {
        if( poGDS->nDataLineNum != static_cast<GIntBig>(nBlockYOff + 1) * nBlockXSize )
        {
            CPLError(CE_Failure, CPLE_AssertionFailed,
                     "The file has not the same number of values per "
                     "line as initialy thought. It must be somehow corrupted");
            return CE_Failure;
        }
    }

    nLastYOff = nBlockYOff;

    return CE_None;
}
Beispiel #6
0
int  Raster::Copy(const char * pOutputRaster,
                  double * dNewCellSize,
                  double fLeft, double fTop, int nRows, int nCols)
{
    if (fLeft <=0)
        return LEFT_ERROR;

    if (fTop <=0)
        return TOP_ERROR;

    if (nRows <=0)
        return ROWS_ERROR;

    if (nCols <=0)
        return COLS_ERROR;


    // Open the original dataset
    GDALDataset * pDSOld = (GDALDataset*) GDALOpen(m_sFilePath, GA_ReadOnly);
    if (pDSOld  == NULL)
        return INPUT_FILE_ERROR;

    GDALRasterBand * pRBInput = pDSOld->GetRasterBand(1);

    /* Create the new dataset. Determine the driver from the output file extension.
     * Enforce LZW compression for TIFs. The predictor 3 is used for floating point prediction.
     * Not using this value defaults the LZW to prediction to 1 which causes striping.
     */
    char **papszOptions = NULL;
    GDALDriver * pDR = NULL;
    std::string psDR = "";
    const char * pSuffix = ExtractFileExt(pOutputRaster);
    if (pSuffix == NULL)
        return OUTPUT_FILE_EXT_ERROR;
    else
    {
        if (strcmp(pSuffix, ".tif") == 0)
        {
            psDR = "GTiff";
            pDR = GetGDALDriverManager()->GetDriverByName(psDR.c_str());
            papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "LZW");
            //papszOptions = CSLSetNameValue(papszOptions, "PREDICTOR", "3");
        }
        else if (strcmp(pSuffix, ".img") == 0){
            psDR = "HFA";
            pDR = GetGDALDriverManager()->GetDriverByName(psDR.c_str());
        }
        else
            return OUTPUT_UNHANDLED_DRIVER;
    }

    double dNewCellHeight = (*dNewCellSize) * -1;
    RasterMeta OutputMeta(fTop, fLeft, nRows, nCols, &dNewCellHeight,
                          dNewCellSize, GetNoDataValuePtr(), psDR.c_str(), GetGDALDataType(), GetProjectionRef() );

    //const char * pC = pDR->GetDescription();
    GDALDataset * pDSOutput = pDR->Create(pOutputRaster, nCols, nRows, 1, *GetGDALDataType(), papszOptions);
    CSLDestroy( papszOptions );
    if (pDSOutput == NULL)
        return OUTPUT_FILE_ERROR;

    if (HasNoDataValue())
    {
        CPLErr er = pDSOutput->GetRasterBand(1)->SetNoDataValue(GetNoDataValue());
        if (er == CE_Failure || er == CE_Fatal)
            return OUTPUT_NO_DATA_ERROR;
    }

    pDSOutput->SetGeoTransform(OutputMeta.GetGeoTransform());
    pDSOutput->SetProjection(pDSOld->GetProjectionRef());

    int nInputCols = pRBInput->GetXSize();
    int nInputRows = pRBInput->GetYSize();

    double * pInputLine = (double *) CPLMalloc(sizeof(double)*nInputCols);
    double * pOutputLine = (double *) CPLMalloc(sizeof(double)*pDSOutput->GetRasterBand(1)->GetXSize());

    int nRowTrans = GetRowTranslation(&OutputMeta);
    int nColTrans = GetColTranslation(&OutputMeta);

    /*
    * Loop over the raster rows. Note that geographic coordinate origin is bottom left. But
    * the GDAL image anchor is top left. The cell height is negative.
    *
    * The loop is over the centres of the output raster cells. Two rows are read from the
    * input raster. The line just above the output cell and the line just below. The line
    * just above is called the "anchor" row.
    */

    int nOldRow, nOldCol;
    int i, j;

    for (i = 0; i < nRows; i++)
    {
        nOldRow = i - nRowTrans;

        if (nOldRow >= 0 && nOldRow < nInputRows)
        {
            pRBInput->RasterIO(GF_Read, 0, nOldRow, nInputCols, 1, pInputLine, nInputCols, 1, GDT_Float64, 0, 0);

            for (j = 0; j < nCols; j++)
            {
                nOldCol = j + nColTrans;

                if (nOldCol >=0 && nOldCol < nInputCols)
                {
                    pOutputLine[j] = pInputLine[nOldCol];
                }
                else
                {
                    if (HasNoDataValue()) {
                        pOutputLine[j] = GetNoDataValue();
                    }
                    else
                    {
                        pOutputLine[j] = 0;
                    }
                }
            }
        }
        else
        {
            // Outside the bounds of the input image. Loop over all cells in current output row and set to NoData.
            for (j = 0; j < nCols; j++)
            {
                pOutputLine[j] = GetNoDataValue();
            }
        }
        pDSOutput->GetRasterBand(1)->RasterIO(GF_Write, 0, i,
                                              pDSOutput->GetRasterBand(1)->GetXSize(), 1,
                                              pOutputLine,
                                              pDSOutput->GetRasterBand(1)->GetXSize(), 1,
                                              GDT_Float64, 0, 0);
    }

    CPLFree(pInputLine);
    CPLFree(pOutputLine);

    CalculateStats(pDSOutput->GetRasterBand(1));

    GDALClose(pDSOld);
    GDALClose(pDSOutput);

    GDALDumpOpenDatasets(stderr);


    return PROCESS_OK;
}
CPLErr GDALApplyVSGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
                                           void * pData )
{
    GDALApplyVSGDataset* poGDS = reinterpret_cast<GDALApplyVSGDataset*>(poDS);

    const int nXOff = nBlockXOff * nBlockXSize;
    const int nReqXSize = ( nXOff > nRasterXSize - nBlockXSize ) ?
                                    nRasterXSize - nXOff : nBlockXSize;
    const int nYOff = nBlockYOff * nBlockYSize;
    const int nReqYSize = ( nYOff > nRasterYSize - nBlockYSize ) ?
                                    nRasterYSize - nYOff : nBlockYSize;

    CPLErr eErr =
        poGDS->m_poSrcDataset->GetRasterBand(1)->RasterIO(GF_Read,
                                                    nXOff, nYOff,
                                                    nReqXSize, nReqYSize,
                                                    m_pafSrcData,
                                                    nReqXSize, nReqYSize,
                                                    GDT_Float32,
                                                    sizeof(float),
                                                    nBlockXSize * sizeof(float),
                                                    nullptr);
    if( eErr == CE_None )
        eErr =  poGDS->m_poReprojectedGrid->GetRasterBand(1)->RasterIO(GF_Read,
                                                    nXOff, nYOff,
                                                    nReqXSize, nReqYSize,
                                                    m_pafGridData,
                                                    nReqXSize, nReqYSize,
                                                    GDT_Float32,
                                                    sizeof(float),
                                                    nBlockXSize * sizeof(float),
                                                    nullptr);
    if( eErr == CE_None )
    {
        const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
        int bHasNoData = FALSE;
        float fNoDataValue = static_cast<float>(GetNoDataValue(&bHasNoData));
        for( int iY = 0; iY < nReqYSize; iY++ )
        {
            for( int iX = 0; iX < nReqXSize; iX ++ )
            {
                const float fSrcVal = m_pafSrcData[iY * nBlockXSize + iX];
                const float fGridVal = m_pafGridData[iY * nBlockXSize + iX];
                if( bHasNoData && fSrcVal == fNoDataValue )
                {
                }
                else if( CPLIsInf(fGridVal) )
                {
                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Missing vertical grid value at source (%d,%d)",
                             nXOff + iX, nYOff + iY);
                    return CE_Failure;
                }
                else if( poGDS->m_bInverse )
                {
                    m_pafSrcData[iY * nBlockXSize + iX] = static_cast<float>(
                        (fSrcVal * poGDS->m_dfSrcUnitToMeter - fGridVal) / 
                                                poGDS->m_dfDstUnitToMeter);
                }
                else
                {
                    m_pafSrcData[iY * nBlockXSize + iX] = static_cast<float>(
                        (fSrcVal * poGDS->m_dfSrcUnitToMeter + fGridVal) / 
                                                poGDS->m_dfDstUnitToMeter);
                }
            }
            GDALCopyWords( m_pafSrcData + iY * nBlockXSize,
                                GDT_Float32, sizeof(float),
                           static_cast<GByte*>(pData) + iY * nBlockXSize *
                                nDTSize, eDataType, nDTSize,
                           nReqXSize );
        }
    }

    return eErr;
}