Exemple #1
0
static CPLErr SqrtPixelFunc( void **papoSources, int nSources, void *pData,
                             int nXSize, int nYSize,
                             GDALDataType eSrcType, GDALDataType eBufType,
                             int nPixelSpace, int nLineSpace )
{
    /* ---- Init ---- */
    if( nSources != 1 ) return CE_Failure;
    if( GDALDataTypeIsComplex( eSrcType ) ) return CE_Failure;

    /* ---- Set pixels ---- */
    for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
        for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
            // Source raster pixels may be obtained with SRCVAL macro.
            const double dfPixVal =
                sqrt( SRCVAL(papoSources[0], eSrcType, ii) );

            GDALCopyWords(
                &dfPixVal, GDT_Float64, 0,
                static_cast<GByte *>(pData) + nLineSpace * iLine +
                iCol * nPixelSpace, eBufType, nPixelSpace, 1);
        }
    }

    /* ---- Return success ---- */
    return CE_None;
}  // SqrtPixelFunc
CPLErr PowPixelFuncHelper(void **papoSources, int nSources, void *pData,
                          int nXSize, int nYSize,
                          GDALDataType eSrcType, GDALDataType eBufType,
                          int nPixelSpace, int nLineSpace,
                          double base, double fact)
{
    int iLine, iCol, ii;
    double dfPixVal;

    /* ---- Init ---- */
    if (nSources != 1) return CE_Failure;
    if (GDALDataTypeIsComplex( eSrcType )) return CE_Failure;

    /* ---- Set pixels ---- */
    for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
        for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

            /* Source raster pixels may be obtained with SRCVAL macro */
            dfPixVal = SRCVAL(papoSources[0], eSrcType, ii);
            dfPixVal = pow(base, dfPixVal / fact);

            GDALCopyWords(&dfPixVal, GDT_Float64, 0,
                          ((GByte *)pData) + nLineSpace * iLine +
                          iCol * nPixelSpace, eBufType, nPixelSpace, 1);
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* PowPixelFuncHelper */
CPLErr GFFRasterBand::IReadBlock( int /* nBlockXOff */ ,
                                  int nBlockYOff,
                                  void *pImage )
{
    GFFDataset *poGDS = (GFFDataset *)poDS;
    long nOffset = poGDS->nLength;

    VSIFSeekL(poGDS->fp, nOffset + (poGDS->GetRasterXSize() * nBlockYOff * (nSampleSize)),SEEK_SET);

    /* Ingest entire range line */
    if (VSIFReadL(pImage,nRasterBandMemory,1,poGDS->fp) != 1)
        return CE_Failure;

#if defined(CPL_MSB)
    if( GDALDataTypeIsComplex( eDataType ) )
    {
        int nWordSize = GDALGetDataTypeSize(eDataType)/16;
        GDALSwapWords( pImage, nWordSize, nBlockXSize, 2*nWordSize );
        GDALSwapWords( ((GByte *) pImage)+nWordSize,
                        nWordSize, nBlockXSize, 2*nWordSize );
    }
#endif

    return CE_None;
}
Exemple #4
0
 // Test GDALDataTypeUnion()
 template<> template<> void object::test<6>()
 {
     for(int i=GDT_Byte;i<GDT_TypeCount;i++)
     {
         for(int j=GDT_Byte;j<GDT_TypeCount;j++)
         {
             GDALDataType eDT1 = static_cast<GDALDataType>(i);
             GDALDataType eDT2 = static_cast<GDALDataType>(j);
             GDALDataType eDT = GDALDataTypeUnion(eDT1,eDT2 );
             ensure( eDT == GDALDataTypeUnion(eDT2,eDT1) );
             ensure( GDALGetDataTypeSize(eDT) >= GDALGetDataTypeSize(eDT1) );
             ensure( GDALGetDataTypeSize(eDT) >= GDALGetDataTypeSize(eDT2) );
             ensure( (GDALDataTypeIsComplex(eDT) && (GDALDataTypeIsComplex(eDT1) || GDALDataTypeIsComplex(eDT2))) ||
                     (!(GDALDataTypeIsComplex(eDT) && !GDALDataTypeIsComplex(eDT1) && !GDALDataTypeIsComplex(eDT2))) );
         }
     }
 }
Exemple #5
0
static CPLErr SumPixelFunc(void **papoSources, int nSources, void *pData,
                    int nXSize, int nYSize,
                    GDALDataType eSrcType, GDALDataType eBufType,
                    int nPixelSpace, int nLineSpace)
{
    /* ---- Init ---- */
    if( nSources < 2 ) return CE_Failure;

    /* ---- Set pixels ---- */
    if( GDALDataTypeIsComplex( eSrcType ) )
    {
        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;

        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                double adfSum[2] = { 0.0, 0.0 };

                for( int iSrc = 0; iSrc < nSources; ++iSrc ) {
                    const void * const pReal = papoSources[iSrc];
                    const void * const pImag =
                        static_cast<const GByte *>(pReal) + nOffset;

                    // Source raster pixels may be obtained with SRCVAL macro.
                    adfSum[0] += SRCVAL(pReal, eSrcType, ii);
                    adfSum[1] += SRCVAL(pImag, eSrcType, ii);
                }

                GDALCopyWords(
                    adfSum, GDT_CFloat64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }
    else
    {
        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                double dfSum = 0;  // Not complex.

                for( int iSrc = 0; iSrc < nSources; ++iSrc ) {
                    // Source raster pixels may be obtained with SRCVAL macro.
                    dfSum += SRCVAL(papoSources[iSrc], eSrcType, ii);
                }

                GDALCopyWords(
                    &dfSum, GDT_Float64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* SumPixelFunc */
CPLErr CMulPixelFunc(void **papoSources, int nSources, void *pData,
                     int nXSize, int nYSize,
                     GDALDataType eSrcType, GDALDataType eBufType,
                     int nPixelSpace, int nLineSpace)
{
    int ii, iLine, iCol;

    /* ---- Init ---- */
    if (nSources != 2) return CE_Failure;

    /* ---- Set pixels ---- */
    if (GDALDataTypeIsComplex( eSrcType ))
    {
        double adfPixVal[2], dfReal0, dfImag0, dfReal1, dfImag1;

        int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2;
        void *pReal0 = papoSources[0];
        void *pImag0 = ((GByte *)papoSources[0]) + nOffset;
        void *pReal1 = papoSources[1];
        void *pImag1 = ((GByte *)papoSources[1]) + nOffset;

        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfReal0 = SRCVAL(pReal0, eSrcType, ii);
                dfReal1 = SRCVAL(pReal1, eSrcType, ii);
                dfImag0 = SRCVAL(pImag0, eSrcType, ii);
                dfImag1 = SRCVAL(pImag1, eSrcType, ii);
                adfPixVal[0]  = dfReal0 * dfReal1 + dfImag0 * dfImag1;
                adfPixVal[1]  = dfReal1 * dfImag0 - dfReal0 * dfImag1;

                GDALCopyWords(adfPixVal, GDT_CFloat64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    } else {
        /* non complex */
        double adfPixVal[2] = {0, 0};

        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                adfPixVal[0] = SRCVAL(papoSources[0], eSrcType, ii)
                             * SRCVAL(papoSources[1], eSrcType, ii);

                GDALCopyWords(adfPixVal, GDT_CFloat64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* CMulPixelFunc */
Exemple #7
0
static CPLErr DiffPixelFunc( void **papoSources, int nSources, void *pData,
                             int nXSize, int nYSize,
                             GDALDataType eSrcType, GDALDataType eBufType,
                             int nPixelSpace, int nLineSpace)
{
    /* ---- Init ---- */
    if( nSources != 2 ) return CE_Failure;

    if( GDALDataTypeIsComplex( eSrcType ) )
    {
        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
        const void * const pReal0 = papoSources[0];
        const void * const pImag0 =
            static_cast<GByte *>(papoSources[0]) + nOffset;
        const void * const pReal1 = papoSources[1];
        const void * const pImag1 =
            static_cast<GByte *>(papoSources[1]) + nOffset;

        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                // Source raster pixels may be obtained with SRCVAL macro.
                double adfPixVal[2] = {
                    SRCVAL(pReal0, eSrcType, ii)
                    - SRCVAL(pReal1, eSrcType, ii),
                    SRCVAL(pImag0, eSrcType, ii)
                    - SRCVAL(pImag1, eSrcType, ii)
                };

                GDALCopyWords(
                    adfPixVal, GDT_CFloat64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
            }
        }
    }
    else
    {
        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                // Source raster pixels may be obtained with SRCVAL macro.
                // Not complex.
                const double dfPixVal = SRCVAL(papoSources[0], eSrcType, ii)
                    - SRCVAL(papoSources[1], eSrcType, ii);

                GDALCopyWords(
                    &dfPixVal, GDT_Float64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
}  // DiffPixelFunc
Exemple #8
0
static CPLErr Log10PixelFuncHelper( void **papoSources, int nSources,
                                    void *pData,
                                    int nXSize, int nYSize,
                                    GDALDataType eSrcType,
                                    GDALDataType eBufType,
                                    int nPixelSpace, int nLineSpace,
                                    double fact )
{
    /* ---- Init ---- */
    if( nSources != 1 ) return CE_Failure;

    if( GDALDataTypeIsComplex( eSrcType ) )
    {
        // Complex input datatype.
        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
        const void * const pReal = papoSources[0];
        const void * const pImag =
            static_cast<GByte *>(papoSources[0]) + nOffset;

        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                // Source raster pixels may be obtained with SRCVAL macro.
                const double dfReal = SRCVAL(pReal, eSrcType, ii);
                const double dfImag = SRCVAL(pImag, eSrcType, ii);

                const double dfPixVal =
                    fact * log10( sqrt( dfReal * dfReal + dfImag * dfImag ) );

                GDALCopyWords(
                    &dfPixVal, GDT_Float64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
            }
        }
    }
    else
    {
        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                // Source raster pixels may be obtained with SRCVAL macro.
                const double dfPixVal =
                    fact * log10( fabs(
                        SRCVAL(papoSources[0], eSrcType, ii) ) );

                GDALCopyWords(
                    &dfPixVal, GDT_Float64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
}  // Log10PixelFuncHelper
CPLErr InvPixelFunc(void **papoSources, int nSources, void *pData,
                    int nXSize, int nYSize,
                    GDALDataType eSrcType, GDALDataType eBufType,
                    int nPixelSpace, int nLineSpace)
{
    int iLine, iCol, ii;

    /* ---- Init ---- */
    if (nSources != 1) return CE_Failure;

    /* ---- Set pixels ---- */
    if (GDALDataTypeIsComplex( eSrcType ))
    {
        double adfPixVal[2], dfReal, dfImag, dfAux;

        int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2;
        void *pReal = papoSources[0];
        void *pImag = ((GByte *)papoSources[0]) + nOffset;

        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfReal = SRCVAL(pReal, eSrcType, ii);
                dfImag = SRCVAL(pImag, eSrcType, ii);
                dfAux = dfReal * dfReal + dfImag * dfImag;
                adfPixVal[0]  = +dfReal / dfAux;
                adfPixVal[1]  = -dfImag / dfAux;

                GDALCopyWords(adfPixVal, GDT_CFloat64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    } else {
        /* non complex */
        double dfPixVal;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfPixVal = 1. / SRCVAL(papoSources[0], eSrcType, ii);

                GDALCopyWords(&dfPixVal, GDT_Float64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* InvPixelFunc */
CPLErr Log10PixelFunc(void **papoSources, int nSources, void *pData,
                      int nXSize, int nYSize,
                      GDALDataType eSrcType, GDALDataType eBufType,
                      int nPixelSpace, int nLineSpace)
{
    int ii, iLine, iCol;

    /* ---- Init ---- */
    if (nSources != 1) return CE_Failure;

    if (GDALDataTypeIsComplex( eSrcType ))
    {
        /* complex input datatype */
        double dfReal, dfImag, dfPixVal;
        int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2;
        void *pReal = papoSources[0];
        void *pImag = ((GByte *)papoSources[0]) + nOffset;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfReal = SRCVAL(pReal, eSrcType, ii);
                dfImag = SRCVAL(pImag, eSrcType, ii);

                dfPixVal = log10( dfReal * dfReal + dfImag * dfImag );

                GDALCopyWords(&dfPixVal, GDT_Float64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    } else {
        double dfPixVal;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfPixVal = SRCVAL(papoSources[0], eSrcType, ii);
                dfPixVal = log10( abs( dfPixVal ) );

                GDALCopyWords(&dfPixVal, GDT_Float64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* Log10PixelFunc */
Exemple #11
0
static CPLErr ConjPixelFunc( void **papoSources, int nSources, void *pData,
                             int nXSize, int nYSize,
                             GDALDataType eSrcType, GDALDataType eBufType,
                             int nPixelSpace, int nLineSpace )
{
    /* ---- Init ---- */
    if( nSources != 1 ) return CE_Failure;

    if( GDALDataTypeIsComplex( eSrcType ) && GDALDataTypeIsComplex( eBufType ) )
    {
        const int nOffset = GDALGetDataTypeSizeBytes( eSrcType ) / 2;
        const void * const pReal = papoSources[0];
        const void * const pImag =
            static_cast<GByte *>(papoSources[0]) + nOffset;

        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                // Source raster pixels may be obtained with SRCVAL macro.
                const double adfPixVal[2] = {
                    +SRCVAL(pReal, eSrcType, ii),  // re
                    -SRCVAL(pImag, eSrcType, ii)  // im
                };

                GDALCopyWords(
                    adfPixVal, GDT_CFloat64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
            }
        }
    }
    else
    {
        // No complex data type.
        return RealPixelFunc(papoSources, nSources, pData, nXSize, nYSize,
                             eSrcType, eBufType, nPixelSpace, nLineSpace);
    }

    /* ---- Return success ---- */
    return CE_None;
}  // ConjPixelFunc
Exemple #12
0
static CPLErr PhasePixelFunc( void **papoSources, int nSources, void *pData,
                              int nXSize, int nYSize,
                              GDALDataType eSrcType, GDALDataType eBufType,
                              int nPixelSpace, int nLineSpace )
{
    /* ---- Init ---- */
    if( nSources != 1 ) return CE_Failure;

    if( GDALDataTypeIsComplex( eSrcType ) )
    {
        const void * const pReal = papoSources[0];
        const void * const pImag = static_cast<GByte *>(papoSources[0])
            + GDALGetDataTypeSizeBytes( eSrcType ) / 2;

        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                // Source raster pixels may be obtained with SRCVAL macro.
                const double dfReal = SRCVAL(pReal, eSrcType, ii);
                const double dfImag = SRCVAL(pImag, eSrcType, ii);

                const double dfPixVal = atan2(dfImag, dfReal);

                GDALCopyWords(
                    &dfPixVal, GDT_Float64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
            }
        }
    }
    else
    {
        /* ---- Set pixels ---- */
        for( int iLine = 0, ii = 0; iLine < nYSize; ++iLine ) {
            for( int iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                const void * const pReal = papoSources[0];

                // Source raster pixels may be obtained with SRCVAL macro.
                const double dfReal = SRCVAL(pReal, eSrcType, ii);
                const double dfPixVal = (dfReal < 0) ? M_PI : 0.0;

                GDALCopyWords(
                    &dfPixVal, GDT_Float64, 0,
                    static_cast<GByte *>(pData) + nLineSpace * iLine +
                    iCol * nPixelSpace, eBufType, nPixelSpace, 1 );
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
}  // PhasePixelFunc
CPLErr ConjPixelFunc(void **papoSources, int nSources, void *pData,
                     int nXSize, int nYSize,
                     GDALDataType eSrcType, GDALDataType eBufType,
                     int nPixelSpace, int nLineSpace)
{
    /* ---- Init ---- */
    if (nSources != 1) return CE_Failure;

    if (GDALDataTypeIsComplex( eSrcType ) && GDALDataTypeIsComplex( eBufType ))
    {
        int iLine, iCol, ii;
        double adfPixVal[2];
        int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2;
        void *pReal = papoSources[0];
        void *pImag = ((GByte *)papoSources[0]) + nOffset;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                adfPixVal[0] = +SRCVAL(pReal, eSrcType, ii); /* re */
                adfPixVal[1] = -SRCVAL(pImag, eSrcType, ii); /* im */

                GDALCopyWords(adfPixVal, GDT_CFloat64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    } else {
        /* no complex data type */
        return RealPixelFunc(papoSources, nSources, pData, nXSize, nYSize,
                             eSrcType, eBufType, nPixelSpace, nLineSpace);
    }

    /* ---- Return success ---- */
    return CE_None;
} /* ConjPixelFunc */
Exemple #14
0
CPLErr RawRasterBand::AccessBlock( vsi_l_offset nBlockOff, int nBlockSize,
                                   void * pData )
{
    int         nBytesActuallyRead;

/* -------------------------------------------------------------------- */
/*      Seek to the right block.                                        */
/* -------------------------------------------------------------------- */
    if( Seek( nBlockOff, SEEK_SET ) == -1 )
    {
        memset( pData, 0, nBlockSize );
        return CE_None;
    }

/* -------------------------------------------------------------------- */
/*      Read the block.                                                 */
/* -------------------------------------------------------------------- */
    nBytesActuallyRead = Read( pData, 1, nBlockSize );
    if( nBytesActuallyRead < nBlockSize )
    {

        memset( ((GByte *) pData) + nBytesActuallyRead, 
                0, nBlockSize - nBytesActuallyRead );
        return CE_None;
    }

/* -------------------------------------------------------------------- */
/*      Byte swap the interesting data, if required.                    */
/* -------------------------------------------------------------------- */
    if( !bNativeOrder && eDataType != GDT_Byte )
    {
        if( GDALDataTypeIsComplex( eDataType ) )
        {
            int nWordSize;

            nWordSize = GDALGetDataTypeSize(eDataType)/16;
            GDALSwapWords( pData, nWordSize, nBlockSize / nPixelOffset,
                           nPixelOffset );
            GDALSwapWords( ((GByte *) pData) + nWordSize, 
                           nWordSize, nBlockSize / nPixelOffset, nPixelOffset );
        }
        else
            GDALSwapWords( pData, GDALGetDataTypeSize(eDataType) / 8,
                           nBlockSize / nPixelOffset, nPixelOffset );
    }

    return CE_None;
}
Exemple #15
0
Gdal::Band::Band(Gdal& owner_, GDALRasterBand *band_)
: owner(owner_), band(band_)
{
	size.cx = band->GetXSize();
	size.cy = band->GetYSize();
	band->GetBlockSize(&block_size.cx, &block_size.cy);
	block_count = idivceil(size, block_size);
	type = band->GetRasterDataType();
	pixel_bytes = (GDALGetDataTypeSize(type) + 7) >> 3;
	complex = GDALDataTypeIsComplex(type);
	int nodata_flag;
	nodata_value = band->GetNoDataValue(&nodata_flag);
	is_nodata = !!nodata_flag;
	is_stat = false;
	nodata_int = fround(nodata_value);
	blocks.Alloc(block_count.cx * block_count.cy);
}
Exemple #16
0
static CPLErr ImagPixelFunc( void **papoSources, int nSources, void *pData,
                             int nXSize, int nYSize,
                             GDALDataType eSrcType, GDALDataType eBufType,
                             int nPixelSpace, int nLineSpace )
{
    /* ---- Init ---- */
    if( nSources != 1 ) return CE_Failure;

    if( GDALDataTypeIsComplex( eSrcType ) )
    {
        const GDALDataType eSrcBaseType = GDALGetNonComplexDataType( eSrcType );
        const int nPixelSpaceSrc = GDALGetDataTypeSizeBytes( eSrcType );
        const int nLineSpaceSrc = nPixelSpaceSrc * nXSize;

        const void * const pImag = static_cast<GByte *>(papoSources[0])
            + GDALGetDataTypeSizeBytes( eSrcType ) / 2;

        /* ---- Set pixels ---- */
        for( int iLine = 0; iLine < nYSize; ++iLine )
        {
            GDALCopyWords(
                static_cast<const GByte *>(pImag) + nLineSpaceSrc * iLine,
                eSrcBaseType, nPixelSpaceSrc,
                static_cast<GByte *>(pData) + nLineSpace * iLine,
                eBufType, nPixelSpace, nXSize );
        }
    }
    else
    {
        const double dfImag = 0;

        /* ---- Set pixels ---- */
        for( int iLine = 0; iLine < nYSize; ++iLine )
        {
            // Always copy from the same location.
            GDALCopyWords(
                &dfImag, eSrcType, 0,
                static_cast<GByte *>(pData) + nLineSpace * iLine,
                eBufType, nPixelSpace, nXSize);
        }
    }

    /* ---- Return success ---- */
    return CE_None;
}  // ImagPixelFunc
CPLErr ImagPixelFunc(void **papoSources, int nSources, void *pData,
                     int nXSize, int nYSize,
                     GDALDataType eSrcType, GDALDataType eBufType,
                     int nPixelSpace, int nLineSpace)
{
    int iLine;

    /* ---- Init ---- */
    if (nSources != 1) return CE_Failure;

    if (GDALDataTypeIsComplex( eSrcType ))
    {
        int nPixelSpaceSrc = GDALGetDataTypeSize( eSrcType ) / 8;
        int nLineSpaceSrc = nPixelSpaceSrc * nXSize;

        void* pImag = ((GByte *)papoSources[0])
                    + GDALGetDataTypeSize( eSrcType ) / 8 / 2;

        /* ---- Set pixels ---- */
        for( iLine = 0; iLine < nYSize; ++iLine ) {
            GDALCopyWords(((GByte *)pImag) + nLineSpaceSrc * iLine,
                          eSrcType, nPixelSpaceSrc,
                          ((GByte *)pData) + nLineSpace * iLine,
                          eBufType, nPixelSpace, nXSize);
        }
    } else {
        double dfImag = 0;

        /* ---- Set pixels ---- */
        for( iLine = 0; iLine < nYSize; ++iLine ) {
            /* always copy from the same location */
            GDALCopyWords(&dfImag, eSrcType, 0,
                          ((GByte *)pData) + nLineSpace * iLine,
                          eBufType, nPixelSpace, nXSize);
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* ImagPixelFunc */
Exemple #18
0
CPLErr
GTIFFBuildOverviews( const char * pszFilename,
                     int nBands, GDALRasterBand **papoBandList,
                     int nOverviews, int * panOverviewList,
                     const char * pszResampling,
                     GDALProgressFunc pfnProgress, void * pProgressData )

{
    if( nBands == 0 || nOverviews == 0 )
        return CE_None;

    if( !GTiffOneTimeInit() )
        return CE_Failure;

    TIFF *hOTIFF = nullptr;
    int nBitsPerPixel = 0;
    int nCompression = COMPRESSION_NONE;
    int nPhotometric = 0;
    int nSampleFormat = 0;
    int nPlanarConfig = 0;
    int iOverview = 0;
    int nXSize = 0;
    int nYSize = 0;

/* -------------------------------------------------------------------- */
/*      Verify that the list of bands is suitable for emitting in       */
/*      TIFF file.                                                      */
/* -------------------------------------------------------------------- */
    for( int iBand = 0; iBand < nBands; iBand++ )
    {
        int nBandBits = 0;
        int nBandFormat = 0;
        GDALRasterBand *hBand = papoBandList[iBand];

        switch( hBand->GetRasterDataType() )
        {
          case GDT_Byte:
            nBandBits = 8;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_UInt16:
            nBandBits = 16;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_Int16:
            nBandBits = 16;
            nBandFormat = SAMPLEFORMAT_INT;
            break;

          case GDT_UInt32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_Int32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_INT;
            break;

          case GDT_Float32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_IEEEFP;
            break;

          case GDT_Float64:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_IEEEFP;
            break;

          case GDT_CInt16:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_COMPLEXINT;
            break;

          case GDT_CInt32:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_COMPLEXINT;
            break;

          case GDT_CFloat32:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
            break;

          case GDT_CFloat64:
            nBandBits = 128;
            nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
            break;

          default:
            CPLAssert( false );
            return CE_Failure;
        }

        if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) )
        {
            nBandBits =
                atoi(hBand->GetMetadataItem("NBITS", "IMAGE_STRUCTURE"));

            if( nBandBits == 1
                && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
                nBandBits = 8;
        }

        if( iBand == 0 )
        {
            nBitsPerPixel = nBandBits;
            nSampleFormat = nBandFormat;
            nXSize = hBand->GetXSize();
            nYSize = hBand->GetYSize();
        }
        else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat )
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "GTIFFBuildOverviews() doesn't support a mixture of band"
                      " data types." );
            return CE_Failure;
        }
        else if( hBand->GetColorTable() != nullptr )
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "GTIFFBuildOverviews() doesn't support building"
                      " overviews of multiple colormapped bands." );
            return CE_Failure;
        }
        else if( hBand->GetXSize() != nXSize
                 || hBand->GetYSize() != nYSize )
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "GTIFFBuildOverviews() doesn't support building"
                      " overviews of different sized bands." );
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Use specified compression method.                               */
/* -------------------------------------------------------------------- */
    const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", nullptr );

    if( pszCompress != nullptr && pszCompress[0] != '\0' )
    {
        nCompression =
            GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW");
        if( nCompression < 0 )
            return CE_Failure;
    }

    if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 )
    {
        if( nBitsPerPixel > 16 )
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "GTIFFBuildOverviews() doesn't support building"
                      " JPEG compressed overviews of nBitsPerPixel > 16." );
            return CE_Failure;
        }

        nBitsPerPixel = 12;
    }

/* -------------------------------------------------------------------- */
/*      Figure out the planar configuration to use.                     */
/* -------------------------------------------------------------------- */
    if( nBands == 1 )
        nPlanarConfig = PLANARCONFIG_CONTIG;
    else
        nPlanarConfig = PLANARCONFIG_SEPARATE;

    bool bSourceIsPixelInterleaved = false;
    bool bSourceIsJPEG2000 = false;
    if( nBands > 1 )
    {
        GDALDataset* poSrcDS = papoBandList[0]->GetDataset();
        if( poSrcDS )
        {
            const char* pszSrcInterleave = poSrcDS->GetMetadataItem("INTERLEAVE",
                                                                "IMAGE_STRUCTURE");
            if( pszSrcInterleave && EQUAL(pszSrcInterleave, "PIXEL") )
            {
                bSourceIsPixelInterleaved = true;
            }
        }

        const char* pszSrcCompression = papoBandList[0]->GetMetadataItem("COMPRESSION",
                                                                "IMAGE_STRUCTURE");
        if( pszSrcCompression )
        {
            bSourceIsJPEG2000 = EQUAL(pszSrcCompression, "JPEG2000");
        }
        if( bSourceIsPixelInterleaved && bSourceIsJPEG2000 )
        {
            nPlanarConfig = PLANARCONFIG_CONTIG;
        }
    }

    const char* pszInterleave =
        CPLGetConfigOption( "INTERLEAVE_OVERVIEW", nullptr );
    if( pszInterleave != nullptr && pszInterleave[0] != '\0' )
    {
        if( EQUAL( pszInterleave, "PIXEL" ) )
            nPlanarConfig = PLANARCONFIG_CONTIG;
        else if( EQUAL( pszInterleave, "BAND" ) )
            nPlanarConfig = PLANARCONFIG_SEPARATE;
        else
        {
            CPLError(
                CE_Failure, CPLE_AppDefined,
                "INTERLEAVE_OVERVIEW=%s unsupported, "
                "value must be PIXEL or BAND. ignoring",
                pszInterleave );
        }
    }

/* -------------------------------------------------------------------- */
/*      Figure out the photometric interpretation to use.               */
/* -------------------------------------------------------------------- */
    if( nBands == 3 )
        nPhotometric = PHOTOMETRIC_RGB;
    else if( papoBandList[0]->GetColorTable() != nullptr
             && !STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") )
    {
        nPhotometric = PHOTOMETRIC_PALETTE;
        // Should set the colormap up at this point too!
    }
    else if( nBands >= 3 &&
             papoBandList[0]->GetColorInterpretation() == GCI_RedBand &&
             papoBandList[1]->GetColorInterpretation() == GCI_GreenBand &&
             papoBandList[2]->GetColorInterpretation() == GCI_BlueBand )
    {
        nPhotometric = PHOTOMETRIC_RGB;
    }
    else
        nPhotometric = PHOTOMETRIC_MINISBLACK;

    const char* pszPhotometric =
        CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", nullptr );
    if( pszPhotometric != nullptr && pszPhotometric[0] != '\0' )
    {
        if( EQUAL( pszPhotometric, "MINISBLACK" ) )
            nPhotometric = PHOTOMETRIC_MINISBLACK;
        else if( EQUAL( pszPhotometric, "MINISWHITE" ) )
            nPhotometric = PHOTOMETRIC_MINISWHITE;
        else if( EQUAL( pszPhotometric, "RGB" ))
        {
            nPhotometric = PHOTOMETRIC_RGB;
        }
        else if( EQUAL( pszPhotometric, "CMYK" ))
        {
            nPhotometric = PHOTOMETRIC_SEPARATED;
        }
        else if( EQUAL( pszPhotometric, "YCBCR" ))
        {
            nPhotometric = PHOTOMETRIC_YCBCR;

            // Because of subsampling, setting YCBCR without JPEG compression
            // leads to a crash currently. Would need to make
            // GTiffRasterBand::IWriteBlock() aware of subsampling so that it
            // doesn't overrun buffer size returned by libtiff.
            if( nCompression != COMPRESSION_JPEG )
            {
                CPLError(
                    CE_Failure, CPLE_NotSupported,
                    "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires "
                    "COMPRESS_OVERVIEW=JPEG" );
                return CE_Failure;
            }

            if( pszInterleave != nullptr &&
                pszInterleave[0] != '\0' &&
                nPlanarConfig == PLANARCONFIG_SEPARATE )
            {
                CPLError(
                    CE_Failure, CPLE_NotSupported,
                    "PHOTOMETRIC_OVERVIEW=YCBCR requires "
                    "INTERLEAVE_OVERVIEW=PIXEL" );
                return CE_Failure;
            }
            else
            {
                nPlanarConfig = PLANARCONFIG_CONTIG;
            }

            // YCBCR strictly requires 3 bands. Not less, not more
            // Issue an explicit error message as libtiff one is a bit cryptic:
            // JPEGLib:Bogus input colorspace.
            if( nBands != 3 )
            {
                CPLError(
                    CE_Failure, CPLE_NotSupported,
                    "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster "
                    "with only 3 bands (RGB)" );
                return CE_Failure;
            }
        }
        else if( EQUAL( pszPhotometric, "CIELAB" ))
        {
            nPhotometric = PHOTOMETRIC_CIELAB;
        }
        else if( EQUAL( pszPhotometric, "ICCLAB" ))
        {
            nPhotometric = PHOTOMETRIC_ICCLAB;
        }
        else if( EQUAL( pszPhotometric, "ITULAB" ))
        {
            nPhotometric = PHOTOMETRIC_ITULAB;
        }
        else
        {
            CPLError(
                CE_Warning, CPLE_IllegalArg,
                "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.",
                pszPhotometric );
        }
    }

/* -------------------------------------------------------------------- */
/*      Figure out the predictor value to use.                          */
/* -------------------------------------------------------------------- */
    int nPredictor = PREDICTOR_NONE;
    if( nCompression == COMPRESSION_LZW ||
        nCompression == COMPRESSION_ADOBE_DEFLATE )
    {
        const char* pszPredictor =
            CPLGetConfigOption( "PREDICTOR_OVERVIEW", nullptr );
        if( pszPredictor != nullptr )
        {
            nPredictor = atoi( pszPredictor );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create the file, if it does not already exist.                  */
/* -------------------------------------------------------------------- */
    VSIStatBufL sStatBuf;
    VSILFILE* fpL = nullptr;

    if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
    {
    /* -------------------------------------------------------------------- */
    /*      Compute the uncompressed size.                                  */
    /* -------------------------------------------------------------------- */
        double dfUncompressedOverviewSize = 0;
        int nDataTypeSize =
            GDALGetDataTypeSizeBytes(papoBandList[0]->GetRasterDataType());

        for( iOverview = 0; iOverview < nOverviews; iOverview++ )
        {
            const int nOXSize = (nXSize + panOverviewList[iOverview] - 1)
                / panOverviewList[iOverview];
            const int nOYSize = (nYSize + panOverviewList[iOverview] - 1)
                / panOverviewList[iOverview];

            dfUncompressedOverviewSize +=
                nOXSize * static_cast<double>(nOYSize) * nBands * nDataTypeSize;
        }

        if( nCompression == COMPRESSION_NONE
            && dfUncompressedOverviewSize > 4200000000.0 )
        {
    #ifndef BIGTIFF_SUPPORT
            CPLError(
                CE_Failure, CPLE_NotSupported,
                "The overview file would be larger than 4GB, "
                "but this is the largest size a TIFF can be, "
                "and BigTIFF is unavailable.  "
                "Creation failed." );
            return CE_Failure;
    #endif
        }
    /* -------------------------------------------------------------------- */
    /*      Should the file be created as a bigtiff file?                   */
    /* -------------------------------------------------------------------- */
        const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", nullptr );

        if( pszBIGTIFF == nullptr )
            pszBIGTIFF = "IF_SAFER";

        bool bCreateBigTIFF = false;
        if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
        {
            if( nCompression == COMPRESSION_NONE
                && dfUncompressedOverviewSize > 4200000000.0 )
                bCreateBigTIFF = true;
        }
        else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
        {
            // Look at the size of the base image and suppose that
            // the added overview levels won't be more than 1/2 of
            // the size of the base image. The theory says 1/3 of the
            // base image size if the overview levels are 2, 4, 8, 16.
            // Thus take 1/2 as the security margin for 1/3.
            const double dfUncompressedImageSize =
                nXSize * static_cast<double>(nYSize) * nBands * nDataTypeSize;
            if( dfUncompressedImageSize * 0.5 > 4200000000.0 )
                bCreateBigTIFF = true;
        }
        else
        {
            bCreateBigTIFF = CPLTestBool( pszBIGTIFF );
            if( !bCreateBigTIFF && nCompression == COMPRESSION_NONE
                && dfUncompressedOverviewSize > 4200000000.0 )
            {
                CPLError(
                    CE_Failure, CPLE_NotSupported,
                    "The overview file will be larger than 4GB, "
                    "so BigTIFF is necessary.  "
                    "Creation failed.");
                return CE_Failure;
            }
        }

    #ifndef BIGTIFF_SUPPORT
        if( bCreateBigTIFF )
        {
            CPLError(
                CE_Warning, CPLE_NotSupported,
                "BigTIFF requested, but GDAL built without BigTIFF "
                "enabled libtiff, request ignored." );
            bCreateBigTIFF = false;
        }
    #endif

        if( bCreateBigTIFF )
            CPLDebug( "GTiff", "File being created as a BigTIFF." );

        fpL = VSIFOpenL( pszFilename, "w+" );
        if( fpL == nullptr )
            hOTIFF = nullptr;
        else
            hOTIFF =
               VSI_TIFFOpen( pszFilename, bCreateBigTIFF ? "w+8" : "w+", fpL );
        if( hOTIFF == nullptr )
        {
            if( CPLGetLastErrorNo() == 0 )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Attempt to create new tiff file `%s' "
                          "failed in VSI_TIFFOpen().",
                          pszFilename );
            if( fpL != nullptr )
                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
            return CE_Failure;
        }
    }
/* -------------------------------------------------------------------- */
/*      Otherwise just open it for update access.                       */
/* -------------------------------------------------------------------- */
    else
    {
        fpL = VSIFOpenL( pszFilename, "r+" );
        if( fpL == nullptr )
            hOTIFF = nullptr;
        else
            hOTIFF = VSI_TIFFOpen( pszFilename, "r+", fpL );
        if( hOTIFF == nullptr )
        {
            if( CPLGetLastErrorNo() == 0 )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Attempt to create new tiff file `%s' "
                          "failed in VSI_TIFFOpen().",
                          pszFilename );
            if( fpL != nullptr )
                CPL_IGNORE_RET_VAL(VSIFCloseL(fpL));
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we have a palette?  If so, create a TIFF compatible version. */
/* -------------------------------------------------------------------- */
    unsigned short *panRed = nullptr;
    unsigned short *panGreen = nullptr;
    unsigned short *panBlue = nullptr;

    if( nPhotometric == PHOTOMETRIC_PALETTE )
    {
        GDALColorTable *poCT = papoBandList[0]->GetColorTable();
        int nColorCount = 65536;

        if( nBitsPerPixel <= 8 )
            nColorCount = 256;

        panRed = static_cast<unsigned short *>(
            CPLCalloc(nColorCount, sizeof(unsigned short)) );
        panGreen = static_cast<unsigned short *>(
            CPLCalloc(nColorCount, sizeof(unsigned short)) );
        panBlue = static_cast<unsigned short *>(
            CPLCalloc(nColorCount, sizeof(unsigned short)) );

        for( int iColor = 0; iColor < nColorCount; iColor++ )
        {
          GDALColorEntry sRGB = { 0, 0, 0, 0 };

            if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) )
            {
                // TODO(schwehr): Check for underflow.
                // Going from signed short to unsigned short.
                panRed[iColor] = static_cast<unsigned short>(257 * sRGB.c1);
                panGreen[iColor] = static_cast<unsigned short>(257 * sRGB.c2);
                panBlue[iColor] = static_cast<unsigned short>(257 * sRGB.c3);
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we need some metadata for the overviews?                     */
/* -------------------------------------------------------------------- */
    CPLString osMetadata;
    GDALDataset *poBaseDS = papoBandList[0]->GetDataset();

    GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata );

/* -------------------------------------------------------------------- */
/*      Loop, creating overviews.                                       */
/* -------------------------------------------------------------------- */
    int nOvrBlockXSize = 0;
    int nOvrBlockYSize = 0;
    GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);

    CPLString osNoData; // don't move this in inner scope
    const char* pszNoData = nullptr;
    int bNoDataSet = FALSE;
    const double dfNoDataValue = papoBandList[0]->GetNoDataValue(&bNoDataSet);
    if( bNoDataSet )
    {
        osNoData = GTiffFormatGDALNoDataTagValue(dfNoDataValue);
        pszNoData = osNoData.c_str();
    }

    std::vector<uint16> anExtraSamples;
    for( int i = GTIFFGetMaxColorChannels(nPhotometric)+1; i <= nBands; i++ )
    {
        if( papoBandList[i-1]->GetColorInterpretation() == GCI_AlphaBand )
        {
            anExtraSamples.push_back(
                GTiffGetAlphaValue(CPLGetConfigOption("GTIFF_ALPHA", nullptr),
                                   DEFAULT_ALPHA_TYPE));
        }
        else
        {
            anExtraSamples.push_back(EXTRASAMPLE_UNSPECIFIED);
        }
    }

    for( iOverview = 0; iOverview < nOverviews; iOverview++ )
    {
        const int nOXSize = (nXSize + panOverviewList[iOverview] - 1)
            / panOverviewList[iOverview];
        const int nOYSize = (nYSize + panOverviewList[iOverview] - 1)
            / panOverviewList[iOverview];

        GTIFFWriteDirectory( hOTIFF, FILETYPE_REDUCEDIMAGE,
                             nOXSize, nOYSize, nBitsPerPixel,
                             nPlanarConfig, nBands,
                             nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression,
                             nPhotometric, nSampleFormat, nPredictor,
                             panRed, panGreen, panBlue,
                             static_cast<int>(anExtraSamples.size()),
                             anExtraSamples.empty() ? nullptr : anExtraSamples.data(),
                             osMetadata,
                             CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", nullptr ),
                             CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", nullptr ),
                             pszNoData,
                             nullptr
                           );
    }

    if( panRed )
    {
        CPLFree(panRed);
        CPLFree(panGreen);
        CPLFree(panBlue);
        panRed = nullptr;
        panGreen = nullptr;
        panBlue = nullptr;
    }

    XTIFFClose( hOTIFF );
    if( VSIFCloseL(fpL) != 0 )
        return CE_Failure;
    fpL = nullptr;

/* -------------------------------------------------------------------- */
/*      Open the overview dataset so that we can get at the overview    */
/*      bands.                                                          */
/* -------------------------------------------------------------------- */
    GDALDataset *hODS = GDALDataset::Open( pszFilename,
                                           GDAL_OF_RASTER | GDAL_OF_UPDATE );
    if( hODS == nullptr )
        return CE_Failure;

/* -------------------------------------------------------------------- */
/*      Do we need to set the jpeg quality?                             */
/* -------------------------------------------------------------------- */
    TIFF *hTIFF = static_cast<TIFF *>( hODS->GetInternalHandle(nullptr) );

    if( nCompression == COMPRESSION_JPEG
        && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", nullptr ) != nullptr )
    {
        const int nJpegQuality =
            atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY,
                      nJpegQuality );
        GTIFFSetJpegQuality(GDALDataset::ToHandle(hODS), nJpegQuality);
    }

    if( nCompression == COMPRESSION_JPEG
        && CPLGetConfigOption( "JPEG_TABLESMODE_OVERVIEW", nullptr ) != nullptr )
    {
        const int nJpegTablesMode =
            atoi(CPLGetConfigOption("JPEG_TABLESMODE_OVERVIEW",
                            CPLSPrintf("%d", knGTIFFJpegTablesModeDefault)));
        TIFFSetField( hTIFF, TIFFTAG_JPEGTABLESMODE,
                      nJpegTablesMode );
        GTIFFSetJpegTablesMode(GDALDataset::ToHandle(hODS), nJpegTablesMode);
    }

/* -------------------------------------------------------------------- */
/*      Loop writing overview data.                                     */
/* -------------------------------------------------------------------- */

    int *panOverviewListSorted =
        static_cast<int*>(CPLMalloc(sizeof(int) * nOverviews));
    memcpy( panOverviewListSorted, panOverviewList, sizeof(int) * nOverviews);
    std::sort(panOverviewListSorted, panOverviewListSorted + nOverviews);

    GTIFFSetInExternalOvr(true);

    CPLErr eErr = CE_None;

    if(  ((bSourceIsPixelInterleaved && bSourceIsJPEG2000) ||
          (nCompression != COMPRESSION_NONE)) &&
         nPlanarConfig == PLANARCONFIG_CONTIG &&
         !GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) &&
         papoBandList[0]->GetColorTable() == nullptr &&
         (STARTS_WITH_CI(pszResampling, "NEAR") ||
          EQUAL(pszResampling, "AVERAGE") ||
          EQUAL(pszResampling, "GAUSS") ||
          EQUAL(pszResampling, "CUBIC") ||
          EQUAL(pszResampling, "CUBICSPLINE") ||
          EQUAL(pszResampling, "LANCZOS") ||
          EQUAL(pszResampling, "BILINEAR")) )
    {
        // In the case of pixel interleaved compressed overviews, we want to
        // generate the overviews for all the bands block by block, and not
        // band after band, in order to write the block once and not loose
        // space in the TIFF file.
        GDALRasterBand ***papapoOverviewBands =
            static_cast<GDALRasterBand ***>(
                CPLCalloc(sizeof(void *), nBands) );
        for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
        {
            GDALRasterBand *poSrcBand = papoBandList[iBand];
            GDALRasterBand *poDstBand = hODS->GetRasterBand( iBand + 1 );
            papapoOverviewBands[iBand] =
                static_cast<GDALRasterBand **>(
                    CPLCalloc(sizeof(void *), nOverviews) );

            int bHasNoData = FALSE;
            const double noDataValue = poSrcBand->GetNoDataValue(&bHasNoData);
            if( bHasNoData )
                poDstBand->SetNoDataValue(noDataValue);

            for( int i = 0; i < nOverviews && eErr == CE_None; i++ )
            {
                for( int j = -1; j < poDstBand->GetOverviewCount() &&
                                 eErr == CE_None; j++ )
                {
                    GDALRasterBand * poOverview =
                            (j < 0 ) ? poDstBand : poDstBand->GetOverview( j );
                    if( poOverview == nullptr )
                    {
                        eErr = CE_Failure;
                        continue;
                    }

                    const int nOvFactor =
                        GDALComputeOvFactor(poOverview->GetXSize(),
                                            poSrcBand->GetXSize(),
                                            poOverview->GetYSize(),
                                            poSrcBand->GetYSize());

                    if( nOvFactor == panOverviewListSorted[i]
                        || nOvFactor == GDALOvLevelAdjust2(
                                            panOverviewListSorted[i],
                                            poSrcBand->GetXSize(),
                                            poSrcBand->GetYSize() ) )
                    {
                        papapoOverviewBands[iBand][i] = poOverview;
                        if( bHasNoData )
                            poOverview->SetNoDataValue(noDataValue);
                        break;
                    }
                }
                CPLAssert( papapoOverviewBands[iBand][i] != nullptr );
            }
        }

        if( eErr == CE_None )
            eErr =
                GDALRegenerateOverviewsMultiBand(
                    nBands, papoBandList,
                    nOverviews, papapoOverviewBands,
                    pszResampling, pfnProgress, pProgressData );

        for( int iBand = 0; iBand < nBands; iBand++ )
        {
            CPLFree(papapoOverviewBands[iBand]);
        }
        CPLFree(papapoOverviewBands);
    }
    else
    {
        GDALRasterBand **papoOverviews =
            static_cast<GDALRasterBand **>(
                CPLCalloc( sizeof(void*), knMaxOverviews ) );

        for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
        {
            GDALRasterBand *hSrcBand = papoBandList[iBand];
            GDALRasterBand *hDstBand = hODS->GetRasterBand( iBand + 1 );

            int bHasNoData = FALSE;
            const double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData);
            if( bHasNoData )
                hDstBand->SetNoDataValue(noDataValue);

            // FIXME: this logic regenerates all overview bands, not only the
            // ones requested.

            papoOverviews[0] = hDstBand;
            int nDstOverviews = hDstBand->GetOverviewCount() + 1;
            CPLAssert( nDstOverviews < knMaxOverviews );
            nDstOverviews = std::min(knMaxOverviews, nDstOverviews);

            // TODO(schwehr): Convert to starting with i = 1 and remove +1.
            for( int i = 0; i < nDstOverviews - 1 && eErr == CE_None; i++ )
            {
                papoOverviews[i+1] = hDstBand->GetOverview(i);
                if( papoOverviews[i+1] == nullptr )
                {
                    eErr = CE_Failure;
                }
                else
                {
                    if( bHasNoData )
                        papoOverviews[i+1]->SetNoDataValue(noDataValue);
                }
            }

            void *pScaledProgressData =
                GDALCreateScaledProgress(
                    iBand / static_cast<double>( nBands ),
                    (iBand + 1) / static_cast<double>( nBands ),
                    pfnProgress, pProgressData );

            if( eErr == CE_None )
                eErr =
                    GDALRegenerateOverviews(
                        hSrcBand,
                        nDstOverviews,
                        reinterpret_cast<GDALRasterBandH *>( papoOverviews ),
                        pszResampling,
                        GDALScaledProgress,
                        pScaledProgressData );

            GDALDestroyScaledProgress( pScaledProgressData );
        }

        CPLFree( papoOverviews );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    if( eErr == CE_None )
        hODS->FlushCache();
    delete hODS;

    GTIFFSetInExternalOvr(false);

    CPLFree(panOverviewListSorted);

    pfnProgress( 1.0, nullptr, pProgressData );

    return eErr;
}
Exemple #19
0
CPLErr
VRTFilteredSource::RasterIO( GDALDataType eBandDataType,
                             int nXOff, int nYOff, int nXSize, int nYSize,
                             void *pData, int nBufXSize, int nBufYSize,
                             GDALDataType eBufType,
                             GSpacing nPixelSpace,
                             GSpacing nLineSpace,
                             GDALRasterIOExtraArg* psExtraArg )

{
/* -------------------------------------------------------------------- */
/*      For now we don't support filtered access to non-full            */
/*      resolution requests. Just collect the data directly without     */
/*      any operator.                                                   */
/* -------------------------------------------------------------------- */
    if( nBufXSize != nXSize || nBufYSize != nYSize )
    {
        return VRTComplexSource::RasterIO( eBandDataType,
                                           nXOff, nYOff, nXSize, nYSize,
                                           pData, nBufXSize, nBufYSize,
                                           eBufType, nPixelSpace, nLineSpace,
                                           psExtraArg );
    }

    // The window we will actually request from the source raster band.
    double dfReqXOff = 0.0;
    double dfReqYOff = 0.0;
    double dfReqXSize = 0.0;
    double dfReqYSize = 0.0;
    int nReqXOff = 0;
    int nReqYOff = 0;
    int nReqXSize = 0;
    int nReqYSize = 0;

    // The window we will actual set _within_ the pData buffer.
    int nOutXOff = 0;
    int nOutYOff = 0;
    int nOutXSize = 0;
    int nOutYSize = 0;

    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                        &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                        &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                        &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
        return CE_None;

    pData = reinterpret_cast<GByte *>( pData )
        + nPixelSpace * nOutXOff
        + nLineSpace * nOutYOff;

/* -------------------------------------------------------------------- */
/*      Determine the data type we want to request.  We try to match    */
/*      the source or destination request, and if both those fail we    */
/*      fallback to the first supported type at least as expressive     */
/*      as the request.                                                 */
/* -------------------------------------------------------------------- */
    GDALDataType eOperDataType = GDT_Unknown;

    if( IsTypeSupported( eBufType ) )
        eOperDataType = eBufType;

    if( eOperDataType == GDT_Unknown
        && IsTypeSupported( m_poRasterBand->GetRasterDataType() ) )
        eOperDataType = m_poRasterBand->GetRasterDataType();

    if( eOperDataType == GDT_Unknown )
    {
        for( int i = 0; i < m_nSupportedTypesCount; i++ )
        {
            if( GDALDataTypeUnion( m_aeSupportedTypes[i], eBufType )
                == m_aeSupportedTypes[i] )
            {
                eOperDataType = m_aeSupportedTypes[i];
            }
        }
    }

    if( eOperDataType == GDT_Unknown )
    {
        eOperDataType = m_aeSupportedTypes[0];

        for( int i = 1; i < m_nSupportedTypesCount; i++ )
        {
            if( GDALGetDataTypeSize( m_aeSupportedTypes[i] )
                > GDALGetDataTypeSize( eOperDataType ) )
            {
                eOperDataType = m_aeSupportedTypes[i];
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Allocate the buffer of data into which our imagery will be      */
/*      read, with the extra edge pixels as well. This will be the      */
/*      source data fed into the filter.                                */
/* -------------------------------------------------------------------- */
    if( nOutXSize > INT_MAX - 2 * m_nExtraEdgePixels ||
        nOutYSize > INT_MAX - 2 * m_nExtraEdgePixels )
    {
        return CE_Failure;
    }
    const int nExtraXSize = nOutXSize + 2 * m_nExtraEdgePixels;
    const int nExtraYSize = nOutYSize + 2 * m_nExtraEdgePixels;

    GByte *pabyWorkData = static_cast<GByte *>(
        VSI_MALLOC3_VERBOSE( nExtraXSize, nExtraYSize,
                             GDALGetDataTypeSizeBytes(eOperDataType)) );

    if( pabyWorkData == nullptr )
    {
        return CE_Failure;
    }

    const GPtrDiff_t nPixelOffset = GDALGetDataTypeSizeBytes( eOperDataType );
    const GPtrDiff_t nLineOffset = nPixelOffset * nExtraXSize;

    memset( pabyWorkData, 0, nLineOffset * nExtraYSize );

/* -------------------------------------------------------------------- */
/*      Allocate the output buffer in the same dimensions as the work   */
/*      buffer. This allows the filter process to write edge pixels     */
/*      if needed for two-pass (separable) filtering.                   */
/* -------------------------------------------------------------------- */
    GByte *pabyOutData = static_cast<GByte *>(
        VSI_MALLOC3_VERBOSE( nExtraXSize, nExtraYSize, nPixelOffset ) );
    if( pabyOutData == nullptr )
    {
        CPLFree( pabyWorkData );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Figure out the extended window that we want to load.  Note      */
/*      that we keep track of the file window as well as the amount     */
/*      we will need to edge fill past the edge of the source dataset.  */
/* -------------------------------------------------------------------- */
    int nFileXOff = nReqXOff - m_nExtraEdgePixels;
    int nFileYOff = nReqYOff - m_nExtraEdgePixels;
    int nFileXSize = nExtraXSize;
    int nFileYSize = nExtraYSize;

    int nTopFill = 0;
    int nLeftFill = 0;
    int nRightFill = 0;
    int nBottomFill = 0;

    if( nFileXOff < 0 )
    {
        nLeftFill = -nFileXOff;
        nFileXOff = 0;
        nFileXSize -= nLeftFill;
    }

    if( nFileYOff < 0 )
    {
        nTopFill = -nFileYOff;
        nFileYOff = 0;
        nFileYSize -= nTopFill;
    }

    if( nFileXOff + nFileXSize > m_poRasterBand->GetXSize() )
    {
        nRightFill = nFileXOff + nFileXSize - m_poRasterBand->GetXSize();
        nFileXSize -= nRightFill;
    }

    if( nFileYOff + nFileYSize > m_poRasterBand->GetYSize() )
    {
        nBottomFill = nFileYOff + nFileYSize - m_poRasterBand->GetYSize();
        nFileYSize -= nBottomFill;
    }

/* -------------------------------------------------------------------- */
/*      Load the data.                                                  */
/* -------------------------------------------------------------------- */
    {
        const bool bIsComplex = CPL_TO_BOOL( GDALDataTypeIsComplex(eOperDataType) );
        const CPLErr eErr
            = VRTComplexSource::RasterIOInternal<float>(
                nFileXOff, nFileYOff, nFileXSize, nFileYSize,
                pabyWorkData + nLineOffset * nTopFill + nPixelOffset * nLeftFill,
                nFileXSize, nFileYSize, eOperDataType,
                nPixelOffset, nLineOffset, psExtraArg,
                bIsComplex ? GDT_CFloat32 : GDT_Float32 );

        if( eErr != CE_None )
        {
            VSIFree( pabyWorkData );
            VSIFree( pabyOutData );

            return eErr;
        }
    }

/* -------------------------------------------------------------------- */
/*      Fill in missing areas.  Note that we replicate the edge         */
/*      valid values out.  We don't using "mirroring" which might be    */
/*      more suitable for some times of filters.  We also don't mark    */
/*      these pixels as "nodata" though perhaps we should.              */
/* -------------------------------------------------------------------- */
    if( nLeftFill != 0 || nRightFill != 0 )
    {
        for( int i = nTopFill; i < nExtraYSize - nBottomFill; i++ )
        {
            if( nLeftFill != 0 )
                GDALCopyWords( pabyWorkData + nPixelOffset * nLeftFill
                               + i * nLineOffset, eOperDataType, 0,
                               pabyWorkData + i * nLineOffset, eOperDataType,
                               static_cast<int>(nPixelOffset), nLeftFill );

            if( nRightFill != 0 )
                GDALCopyWords( pabyWorkData + i * nLineOffset
                               + nPixelOffset * (nExtraXSize - nRightFill - 1),
                               eOperDataType, 0,
                               pabyWorkData + i * nLineOffset
                               + nPixelOffset * (nExtraXSize - nRightFill),
                               eOperDataType,
                               static_cast<int>(nPixelOffset), nRightFill );
        }
    }

    for( int i = 0; i < nTopFill; i++ )
    {
        memcpy( pabyWorkData + i * nLineOffset,
                pabyWorkData + nTopFill * nLineOffset,
                nLineOffset );
    }

    for( int i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ )
    {
        memcpy( pabyWorkData + i * nLineOffset,
                pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset,
                nLineOffset );
    }

/* -------------------------------------------------------------------- */
/*      Filter the data.                                                */
/* -------------------------------------------------------------------- */
    const CPLErr eErr = FilterData( nExtraXSize, nExtraYSize, eOperDataType,
                                    pabyWorkData, pabyOutData );

    VSIFree( pabyWorkData );
    if( eErr != CE_None )
    {
        VSIFree( pabyOutData );

        return eErr;
    }

/* -------------------------------------------------------------------- */
/*      Copy from work buffer to target buffer.                         */
/* -------------------------------------------------------------------- */
    GByte *pabySrcRow =
        pabyOutData + (nLineOffset + nPixelOffset) * m_nExtraEdgePixels;
    GByte *pabyDstRow = reinterpret_cast<GByte *>( pData );

    for( int i = 0; i < nOutYSize; i++,
         pabySrcRow += nLineOffset, pabyDstRow += nLineSpace )
    {
        GDALCopyWords( pabySrcRow, eOperDataType, static_cast<int>(nPixelOffset),
                       pabyDstRow, eBufType, static_cast<int>(nPixelSpace),
                       nOutXSize );
    }

    VSIFree( pabyOutData );

    return CE_None;
}
int main( int argc, char ** argv )

{
    const char         *pszLocX = NULL, *pszLocY = NULL;
    const char         *pszSrcFilename = NULL;
    char               *pszSourceSRS = NULL;
    std::vector<int>   anBandList;
    bool               bAsXML = false, bLIFOnly = false;
    bool               bQuiet = false, bValOnly = false;
    int                nOverview = -1;
    char             **papszOpenOptions = NULL;

    GDALAllRegister();
    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    if( argc < 1 )
        exit( -argc );

/* -------------------------------------------------------------------- */
/*      Parse arguments.                                                */
/* -------------------------------------------------------------------- */
    int i;

    for( i = 1; i < argc; i++ )
    {
        if( EQUAL(argv[i], "--utility_version") )
        {
            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
            return 0;
        }
        else if( EQUAL(argv[i],"-b") && i < argc-1 )
        {
            anBandList.push_back( atoi(argv[++i]) );
        }
        else if( EQUAL(argv[i],"-overview") && i < argc-1 )
        {
            nOverview = atoi(argv[++i]) - 1;
        }
        else if( EQUAL(argv[i],"-l_srs") && i < argc-1 )
        {
            CPLFree(pszSourceSRS);
            pszSourceSRS = SanitizeSRS(argv[++i]);
        }
        else if( EQUAL(argv[i],"-geoloc") )
        {
            CPLFree(pszSourceSRS);
            pszSourceSRS = CPLStrdup("-geoloc");
        }
        else if( EQUAL(argv[i],"-wgs84") )
        {
            CPLFree(pszSourceSRS);
            pszSourceSRS = SanitizeSRS("WGS84");
        }
        else if( EQUAL(argv[i],"-xml") )
        {
            bAsXML = true;
        }
        else if( EQUAL(argv[i],"-lifonly") )
        {
            bLIFOnly = true;
            bQuiet = true;
        }
        else if( EQUAL(argv[i],"-valonly") )
        {
            bValOnly = true;
            bQuiet = true;
        }
        else if( EQUAL(argv[i], "-oo") && i < argc-1 )
        {
            papszOpenOptions = CSLAddString( papszOpenOptions,
                                                argv[++i] );
        }
        else if( argv[i][0] == '-' && !isdigit(argv[i][1]) )
            Usage();

        else if( pszSrcFilename == NULL )
            pszSrcFilename = argv[i];

        else if( pszLocX == NULL )
            pszLocX = argv[i];

        else if( pszLocY == NULL )
            pszLocY = argv[i];

        else
            Usage();
    }

    if( pszSrcFilename == NULL || (pszLocX != NULL && pszLocY == NULL) )
        Usage();

/* -------------------------------------------------------------------- */
/*      Open source file.                                               */
/* -------------------------------------------------------------------- */
    GDALDatasetH hSrcDS = NULL;

    hSrcDS = GDALOpenEx( pszSrcFilename, GDAL_OF_RASTER, NULL,
                           (const char* const* )papszOpenOptions, NULL );
    if( hSrcDS == NULL )
        exit( 1 );

/* -------------------------------------------------------------------- */
/*      Setup coordinate transformation, if required                    */
/* -------------------------------------------------------------------- */
    OGRSpatialReferenceH hSrcSRS = NULL, hTrgSRS = NULL;
    OGRCoordinateTransformationH hCT = NULL;
    if( pszSourceSRS != NULL && !EQUAL(pszSourceSRS,"-geoloc") )
    {

        hSrcSRS = OSRNewSpatialReference( pszSourceSRS );
        hTrgSRS = OSRNewSpatialReference( GDALGetProjectionRef( hSrcDS ) );

        hCT = OCTNewCoordinateTransformation( hSrcSRS, hTrgSRS );
        if( hCT == NULL )
            exit( 1 );
    }

/* -------------------------------------------------------------------- */
/*      If no bands were requested, we will query them all.             */
/* -------------------------------------------------------------------- */
    if( anBandList.size() == 0 )
    {
        for( i = 0; i < GDALGetRasterCount( hSrcDS ); i++ )
            anBandList.push_back( i+1 );
    }
    
/* -------------------------------------------------------------------- */
/*      Turn the location into a pixel and line location.               */
/* -------------------------------------------------------------------- */
    int inputAvailable = 1;
    double dfGeoX;
    double dfGeoY;
    CPLString osXML;

    if( pszLocX == NULL && pszLocY == NULL )
    {
        if (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2)
        {
            inputAvailable = 0;
        }
    }
    else
    {
        dfGeoX = CPLAtof(pszLocX);
        dfGeoY = CPLAtof(pszLocY);
    }

    while (inputAvailable)
    {
        int iPixel, iLine;

        if (hCT)
        {
            if( !OCTTransform( hCT, 1, &dfGeoX, &dfGeoY, NULL ) )
                exit( 1 );
        }
    
        if( pszSourceSRS != NULL )
        {
            double adfGeoTransform[6], adfInvGeoTransform[6];
    
            if( GDALGetGeoTransform( hSrcDS, adfGeoTransform ) != CE_None )
            {
                CPLError(CE_Failure, CPLE_AppDefined, "Cannot get geotransform");
                exit( 1 );
            }
    
            if( !GDALInvGeoTransform( adfGeoTransform, adfInvGeoTransform ) )
            {
                CPLError(CE_Failure, CPLE_AppDefined, "Cannot invert geotransform");
                exit( 1 );
            }
    
            iPixel = (int) floor(
                adfInvGeoTransform[0] 
                + adfInvGeoTransform[1] * dfGeoX
                + adfInvGeoTransform[2] * dfGeoY );
            iLine = (int) floor(
                adfInvGeoTransform[3] 
                + adfInvGeoTransform[4] * dfGeoX
                + adfInvGeoTransform[5] * dfGeoY );
        }
        else
        {
            iPixel = (int) floor(dfGeoX);
            iLine  = (int) floor(dfGeoY);
        }

    /* -------------------------------------------------------------------- */
    /*      Prepare report.                                                 */
    /* -------------------------------------------------------------------- */
        CPLString osLine;
    
        if( bAsXML )
        {
            osLine.Printf( "<Report pixel=\"%d\" line=\"%d\">", 
                          iPixel, iLine );
            osXML += osLine;
        }
        else if( !bQuiet )
        {
            printf( "Report:\n" );
            printf( "  Location: (%dP,%dL)\n", iPixel, iLine );
        }

        int bPixelReport = TRUE;

        if( iPixel < 0 || iLine < 0 
            || iPixel >= GDALGetRasterXSize( hSrcDS )
            || iLine  >= GDALGetRasterYSize( hSrcDS ) )
        {
            if( bAsXML )
                osXML += "<Alert>Location is off this file! No further details to report.</Alert>";
            else if( bValOnly )
                printf("\n");
            else if( !bQuiet )
                printf( "\nLocation is off this file! No further details to report.\n");
            bPixelReport = FALSE;
        }

    /* -------------------------------------------------------------------- */
    /*      Process each band.                                              */
    /* -------------------------------------------------------------------- */
        for( i = 0; bPixelReport && i < (int) anBandList.size(); i++ )
        {
            GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, anBandList[i] );

            int iPixelToQuery = iPixel;
            int iLineToQuery = iLine;

            if (nOverview >= 0 && hBand != NULL)
            {
                GDALRasterBandH hOvrBand = GDALGetOverview(hBand, nOverview);
                if (hOvrBand != NULL)
                {
                    int nOvrXSize = GDALGetRasterBandXSize(hOvrBand);
                    int nOvrYSize = GDALGetRasterBandYSize(hOvrBand);
                    iPixelToQuery = (int)(0.5 + 1.0 * iPixel / GDALGetRasterXSize( hSrcDS ) * nOvrXSize);
                    iLineToQuery = (int)(0.5 + 1.0 * iLine / GDALGetRasterYSize( hSrcDS ) * nOvrYSize);
                    if (iPixelToQuery >= nOvrXSize)
                        iPixelToQuery = nOvrXSize - 1;
                    if (iLineToQuery >= nOvrYSize)
                        iLineToQuery = nOvrYSize - 1;
                }
                else
                {
                    CPLError(CE_Failure, CPLE_AppDefined,
                             "Cannot get overview %d of band %d",
                             nOverview + 1, anBandList[i] );
                }
                hBand = hOvrBand;
            }

            if (hBand == NULL)
                continue;

            if( bAsXML )
            {
                osLine.Printf( "<BandReport band=\"%d\">", anBandList[i] );
                osXML += osLine;
            }
            else if( !bQuiet )
            {
                printf( "  Band %d:\n", anBandList[i] );
            }
    
    /* -------------------------------------------------------------------- */
    /*      Request location info for this location.  It is possible        */
    /*      only the VRT driver actually supports this.                     */
    /* -------------------------------------------------------------------- */
            CPLString osItem;
            
            osItem.Printf( "Pixel_%d_%d", iPixelToQuery, iLineToQuery );
            
            const char *pszLI = GDALGetMetadataItem( hBand, osItem, "LocationInfo");
    
            if( pszLI != NULL )
            {
                if( bAsXML )
                    osXML += pszLI;
                else if( !bQuiet )
                    printf( "    %s\n", pszLI );
                else if( bLIFOnly )
                {
                    /* Extract all files, if any. */
                 
                    CPLXMLNode *psRoot = CPLParseXMLString( pszLI );
                    
                    if( psRoot != NULL 
                        && psRoot->psChild != NULL
                        && psRoot->eType == CXT_Element
                        && EQUAL(psRoot->pszValue,"LocationInfo") )
                    {
                        CPLXMLNode *psNode;
    
                        for( psNode = psRoot->psChild;
                             psNode != NULL;
                             psNode = psNode->psNext )
                        {
                            if( psNode->eType == CXT_Element
                                && EQUAL(psNode->pszValue,"File") 
                                && psNode->psChild != NULL )
                            {
                                char* pszUnescaped = CPLUnescapeString(
                                    psNode->psChild->pszValue, NULL, CPLES_XML);
                                printf( "%s\n", pszUnescaped );
                                CPLFree(pszUnescaped);
                            }
                        }
                    }
                    CPLDestroyXMLNode( psRoot );
                }
            }
    
    /* -------------------------------------------------------------------- */
    /*      Report the pixel value of this band.                            */
    /* -------------------------------------------------------------------- */
            double adfPixel[2];
    
            if( GDALRasterIO( hBand, GF_Read, iPixelToQuery, iLineToQuery, 1, 1, 
                              adfPixel, 1, 1, GDT_CFloat64, 0, 0) == CE_None )
            {
                CPLString osValue;
    
                if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) )
                    osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] );
                else
                    osValue.Printf( "%.15g", adfPixel[0] );
    
                if( bAsXML )
                {
                    osXML += "<Value>";
                    osXML += osValue;
                    osXML += "</Value>";
                }
                else if( !bQuiet )
                    printf( "    Value: %s\n", osValue.c_str() );
                else if( bValOnly )
                    printf( "%s\n", osValue.c_str() );
    
                // Report unscaled if we have scale/offset values.
                int bSuccess;
                
                double dfOffset = GDALGetRasterOffset( hBand, &bSuccess );
                double dfScale  = GDALGetRasterScale( hBand, &bSuccess );
    
                if( dfOffset != 0.0 || dfScale != 1.0 )
                {
                    adfPixel[0] = adfPixel[0] * dfScale + dfOffset;
                    adfPixel[1] = adfPixel[1] * dfScale + dfOffset;
    
                    if( GDALDataTypeIsComplex( GDALGetRasterDataType( hBand ) ) )
                        osValue.Printf( "%.15g+%.15gi", adfPixel[0], adfPixel[1] );
                    else
                        osValue.Printf( "%.15g", adfPixel[0] );
    
                    if( bAsXML )
                    {
                        osXML += "<DescaledValue>";
                        osXML += osValue;
                        osXML += "</DescaledValue>";
                    }
                    else if( !bQuiet )
                        printf( "    Descaled Value: %s\n", osValue.c_str() );
                }
            }
    
            if( bAsXML )
                osXML += "</BandReport>";
        }

        osXML += "</Report>";
    
        if( (pszLocX != NULL && pszLocY != NULL)  ||
            (fscanf(stdin, "%lf %lf", &dfGeoX, &dfGeoY) != 2) )
        {
            inputAvailable = 0;
        }
            
    }

/* -------------------------------------------------------------------- */
/*      Finalize xml report and print.                                  */
/* -------------------------------------------------------------------- */
    if( bAsXML )
    {
        CPLXMLNode *psRoot;
        char *pszFormattedXML;


        psRoot = CPLParseXMLString( osXML );
        pszFormattedXML = CPLSerializeXMLTree( psRoot );
        CPLDestroyXMLNode( psRoot );

        printf( "%s", pszFormattedXML );
        CPLFree( pszFormattedXML );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    if (hCT) {
        OSRDestroySpatialReference( hSrcSRS );
        OSRDestroySpatialReference( hTrgSRS );
        OCTDestroyCoordinateTransformation( hCT );
    }

    if (hSrcDS)
        GDALClose(hSrcDS);

    GDALDumpOpenDatasets( stderr );
    GDALDestroyDriverManager();
    CPLFree(pszSourceSRS);
    CSLDestroy(papszOpenOptions);

    CSLDestroy( argv );

    return 0;
}
Exemple #21
0
CPLErr 
GTIFFBuildOverviews( const char * pszFilename,
                     int nBands, GDALRasterBand **papoBandList, 
                     int nOverviews, int * panOverviewList,
                     const char * pszResampling, 
                     GDALProgressFunc pfnProgress, void * pProgressData )

{
    TIFF    *hOTIFF;
    int     nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0;
    int     nSampleFormat=0, nPlanarConfig, iOverview, iBand;
    int     nXSize=0, nYSize=0;

    if( nBands == 0 || nOverviews == 0 )
        return CE_None;

    if (!GTiffOneTimeInit())
        return CE_Failure;

/* -------------------------------------------------------------------- */
/*      Verify that the list of bands is suitable for emitting in       */
/*      TIFF file.                                                      */
/* -------------------------------------------------------------------- */
    for( iBand = 0; iBand < nBands; iBand++ )
    {
        int     nBandBits, nBandFormat;
        GDALRasterBand *hBand = papoBandList[iBand];

        switch( hBand->GetRasterDataType() )
        {
          case GDT_Byte:
            nBandBits = 8;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_UInt16:
            nBandBits = 16;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_Int16:
            nBandBits = 16;
            nBandFormat = SAMPLEFORMAT_INT;
            break;

          case GDT_UInt32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_Int32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_INT;
            break;

          case GDT_Float32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_IEEEFP;
            break;

          case GDT_Float64:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_IEEEFP;
            break;

          case GDT_CInt16:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_COMPLEXINT;
            break;

          case GDT_CInt32:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_COMPLEXINT;
            break;

          case GDT_CFloat32:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
            break;

          case GDT_CFloat64:
            nBandBits = 128;
            nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
            break;

          default:
            CPLAssert( FALSE );
            return CE_Failure;
        }

        if( hBand->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ) )
        {
            nBandBits = 
                atoi(hBand->GetMetadataItem("NBITS","IMAGE_STRUCTURE"));

            if( nBandBits == 1 
                && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
                nBandBits = 8;
        }

        if( iBand == 0 )
        {
            nBitsPerPixel = nBandBits;
            nSampleFormat = nBandFormat;
            nXSize = hBand->GetXSize();
            nYSize = hBand->GetYSize();
        }
        else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support a mixture of band"
                      " data types." );
            return CE_Failure;
        }
        else if( hBand->GetColorTable() != NULL )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support building"
                      " overviews of multiple colormapped bands." );
            return CE_Failure;
        }
        else if( hBand->GetXSize() != nXSize 
                 || hBand->GetYSize() != nYSize )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support building"
                      " overviews of different sized bands." );
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Use specified compression method.                               */
/* -------------------------------------------------------------------- */
    const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", NULL );

    if( pszCompress != NULL && pszCompress[0] != '\0' )
    {
        nCompression = GTIFFGetCompressionMethod(pszCompress, "COMPRESS_OVERVIEW");
        if (nCompression < 0)
            return CE_Failure;
    }
    
    if( nCompression == COMPRESSION_JPEG && nBitsPerPixel > 8 )
    {  
        if( nBitsPerPixel > 16 )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support building"
                      " JPEG compressed overviews of nBitsPerPixel > 16." );
            return CE_Failure;
        }

        nBitsPerPixel = 12;
    }

/* -------------------------------------------------------------------- */
/*      Figure out the planar configuration to use.                     */
/* -------------------------------------------------------------------- */
    if( nBands == 1 )
        nPlanarConfig = PLANARCONFIG_CONTIG;
    else
        nPlanarConfig = PLANARCONFIG_SEPARATE;

    const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL );
    if (pszInterleave != NULL && pszInterleave[0] != '\0')
    {
        if( EQUAL( pszInterleave, "PIXEL" ) )
            nPlanarConfig = PLANARCONFIG_CONTIG;
        else if( EQUAL( pszInterleave, "BAND" ) )
            nPlanarConfig = PLANARCONFIG_SEPARATE;
        else
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring",
                      pszInterleave );
        }
    }

/* -------------------------------------------------------------------- */
/*      Figure out the photometric interpretation to use.               */
/* -------------------------------------------------------------------- */
    if( nBands == 3 )
        nPhotometric = PHOTOMETRIC_RGB;
    else if( papoBandList[0]->GetColorTable() != NULL 
             && !EQUALN(pszResampling,"AVERAGE_BIT2",12) )
    {
        nPhotometric = PHOTOMETRIC_PALETTE;
        /* should set the colormap up at this point too! */
    }
    else
        nPhotometric = PHOTOMETRIC_MINISBLACK;

    const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL );
    if (pszPhotometric != NULL && pszPhotometric[0] != '\0')
    {
        if( EQUAL( pszPhotometric, "MINISBLACK" ) )
            nPhotometric = PHOTOMETRIC_MINISBLACK;
        else if( EQUAL( pszPhotometric, "MINISWHITE" ) )
            nPhotometric = PHOTOMETRIC_MINISWHITE;
        else if( EQUAL( pszPhotometric, "RGB" ))
        {
            nPhotometric = PHOTOMETRIC_RGB;
        }
        else if( EQUAL( pszPhotometric, "CMYK" ))
        {
            nPhotometric = PHOTOMETRIC_SEPARATED;
        }
        else if( EQUAL( pszPhotometric, "YCBCR" ))
        {
            nPhotometric = PHOTOMETRIC_YCBCR;

            /* Because of subsampling, setting YCBCR without JPEG compression leads */
            /* to a crash currently. Would need to make GTiffRasterBand::IWriteBlock() */
            /* aware of subsampling so that it doesn't overrun buffer size returned */
            /* by libtiff */
            if ( nCompression != COMPRESSION_JPEG )
            {
                CPLError(CE_Failure, CPLE_NotSupported,
                         "Currently, PHOTOMETRIC_OVERVIEW=YCBCR requires COMPRESS_OVERVIEW=JPEG");
                return CE_Failure;
            }

            if (pszInterleave != NULL && pszInterleave[0] != '\0' && nPlanarConfig == PLANARCONFIG_SEPARATE)
            {
                CPLError(CE_Failure, CPLE_NotSupported,
                         "PHOTOMETRIC_OVERVIEW=YCBCR requires INTERLEAVE_OVERVIEW=PIXEL");
                return CE_Failure;
            }
            else
            {
                nPlanarConfig = PLANARCONFIG_CONTIG;
            }

            /* YCBCR strictly requires 3 bands. Not less, not more */
            /* Issue an explicit error message as libtiff one is a bit cryptic : */
            /* JPEGLib:Bogus input colorspace */
            if ( nBands != 3 )
            {
                CPLError(CE_Failure, CPLE_NotSupported,
                         "PHOTOMETRIC_OVERVIEW=YCBCR requires a source raster with only 3 bands (RGB)");
                return CE_Failure;
            }
        }
        else if( EQUAL( pszPhotometric, "CIELAB" ))
        {
            nPhotometric = PHOTOMETRIC_CIELAB;
        }
        else if( EQUAL( pszPhotometric, "ICCLAB" ))
        {
            nPhotometric = PHOTOMETRIC_ICCLAB;
        }
        else if( EQUAL( pszPhotometric, "ITULAB" ))
        {
            nPhotometric = PHOTOMETRIC_ITULAB;
        }
        else
        {
            CPLError( CE_Warning, CPLE_IllegalArg, 
                      "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n",
                      pszPhotometric );
        }
    }

/* -------------------------------------------------------------------- */
/*      Figure out the predictor value to use.                          */
/* -------------------------------------------------------------------- */
    int nPredictor = PREDICTOR_NONE;
    if ( nCompression == COMPRESSION_LZW ||
         nCompression == COMPRESSION_ADOBE_DEFLATE )
    {
        const char* pszPredictor = CPLGetConfigOption( "PREDICTOR_OVERVIEW", NULL );
        if( pszPredictor  != NULL )
        {
            nPredictor =  atoi( pszPredictor );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create the file, if it does not already exist.                  */
/* -------------------------------------------------------------------- */
    VSIStatBufL  sStatBuf;
    VSILFILE* fpL = NULL;

    if( VSIStatExL( pszFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) != 0 )
    {
    /* -------------------------------------------------------------------- */
    /*      Compute the uncompressed size.                                  */
    /* -------------------------------------------------------------------- */
        double  dfUncompressedOverviewSize = 0;
        int nDataTypeSize = GDALGetDataTypeSize(papoBandList[0]->GetRasterDataType())/8;

        for( iOverview = 0; iOverview < nOverviews; iOverview++ )
        {
            int    nOXSize, nOYSize;

            nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
                / panOverviewList[iOverview];
            nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
                / panOverviewList[iOverview];

            dfUncompressedOverviewSize += 
                nOXSize * ((double)nOYSize) * nBands * nDataTypeSize;
        }

        if( nCompression == COMPRESSION_NONE 
            && dfUncompressedOverviewSize > 4200000000.0 )
        {
    #ifndef BIGTIFF_SUPPORT
            CPLError( CE_Failure, CPLE_NotSupported, 
                    "The overview file would be larger than 4GB\n"
                    "but this is the largest size a TIFF can be, and BigTIFF is unavailable.\n"
                    "Creation failed." );
            return CE_Failure;
    #endif
        }
    /* -------------------------------------------------------------------- */
    /*      Should the file be created as a bigtiff file?                   */
    /* -------------------------------------------------------------------- */
        const char *pszBIGTIFF = CPLGetConfigOption( "BIGTIFF_OVERVIEW", NULL );

        if( pszBIGTIFF == NULL )
            pszBIGTIFF = "IF_NEEDED";

        int bCreateBigTIFF = FALSE;
        if( EQUAL(pszBIGTIFF,"IF_NEEDED") )
        {
            if( nCompression == COMPRESSION_NONE 
                && dfUncompressedOverviewSize > 4200000000.0 )
                bCreateBigTIFF = TRUE;
        }
        else if( EQUAL(pszBIGTIFF,"IF_SAFER") )
        {
            /* Look at the size of the base image and suppose that */
            /* the added overview levels won't be more than 1/2 of */
            /* the size of the base image. The theory says 1/3 of the */
            /* base image size if the overview levels are 2, 4, 8, 16... */
            /* Thus take 1/2 as the security margin for 1/3 */
            double dfUncompressedImageSize =
                        nXSize * ((double)nYSize) * nBands * nDataTypeSize;
            if( dfUncompressedImageSize * .5 > 4200000000.0 )
                bCreateBigTIFF = TRUE;
        }
        else
        {
            bCreateBigTIFF = CSLTestBoolean( pszBIGTIFF );
            if (!bCreateBigTIFF && nCompression == COMPRESSION_NONE 
                && dfUncompressedOverviewSize > 4200000000.0 )
            {
                CPLError( CE_Failure, CPLE_NotSupported, 
                    "The overview file will be larger than 4GB, so BigTIFF is necessary.\n"
                    "Creation failed.");
                return CE_Failure;
            }
        }

    #ifndef BIGTIFF_SUPPORT
        if( bCreateBigTIFF )
        {
            CPLError( CE_Warning, CPLE_NotSupported,
                    "BigTIFF requested, but GDAL built without BigTIFF\n"
                    "enabled libtiff, request ignored." );
            bCreateBigTIFF = FALSE;
        }
    #endif

        if( bCreateBigTIFF )
            CPLDebug( "GTiff", "File being created as a BigTIFF." );

        fpL = VSIFOpenL( pszFilename, "w+" );
        if( fpL == NULL )
            hOTIFF = NULL;
        else
            hOTIFF = VSI_TIFFOpen( pszFilename, (bCreateBigTIFF) ? "w+8" : "w+", fpL );
        if( hOTIFF == NULL )
        {
            if( CPLGetLastErrorNo() == 0 )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Attempt to create new tiff file `%s'\n"
                          "failed in VSI_TIFFOpen().\n",
                          pszFilename );
            if( fpL != NULL )
                VSIFCloseL(fpL);
            return CE_Failure;
        }
    }
/* -------------------------------------------------------------------- */
/*      Otherwise just open it for update access.                       */
/* -------------------------------------------------------------------- */
    else 
    {
        fpL = VSIFOpenL( pszFilename, "r+" );
        if( fpL == NULL )
            hOTIFF = NULL;
        else
            hOTIFF = VSI_TIFFOpen( pszFilename, "r+", fpL );
        if( hOTIFF == NULL )
        {
            if( CPLGetLastErrorNo() == 0 )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Attempt to create new tiff file `%s'\n"
                          "failed in VSI_TIFFOpen().\n",
                          pszFilename );
            if( fpL != NULL )
                VSIFCloseL(fpL);
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we have a palette?  If so, create a TIFF compatible version. */
/* -------------------------------------------------------------------- */
    unsigned short      *panRed=NULL, *panGreen=NULL, *panBlue=NULL;

    if( nPhotometric == PHOTOMETRIC_PALETTE )
    {
        GDALColorTable *poCT = papoBandList[0]->GetColorTable();
        int nColorCount;

        if( nBitsPerPixel <= 8 )
            nColorCount = 256;
        else
            nColorCount = 65536;

        panRed   = (unsigned short *) 
            CPLCalloc(nColorCount,sizeof(unsigned short));
        panGreen = (unsigned short *) 
            CPLCalloc(nColorCount,sizeof(unsigned short));
        panBlue  = (unsigned short *) 
            CPLCalloc(nColorCount,sizeof(unsigned short));

        for( int iColor = 0; iColor < nColorCount; iColor++ )
        {
            GDALColorEntry  sRGB;

            if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) )
            {
                panRed[iColor] = (unsigned short) (257 * sRGB.c1);
                panGreen[iColor] = (unsigned short) (257 * sRGB.c2);
                panBlue[iColor] = (unsigned short) (257 * sRGB.c3);
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we need some metadata for the overviews?                     */
/* -------------------------------------------------------------------- */
    CPLString osMetadata;
    GDALDataset *poBaseDS = papoBandList[0]->GetDataset();

    GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata );

/* -------------------------------------------------------------------- */
/*      Loop, creating overviews.                                       */
/* -------------------------------------------------------------------- */
    int nOvrBlockXSize, nOvrBlockYSize;
    GTIFFGetOverviewBlockSize(&nOvrBlockXSize, &nOvrBlockYSize);
    for( iOverview = 0; iOverview < nOverviews; iOverview++ )
    {
        int    nOXSize, nOYSize;

        nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
            / panOverviewList[iOverview];
        nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
            / panOverviewList[iOverview];

        GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE,
                            nOXSize, nOYSize, nBitsPerPixel, 
                            nPlanarConfig, nBands,
                            nOvrBlockXSize, nOvrBlockYSize, TRUE, nCompression,
                            nPhotometric, nSampleFormat, nPredictor,
                            panRed, panGreen, panBlue,
                            0, NULL, /* FIXME? how can we fetch extrasamples */
                            osMetadata );
    }

    if (panRed)
    {
        CPLFree(panRed);
        CPLFree(panGreen);
        CPLFree(panBlue);
        panRed = panGreen = panBlue = NULL;
    }

    XTIFFClose( hOTIFF );
    VSIFCloseL(fpL);
    fpL = NULL;

/* -------------------------------------------------------------------- */
/*      Open the overview dataset so that we can get at the overview    */
/*      bands.                                                          */
/* -------------------------------------------------------------------- */
    GDALDataset *hODS;
    CPLErr eErr = CE_None;

    hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
    if( hODS == NULL )
        return CE_Failure;
    
/* -------------------------------------------------------------------- */
/*      Do we need to set the jpeg quality?                             */
/* -------------------------------------------------------------------- */
    TIFF *hTIFF = (TIFF*) hODS->GetInternalHandle(NULL);

    if( nCompression == COMPRESSION_JPEG 
        && CPLGetConfigOption( "JPEG_QUALITY_OVERVIEW", NULL ) != NULL )
    {
        int nJpegQuality = atoi(CPLGetConfigOption("JPEG_QUALITY_OVERVIEW","75"));
        TIFFSetField( hTIFF, TIFFTAG_JPEGQUALITY, 
                      nJpegQuality );
        GTIFFSetJpegQuality((GDALDatasetH)hODS, nJpegQuality);
    }

/* -------------------------------------------------------------------- */
/*      Loop writing overview data.                                     */
/* -------------------------------------------------------------------- */

    if (nCompression != COMPRESSION_NONE &&
        nPlanarConfig == PLANARCONFIG_CONTIG &&
        GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE &&
        papoBandList[0]->GetColorTable() == NULL &&
        (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") ||
         EQUAL(pszResampling, "GAUSS") || EQUAL(pszResampling, "CUBIC") ||
         EQUAL(pszResampling, "CUBICSPLINE") || EQUAL(pszResampling, "LANCZOS") ||
         EQUAL(pszResampling, "BILINEAR")))
    {
        /* In the case of pixel interleaved compressed overviews, we want to generate */
        /* the overviews for all the bands block by block, and not band after band, */
        /* in order to write the block once and not loose space in the TIFF file */
        GDALRasterBand ***papapoOverviewBands;

        papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
        for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
        {
            GDALRasterBand    *hSrcBand = papoBandList[iBand];
            GDALRasterBand    *hDstBand = hODS->GetRasterBand( iBand+1 );
            papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
            papapoOverviewBands[iBand][0] = hDstBand;

            int bHasNoData;
            double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData);
            if (bHasNoData)
                hDstBand->SetNoDataValue(noDataValue);

            for( int i = 0; i < nOverviews-1 && eErr == CE_None; i++ )
            {
                papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i);
                if (papapoOverviewBands[iBand][i+1] == NULL)
                    eErr = CE_Failure;
                else
                {
                    if (bHasNoData)
                        papapoOverviewBands[iBand][i+1]->SetNoDataValue(noDataValue);
                }
            }
        }

        if (eErr == CE_None)
            eErr = GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
                                            nOverviews, papapoOverviewBands,
                                            pszResampling, pfnProgress, pProgressData );

        for( iBand = 0; iBand < nBands; iBand++ )
        {
            CPLFree(papapoOverviewBands[iBand]);
        }
        CPLFree(papapoOverviewBands);
    }
    else
    {
        GDALRasterBand   **papoOverviews;

        papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128);

        for( iBand = 0; iBand < nBands && eErr == CE_None; iBand++ )
        {
            GDALRasterBand    *hSrcBand = papoBandList[iBand];
            GDALRasterBand    *hDstBand;
            int               nDstOverviews;

            hDstBand = hODS->GetRasterBand( iBand+1 );

            int bHasNoData;
            double noDataValue = hSrcBand->GetNoDataValue(&bHasNoData);
            if (bHasNoData)
                hDstBand->SetNoDataValue(noDataValue);

            papoOverviews[0] = hDstBand;
            nDstOverviews = hDstBand->GetOverviewCount() + 1;
            CPLAssert( nDstOverviews < 128 );
            nDstOverviews = MIN(128,nDstOverviews);

            for( int i = 0; i < nDstOverviews-1 && eErr == CE_None; i++ )
            {
                papoOverviews[i+1] = hDstBand->GetOverview(i);
                if (papoOverviews[i+1] == NULL)
                    eErr = CE_Failure;
                else
                {
                    if (bHasNoData)
                        papoOverviews[i+1]->SetNoDataValue(noDataValue);
                }
            }

            void         *pScaledProgressData;

            pScaledProgressData = 
                GDALCreateScaledProgress( iBand / (double) nBands, 
                                        (iBand+1) / (double) nBands,
                                        pfnProgress, pProgressData );

            if (eErr == CE_None)
                eErr = 
                    GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, 
                                        nDstOverviews, 
                                        (GDALRasterBandH *) papoOverviews, 
                                        pszResampling,
                                        GDALScaledProgress, 
                                        pScaledProgressData);

            GDALDestroyScaledProgress( pScaledProgressData );
        }

        CPLFree( papoOverviews );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    if (eErr == CE_None)
        hODS->FlushCache();
    delete hODS;

    pfnProgress( 1.0, NULL, pProgressData );

    return eErr;
}
Exemple #22
0
CPLErr RawRasterBand::AccessLine( int iLine )

{
    if (pLineBuffer == NULL)
        return CE_Failure;

    if( nLoadedScanline == iLine )
        return CE_None;

/* -------------------------------------------------------------------- */
/*      Figure out where to start reading.                              */
/* -------------------------------------------------------------------- */
    vsi_l_offset nReadStart;
    if( nPixelOffset >= 0 )
        nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset;
    else
    {
        nReadStart = nImgOffset + (vsi_l_offset)iLine * nLineOffset
            - ABS(nPixelOffset) * (nBlockXSize-1);
    }

/* -------------------------------------------------------------------- */
/*      Seek to the right line.                                         */
/* -------------------------------------------------------------------- */
    if( Seek(nReadStart, SEEK_SET) == -1 )
    {
        if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
        {
            CPLError( CE_Failure, CPLE_FileIO,
                  "Failed to seek to scanline %d @ %d.\n",
                  iLine, (int) (nImgOffset + (vsi_l_offset)iLine * nLineOffset) );
            return CE_Failure;
        }
        else
        {
            memset( pLineBuffer, 0, nPixelOffset * nBlockXSize );
            nLoadedScanline = iLine;
            return CE_None;
        }
    }

/* -------------------------------------------------------------------- */
/*      Read the line.  Take care not to request any more bytes than    */
/*      are needed, and not to lose a partially successful scanline     */
/*      read.                                                           */
/* -------------------------------------------------------------------- */
    int	nBytesToRead, nBytesActuallyRead;

    nBytesToRead = ABS(nPixelOffset) * (nBlockXSize - 1) 
        + GDALGetDataTypeSize(GetRasterDataType()) / 8;

    nBytesActuallyRead = Read( pLineBuffer, 1, nBytesToRead );
    if( nBytesActuallyRead < nBlockXSize )
    {
        if (poDS != NULL && poDS->GetAccess() == GA_ReadOnly)
        {
            CPLError( CE_Failure, CPLE_FileIO,
                      "Failed to read scanline %d.\n",
                      iLine);
            return CE_Failure;
        }
        else
        {
            memset( ((GByte *) pLineBuffer) + nBytesActuallyRead, 
                    0, nBytesToRead - nBytesActuallyRead );
        }
    }

/* -------------------------------------------------------------------- */
/*      Byte swap the interesting data, if required.                    */
/* -------------------------------------------------------------------- */
    if( !bNativeOrder && eDataType != GDT_Byte )
    {
        if( GDALDataTypeIsComplex( eDataType ) )
        {
            int nWordSize;

            nWordSize = GDALGetDataTypeSize(eDataType)/16;
            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, ABS(nPixelOffset) );
            GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, 
                           nWordSize, nBlockXSize, ABS(nPixelOffset) );
        }
        else
            GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
                           nBlockXSize, ABS(nPixelOffset) );
    }

    nLoadedScanline = iLine;

    return CE_None;
}
CPLErr MulPixelFunc(void **papoSources, int nSources, void *pData,
                    int nXSize, int nYSize,
                    GDALDataType eSrcType, GDALDataType eBufType,
                    int nPixelSpace, int nLineSpace)
{
    int iLine, iCol, ii, iSrc;

    /* ---- Init ---- */
    if (nSources < 2) return CE_Failure;

    /* ---- Set pixels ---- */
    if (GDALDataTypeIsComplex( eSrcType ))
    {
        double adfPixVal[2], dfOldR, dfOldI, dfNewR, dfNewI;
        void *pReal, *pImag;
        int nOffset = GDALGetDataTypeSize( eSrcType ) / 8 / 2;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                adfPixVal[0] = 1.;
                adfPixVal[1] = 0.;

                for( iSrc = 0; iSrc < nSources; ++iSrc ) {
                    pReal = papoSources[iSrc];
                    pImag = ((GByte *)pReal) + nOffset;

                    dfOldR = adfPixVal[0];
                    dfOldI = adfPixVal[1];

                    /* Source raster pixels may be obtained with SRCVAL macro */
                    dfNewR = SRCVAL(pReal, eSrcType, ii);
                    dfNewI = SRCVAL(pImag, eSrcType, ii);

                    adfPixVal[0] = dfOldR * dfNewR - dfOldI * dfNewI;
                    adfPixVal[1] = dfOldR * dfNewI + dfOldI * dfNewR;
                }

                GDALCopyWords(adfPixVal, GDT_CFloat64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    } else {
        /* non complex */
        double dfPixVal;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {
                dfPixVal = 1;

                for( iSrc = 0; iSrc < nSources; ++iSrc ) {
                    /* Source raster pixels may be obtained with SRCVAL macro */
                    dfPixVal *= SRCVAL(papoSources[iSrc], eSrcType, ii);
                }

                GDALCopyWords(&dfPixVal, GDT_Float64, 0,
                              ((GByte *)pData) + nLineSpace * iLine +
                              iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* MulPixelFunc */
Exemple #24
0
CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
                                 GDALDataType eBufType,
                                 int nPixelSpace, int nLineSpace )

{
    int         nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
    int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
    int         nBytesToRW = nPixelOffset * nXSize;

    if( !CanUseDirectIO(nXOff, nYOff, nXSize, nYSize, eBufType ) )
    {
        return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
                                          nXSize, nYSize,
                                          pData, nBufXSize, nBufYSize,
                                          eBufType,
                                          nPixelSpace, nLineSpace );
    }

    CPLDebug("RAW", "Using direct IO implementation");

/* ==================================================================== */
/*   Read data.                                                         */
/* ==================================================================== */
    if ( eRWFlag == GF_Read )
    {
/* -------------------------------------------------------------------- */
/*      Do we have overviews that would be appropriate to satisfy       */
/*      this request?                                                   */
/* -------------------------------------------------------------------- */
        if( (nBufXSize < nXSize || nBufYSize < nYSize)
            && GetOverviewCount() > 0 )
        {
            if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
                                  pData, nBufXSize, nBufYSize, 
                                  eBufType, nPixelSpace, nLineSpace ) == CE_None )
                return CE_None;
        }

/* ==================================================================== */
/*   1. Simplest case when we should get contiguous block               */
/*   of uninterleaved pixels.                                           */
/* ==================================================================== */
        if ( nXSize == GetXSize() 
             && nXSize == nBufXSize
             && nYSize == nBufYSize
             && eBufType == eDataType
             && nPixelOffset == nBandDataSize
             && nPixelSpace == nBufDataSize
             && nLineSpace == nPixelSpace * nXSize )
        {
            vsi_l_offset nOffset = nImgOffset
                              + (vsi_l_offset)nYOff * nLineOffset + nXOff;
            if ( AccessBlock( nOffset,
                              nXSize * nYSize * nBandDataSize, pData ) != CE_None )
            {
                CPLError( CE_Failure, CPLE_FileIO,
                          "Failed to read %d bytes at " CPL_FRMT_GUIB ".",
                          nXSize * nYSize * nBandDataSize, nOffset);
            }
        }

/* ==================================================================== */
/*   2. Case when we need deinterleave and/or subsample data.           */
/* ==================================================================== */
        else
        {
            GByte   *pabyData;
            double  dfSrcXInc, dfSrcYInc;
            int     iLine;
            
            dfSrcXInc = (double)nXSize / nBufXSize;
            dfSrcYInc = (double)nYSize / nBufYSize;


            pabyData = (GByte *) CPLMalloc( nBytesToRW );

            for ( iLine = 0; iLine < nBufYSize; iLine++ )
            {
                vsi_l_offset nOffset = nImgOffset
                                  + ((vsi_l_offset)nYOff
                                  + (vsi_l_offset)(iLine * dfSrcYInc)) * nLineOffset
                                  + nXOff * nPixelOffset;
                if ( AccessBlock( nOffset,
                                  nBytesToRW, pabyData ) != CE_None )
                {
                    CPLError( CE_Failure, CPLE_FileIO,
                              "Failed to read %d bytes at " CPL_FRMT_GUIB ".",
                              nBytesToRW, nOffset );
                }

/* -------------------------------------------------------------------- */
/*      Copy data from disk buffer to user block buffer and subsample,  */
/*      if needed.                                                      */
/* -------------------------------------------------------------------- */
                if ( nXSize == nBufXSize && nYSize == nBufYSize )
                {
                    GDALCopyWords( pabyData, eDataType, nPixelOffset,
                                   (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
                                   eBufType, nPixelSpace, nXSize );
                }
                else
                {
                    int     iPixel;

                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                    {
                        GDALCopyWords( pabyData +
                                       (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
                                       eDataType, nPixelOffset,
                                       (GByte *)pData + (vsi_l_offset)iLine * nLineSpace +
                                       (vsi_l_offset)iPixel * nPixelSpace,
                                       eBufType, nPixelSpace, 1 );
                    }
                }
            }

            CPLFree( pabyData );
        }
    }

/* ==================================================================== */
/*   Write data.                                                        */
/* ==================================================================== */
    else
    {
        int nBytesActuallyWritten;

/* ==================================================================== */
/*   1. Simplest case when we should write contiguous block             */
/*   of uninterleaved pixels.                                           */
/* ==================================================================== */
        if ( nXSize == GetXSize() 
             && nXSize == nBufXSize
             && nYSize == nBufYSize
             && eBufType == eDataType
             && nPixelOffset == nBandDataSize
             && nPixelSpace == nBufDataSize
             && nLineSpace == nPixelSpace * nXSize )
        {
/* -------------------------------------------------------------------- */
/*      Byte swap the data buffer, if required.                         */
/* -------------------------------------------------------------------- */
            if( !bNativeOrder && eDataType != GDT_Byte )
            {
                if( GDALDataTypeIsComplex( eDataType ) )
                {
                    int nWordSize;

                    nWordSize = GDALGetDataTypeSize(eDataType)/16;
                    GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
                    GDALSwapWords( ((GByte *) pData) + nWordSize, 
                                   nWordSize, nXSize, nPixelOffset );
                }
                else
                    GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
            }

/* -------------------------------------------------------------------- */
/*      Seek to the right block.                                        */
/* -------------------------------------------------------------------- */
            vsi_l_offset nOffset = nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff;
            if( Seek( nOffset, SEEK_SET) == -1 )
            {
                CPLError( CE_Failure, CPLE_FileIO,
                          "Failed to seek to " CPL_FRMT_GUIB " to write data.\n",
                          nOffset);
        
                return CE_Failure;
            }

/* -------------------------------------------------------------------- */
/*      Write the block.                                                */
/* -------------------------------------------------------------------- */
            nBytesToRW = nXSize * nYSize * nBandDataSize;

            nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
            if( nBytesActuallyWritten < nBytesToRW )
            {
                CPLError( CE_Failure, CPLE_FileIO,
                          "Failed to write %d bytes to file. %d bytes written",
                          nBytesToRW, nBytesActuallyWritten );
        
                return CE_Failure;
            }

/* -------------------------------------------------------------------- */
/*      Byte swap (if necessary) back into machine order so the         */
/*      buffer is still usable for reading purposes.                    */
/* -------------------------------------------------------------------- */
            if( !bNativeOrder  && eDataType != GDT_Byte )
            {
                if( GDALDataTypeIsComplex( eDataType ) )
                {
                    int nWordSize;

                    nWordSize = GDALGetDataTypeSize(eDataType)/16;
                    GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
                    GDALSwapWords( ((GByte *) pData) + nWordSize, 
                                   nWordSize, nXSize, nPixelOffset );
                }
                else
                    GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
            }
        }

/* ==================================================================== */
/*   2. Case when we need deinterleave and/or subsample data.           */
/* ==================================================================== */
        else
        {
            GByte   *pabyData;
            double  dfSrcXInc, dfSrcYInc;
            vsi_l_offset nBlockOff;
            int     iLine;
            
            dfSrcXInc = (double)nXSize / nBufXSize;
            dfSrcYInc = (double)nYSize / nBufYSize;

            pabyData = (GByte *) CPLMalloc( nBytesToRW );

            for ( iLine = 0; iLine < nBufYSize; iLine++ )
            {
                nBlockOff = nImgOffset
                    + ((vsi_l_offset)nYOff + (vsi_l_offset)(iLine*dfSrcYInc))*nLineOffset
                    + nXOff * nPixelOffset;

/* -------------------------------------------------------------------- */
/*      If the data for this band is completely contiguous we don't     */
/*      have to worry about pre-reading from disk.                      */
/* -------------------------------------------------------------------- */
                if( nPixelOffset > nBandDataSize )
                    AccessBlock( nBlockOff, nBytesToRW, pabyData );

/* -------------------------------------------------------------------- */
/*      Copy data from user block buffer to disk buffer and subsample,  */
/*      if needed.                                                      */
/* -------------------------------------------------------------------- */
                if ( nXSize == nBufXSize && nYSize == nBufYSize )
                {
                    GDALCopyWords( (GByte *)pData + (vsi_l_offset)iLine * nLineSpace,
                                   eBufType, nPixelSpace,
                                   pabyData, eDataType, nPixelOffset, nXSize );
                }
                else
                {
                    int     iPixel;

                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                    {
                        GDALCopyWords( (GByte *)pData+(vsi_l_offset)iLine*nLineSpace +
                                       (vsi_l_offset)iPixel * nPixelSpace,
                                       eBufType, nPixelSpace,
                                       pabyData +
                                       (vsi_l_offset)(iPixel * dfSrcXInc) * nPixelOffset,
                                       eDataType, nPixelOffset, 1 );
                    }
                }

/* -------------------------------------------------------------------- */
/*      Byte swap the data buffer, if required.                         */
/* -------------------------------------------------------------------- */
                if( !bNativeOrder && eDataType != GDT_Byte )
                {
                    if( GDALDataTypeIsComplex( eDataType ) )
                    {
                        int nWordSize;

                        nWordSize = GDALGetDataTypeSize(eDataType)/16;
                        GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
                        GDALSwapWords( ((GByte *) pabyData) + nWordSize, 
                                       nWordSize, nXSize, nPixelOffset );
                    }
                    else
                        GDALSwapWords( pabyData, nBandDataSize, nXSize,
                                       nPixelOffset );
                }

/* -------------------------------------------------------------------- */
/*      Seek to the right line in block.                                */
/* -------------------------------------------------------------------- */
                if( Seek( nBlockOff, SEEK_SET) == -1 )
                {
                    CPLError( CE_Failure, CPLE_FileIO,
                              "Failed to seek to " CPL_FRMT_GUIB " to read.\n",
                              nBlockOff );

                    return CE_Failure;
                }

/* -------------------------------------------------------------------- */
/*      Write the line of block.                                        */
/* -------------------------------------------------------------------- */
                nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW );
                if( nBytesActuallyWritten < nBytesToRW )
                {
                    CPLError( CE_Failure, CPLE_FileIO,
                              "Failed to write %d bytes to file. %d bytes written",
                              nBytesToRW, nBytesActuallyWritten );
            
                    return CE_Failure;
                }

/* -------------------------------------------------------------------- */
/*      Byte swap (if necessary) back into machine order so the         */
/*      buffer is still usable for reading purposes.                    */
/* -------------------------------------------------------------------- */
                if( !bNativeOrder && eDataType != GDT_Byte )
                {
                    if( GDALDataTypeIsComplex( eDataType ) )
                    {
                        int nWordSize;

                        nWordSize = GDALGetDataTypeSize(eDataType)/16;
                        GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
                        GDALSwapWords( ((GByte *) pabyData) + nWordSize, 
                                       nWordSize, nXSize, nPixelOffset );
                    }
                    else
                        GDALSwapWords( pabyData, nBandDataSize, nXSize,
                                       nPixelOffset );
                }

            }

            bDirty = TRUE;
            CPLFree( pabyData );
        }
    }

    return CE_None;
}
int CPL_STDCALL 
GDALChecksumImage( GDALRasterBandH hBand, 
                   int nXOff, int nYOff, int nXSize, int nYSize )

{
    VALIDATE_POINTER1( hBand, "GDALChecksumImage", 0 );

    const static int anPrimes[11] = 
        { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43 };

    int  iLine, i, nChecksum = 0, iPrime = 0, nCount;
    GDALDataType eDataType = GDALGetRasterDataType( hBand );
    int  bComplex = GDALDataTypeIsComplex( eDataType );
    
    if (eDataType == GDT_Float32 || eDataType == GDT_Float64 ||
        eDataType == GDT_CFloat32 || eDataType == GDT_CFloat64)
    {
        double* padfLineData;
        GDALDataType eDstDataType = (bComplex) ? GDT_CFloat64 : GDT_Float64;

        padfLineData = (double *) VSIMalloc2(nXSize, sizeof(double) * 2);
        if (padfLineData == NULL)
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                    "VSIMalloc2(): Out of memory in GDALChecksumImage. "
                    "Checksum value couldn't be computed\n");
            return 0;
        }

        for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
        {
            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1, 
                              padfLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
            {
                CPLError( CE_Failure, CPLE_FileIO,
                        "Checksum value couldn't be computed due to I/O read error.\n");
                break;
            }
            nCount = (bComplex) ? nXSize * 2 : nXSize;

            for( i = 0; i < nCount; i++ )
            {
                double dfVal = padfLineData[i];
                int nVal;
                if (CPLIsNan(dfVal) || CPLIsInf(dfVal))
                {
                    /* Most compilers seem to cast NaN or Inf to 0x80000000. */
                    /* but VC7 is an exception. So we force the result */
                    /* of such a cast */
                    nVal = 0x80000000;
                }
                else
                {
                    /* Standard behaviour of GDALCopyWords when converting */
                    /* from floating point to Int32 */
                    dfVal += 0.5;

                    if( dfVal < -2147483647.0 )
                        nVal = -2147483647;
                    else if( dfVal > 2147483647 )
                        nVal = 2147483647;
                    else
                        nVal = (GInt32) floor(dfVal);
                }

                nChecksum += (nVal % anPrimes[iPrime++]);
                if( iPrime > 10 )
                    iPrime = 0;

                nChecksum &= 0xffff;
            }
        }

        CPLFree(padfLineData);
    }
    else
    {
        int  *panLineData;
        GDALDataType eDstDataType = (bComplex) ? GDT_CInt32 : GDT_Int32;

        panLineData = (GInt32 *) VSIMalloc2(nXSize, sizeof(GInt32) * 2);
        if (panLineData == NULL)
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                    "VSIMalloc2(): Out of memory in GDALChecksumImage. "
                    "Checksum value couldn't be computed\n");
            return 0;
        }

        for( iLine = nYOff; iLine < nYOff + nYSize; iLine++ )
        {
            if (GDALRasterIO( hBand, GF_Read, nXOff, iLine, nXSize, 1, 
                            panLineData, nXSize, 1, eDstDataType, 0, 0 ) != CE_None)
            {
                CPLError( CE_Failure, CPLE_FileIO,
                        "Checksum value couldn't be computed due to I/O read error.\n");
                break;
            }
            nCount = (bComplex) ? nXSize * 2 : nXSize;

            for( i = 0; i < nCount; i++ )
            {
                nChecksum += (panLineData[i] % anPrimes[iPrime++]);
                if( iPrime > 10 )
                    iPrime = 0;

                nChecksum &= 0xffff;
            }
        }

        CPLFree( panLineData );
    }

    return nChecksum;
}
Exemple #26
0
CPLErr RawRasterBand::IWriteBlock( int nBlockXOff, int nBlockYOff,
                                   void * pImage )

{
    CPLErr		eErr = CE_None;

    CPLAssert( nBlockXOff == 0 );

    if (pLineBuffer == NULL)
        return CE_Failure;

/* -------------------------------------------------------------------- */
/*      If the data for this band is completely contiguous we don't     */
/*      have to worry about pre-reading from disk.                      */
/* -------------------------------------------------------------------- */
    if( ABS(nPixelOffset) > GDALGetDataTypeSize(eDataType) / 8 )
        eErr = AccessLine( nBlockYOff );

/* -------------------------------------------------------------------- */
/*	Copy data from user buffer into disk buffer.                    */
/* -------------------------------------------------------------------- */
    GDALCopyWords( pImage, eDataType, GDALGetDataTypeSize(eDataType)/8,
                   pLineStart, eDataType, nPixelOffset,
                   nBlockXSize );

/* -------------------------------------------------------------------- */
/*      Byte swap (if necessary) back into disk order before writing.   */
/* -------------------------------------------------------------------- */
    if( !bNativeOrder && eDataType != GDT_Byte )
    {
        if( GDALDataTypeIsComplex( eDataType ) )
        {
            int nWordSize;

            nWordSize = GDALGetDataTypeSize(eDataType)/16;
            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, 
                           ABS(nPixelOffset) );
            GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, 
                           nWordSize, nBlockXSize, ABS(nPixelOffset) );
        }
        else
            GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
                           nBlockXSize, ABS(nPixelOffset) );
    }

/* -------------------------------------------------------------------- */
/*      Figure out where to start reading.                              */
/* -------------------------------------------------------------------- */
    vsi_l_offset nWriteStart;
    if( nPixelOffset >= 0 )
        nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset;
    else
    {
        nWriteStart = nImgOffset + (vsi_l_offset)nBlockYOff * nLineOffset
            - ABS(nPixelOffset) * (nBlockXSize-1);
    }

/* -------------------------------------------------------------------- */
/*      Seek to correct location.                                       */
/* -------------------------------------------------------------------- */
    if( Seek( nWriteStart, SEEK_SET ) == -1 ) 
    {
        CPLError( CE_Failure, CPLE_FileIO,
                  "Failed to seek to scanline %d @ %d to write to file.\n",
                  nBlockYOff, (int) (nImgOffset + nBlockYOff * nLineOffset) );
        
        eErr = CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Write data buffer.                                              */
/* -------------------------------------------------------------------- */
    int	nBytesToWrite;

    nBytesToWrite = ABS(nPixelOffset) * (nBlockXSize - 1) 
        + GDALGetDataTypeSize(GetRasterDataType()) / 8;

    if( eErr == CE_None 
        && Write( pLineBuffer, 1, nBytesToWrite ) < (size_t) nBytesToWrite )
    {
        CPLError( CE_Failure, CPLE_FileIO,
                  "Failed to write scanline %d to file.\n",
                  nBlockYOff );
        
        eErr = CE_Failure;
    }
    
/* -------------------------------------------------------------------- */
/*      Byte swap (if necessary) back into machine order so the         */
/*      buffer is still usable for reading purposes.                    */
/* -------------------------------------------------------------------- */
    if( !bNativeOrder && eDataType != GDT_Byte )
    {
        if( GDALDataTypeIsComplex( eDataType ) )
        {
            int nWordSize;

            nWordSize = GDALGetDataTypeSize(eDataType)/16;
            GDALSwapWords( pLineBuffer, nWordSize, nBlockXSize, 
                           ABS(nPixelOffset) );
            GDALSwapWords( ((GByte *) pLineBuffer)+nWordSize, 
                           nWordSize, nBlockXSize, 
                           ABS(nPixelOffset) );
        }
        else
            GDALSwapWords( pLineBuffer, GDALGetDataTypeSize(eDataType)/8,
                           nBlockXSize, ABS(nPixelOffset) );
    }

    bDirty = TRUE;
    return eErr;
}
Exemple #27
0
CPLErr 
GTIFFBuildOverviews( const char * pszFilename,
                     int nBands, GDALRasterBand **papoBandList, 
                     int nOverviews, int * panOverviewList,
                     const char * pszResampling, 
                     GDALProgressFunc pfnProgress, void * pProgressData )

{
    TIFF    *hOTIFF;
    int     nBitsPerPixel=0, nCompression=COMPRESSION_NONE, nPhotometric=0;
    int     nSampleFormat=0, nPlanarConfig, iOverview, iBand;
    int     nXSize=0, nYSize=0;

    if( nBands == 0 || nOverviews == 0 )
        return CE_None;

    GTiffOneTimeInit();

/* -------------------------------------------------------------------- */
/*      Verify that the list of bands is suitable for emitting in       */
/*      TIFF file.                                                      */
/* -------------------------------------------------------------------- */
    for( iBand = 0; iBand < nBands; iBand++ )
    {
        int     nBandBits, nBandFormat;
        GDALRasterBand *hBand = papoBandList[iBand];

        switch( hBand->GetRasterDataType() )
        {
          case GDT_Byte:
            nBandBits = 8;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_UInt16:
            nBandBits = 16;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_Int16:
            nBandBits = 16;
            nBandFormat = SAMPLEFORMAT_INT;
            break;

          case GDT_UInt32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_UINT;
            break;

          case GDT_Int32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_INT;
            break;

          case GDT_Float32:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_IEEEFP;
            break;

          case GDT_Float64:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_IEEEFP;
            break;

          case GDT_CInt16:
            nBandBits = 32;
            nBandFormat = SAMPLEFORMAT_COMPLEXINT;
            break;

          case GDT_CFloat32:
            nBandBits = 64;
            nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
            break;

          case GDT_CFloat64:
            nBandBits = 128;
            nBandFormat = SAMPLEFORMAT_COMPLEXIEEEFP;
            break;

          default:
            CPLAssert( FALSE );
            return CE_Failure;
        }

        if( iBand == 0 )
        {
            nBitsPerPixel = nBandBits;
            nSampleFormat = nBandFormat;
            nXSize = hBand->GetXSize();
            nYSize = hBand->GetYSize();
        }
        else if( nBitsPerPixel != nBandBits || nSampleFormat != nBandFormat )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support a mixture of band"
                      " data types." );
            return CE_Failure;
        }
        else if( hBand->GetColorTable() != NULL )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support building"
                      " overviews of multiple colormapped bands." );
            return CE_Failure;
        }
        else if( hBand->GetXSize() != nXSize 
                 || hBand->GetYSize() != nYSize )
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "GTIFFBuildOverviews() doesn't support building"
                      " overviews of different sized bands." );
            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Use specified compression method.                               */
/* -------------------------------------------------------------------- */
    const char *pszCompress = CPLGetConfigOption( "COMPRESS_OVERVIEW", NULL );

    if( pszCompress != NULL && pszCompress[0] != '\0' )
    {
        if( EQUAL( pszCompress, "JPEG" ) )
            nCompression = COMPRESSION_JPEG;
        else if( EQUAL( pszCompress, "LZW" ) )
            nCompression = COMPRESSION_LZW;
        else if( EQUAL( pszCompress, "PACKBITS" ))
            nCompression = COMPRESSION_PACKBITS;
        else if( EQUAL( pszCompress, "DEFLATE" ) || EQUAL( pszCompress, "ZIP" ))
            nCompression = COMPRESSION_ADOBE_DEFLATE;
        else
            CPLError( CE_Warning, CPLE_IllegalArg, 
                      "COMPRESS_OVERVIEW=%s value not recognised, ignoring.",
                      pszCompress );
    }

/* -------------------------------------------------------------------- */
/*      Figure out the planar configuration to use.                     */
/* -------------------------------------------------------------------- */
    if( nBands == 1 )
        nPlanarConfig = PLANARCONFIG_CONTIG;
    else
        nPlanarConfig = PLANARCONFIG_SEPARATE;

    const char* pszInterleave = CPLGetConfigOption( "INTERLEAVE_OVERVIEW", NULL );
    if (pszInterleave != NULL && pszInterleave[0] != '\0')
    {
        if( EQUAL( pszInterleave, "PIXEL" ) )
            nPlanarConfig = PLANARCONFIG_CONTIG;
        else if( EQUAL( pszInterleave, "BAND" ) )
            nPlanarConfig = PLANARCONFIG_SEPARATE;
        else
        {
            CPLError( CE_Failure, CPLE_AppDefined, 
                      "INTERLEAVE_OVERVIEW=%s unsupported, value must be PIXEL or BAND. ignoring",
                      pszInterleave );
        }
    }

/* -------------------------------------------------------------------- */
/*      Figure out the photometric interpretation to use.               */
/* -------------------------------------------------------------------- */
    if( nBands == 3 )
        nPhotometric = PHOTOMETRIC_RGB;
    else if( papoBandList[0]->GetColorTable() != NULL 
             && !EQUALN(pszResampling,"AVERAGE_BIT2",12) )
    {
        nPhotometric = PHOTOMETRIC_PALETTE;
        /* should set the colormap up at this point too! */
    }
    else
        nPhotometric = PHOTOMETRIC_MINISBLACK;

    const char* pszPhotometric = CPLGetConfigOption( "PHOTOMETRIC_OVERVIEW", NULL );
    if (pszPhotometric != NULL && pszPhotometric[0] != '\0')
    {
        if( EQUAL( pszPhotometric, "MINISBLACK" ) )
            nPhotometric = PHOTOMETRIC_MINISBLACK;
        else if( EQUAL( pszPhotometric, "MINISWHITE" ) )
            nPhotometric = PHOTOMETRIC_MINISWHITE;
        else if( EQUAL( pszPhotometric, "RGB" ))
        {
            nPhotometric = PHOTOMETRIC_RGB;
        }
        else if( EQUAL( pszPhotometric, "CMYK" ))
        {
            nPhotometric = PHOTOMETRIC_SEPARATED;
        }
        else if( EQUAL( pszPhotometric, "YCBCR" ))
        {
            nPhotometric = PHOTOMETRIC_YCBCR;
        }
        else if( EQUAL( pszPhotometric, "CIELAB" ))
        {
            nPhotometric = PHOTOMETRIC_CIELAB;
        }
        else if( EQUAL( pszPhotometric, "ICCLAB" ))
        {
            nPhotometric = PHOTOMETRIC_ICCLAB;
        }
        else if( EQUAL( pszPhotometric, "ITULAB" ))
        {
            nPhotometric = PHOTOMETRIC_ITULAB;
        }
        else
        {
            CPLError( CE_Warning, CPLE_IllegalArg, 
                      "PHOTOMETRIC_OVERVIEW=%s value not recognised, ignoring.\n",
                      pszPhotometric );
        }
    }

/* -------------------------------------------------------------------- */
/*      Create the file, if it does not already exist.                  */
/* -------------------------------------------------------------------- */
    VSIStatBuf  sStatBuf;

    if( VSIStat( pszFilename, &sStatBuf ) != 0 )
    {
        hOTIFF = XTIFFOpen( pszFilename, "w+" );
        if( hOTIFF == NULL )
        {
            if( CPLGetLastErrorNo() == 0 )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Attempt to create new tiff file `%s'\n"
                          "failed in XTIFFOpen().\n",
                          pszFilename );

            return CE_Failure;
        }
    }
/* -------------------------------------------------------------------- */
/*      Otherwise just open it for update access.                       */
/* -------------------------------------------------------------------- */
    else 
    {
        hOTIFF = XTIFFOpen( pszFilename, "r+" );
        if( hOTIFF == NULL )
        {
            if( CPLGetLastErrorNo() == 0 )
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Attempt to create new tiff file `%s'\n"
                          "failed in XTIFFOpen().\n",
                          pszFilename );

            return CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we have a palette?  If so, create a TIFF compatible version. */
/* -------------------------------------------------------------------- */
    unsigned short      *panRed=NULL, *panGreen=NULL, *panBlue=NULL;

    if( nPhotometric == PHOTOMETRIC_PALETTE )
    {
        GDALColorTable *poCT = papoBandList[0]->GetColorTable();
        int nColorCount;

        if( nBitsPerPixel <= 8 )
            nColorCount = 256;
        else
            nColorCount = 65536;

        panRed   = (unsigned short *) 
            CPLCalloc(nColorCount,sizeof(unsigned short));
        panGreen = (unsigned short *) 
            CPLCalloc(nColorCount,sizeof(unsigned short));
        panBlue  = (unsigned short *) 
            CPLCalloc(nColorCount,sizeof(unsigned short));

        for( int iColor = 0; iColor < nColorCount; iColor++ )
        {
            GDALColorEntry  sRGB;

            if( poCT->GetColorEntryAsRGB( iColor, &sRGB ) )
            {
                panRed[iColor] = (unsigned short) (257 * sRGB.c1);
                panGreen[iColor] = (unsigned short) (257 * sRGB.c2);
                panBlue[iColor] = (unsigned short) (257 * sRGB.c3);
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Do we need some metadata for the overviews?                     */
/* -------------------------------------------------------------------- */
    CPLString osMetadata;
    GDALDataset *poBaseDS = papoBandList[0]->GetDataset();

    GTIFFBuildOverviewMetadata( pszResampling, poBaseDS, osMetadata );

/* -------------------------------------------------------------------- */
/*      Loop, creating overviews.                                       */
/* -------------------------------------------------------------------- */
    for( iOverview = 0; iOverview < nOverviews; iOverview++ )
    {
        int    nOXSize, nOYSize;
        uint32 nDirOffset;

        nOXSize = (nXSize + panOverviewList[iOverview] - 1) 
            / panOverviewList[iOverview];
        nOYSize = (nYSize + panOverviewList[iOverview] - 1) 
            / panOverviewList[iOverview];

        nDirOffset = 
            GTIFFWriteDirectory(hOTIFF, FILETYPE_REDUCEDIMAGE,
                                nOXSize, nOYSize, nBitsPerPixel, 
                                nPlanarConfig, nBands,
                                128, 128, TRUE, nCompression,
                                nPhotometric, nSampleFormat, 
                                panRed, panGreen, panBlue,
                                0, NULL, /* FIXME ? how can we fetch extrasamples from here */
                                osMetadata );
    }

    if (panRed)
    {
        CPLFree(panRed);
        CPLFree(panGreen);
        CPLFree(panBlue);
        panRed = panGreen = panBlue = NULL;
    }

    XTIFFClose( hOTIFF );

/* -------------------------------------------------------------------- */
/*      Open the overview dataset so that we can get at the overview    */
/*      bands.                                                          */
/* -------------------------------------------------------------------- */
    GDALDataset *hODS;

    hODS = (GDALDataset *) GDALOpen( pszFilename, GA_Update );
    if( hODS == NULL )
        return CE_Failure;
    
/* -------------------------------------------------------------------- */
/*      Loop writing overview data.                                     */
/* -------------------------------------------------------------------- */

    if (nCompression != COMPRESSION_NONE &&
        nPlanarConfig == PLANARCONFIG_CONTIG &&
        GDALDataTypeIsComplex(papoBandList[0]->GetRasterDataType()) == FALSE &&
        papoBandList[0]->GetColorTable() == NULL &&
        (EQUALN(pszResampling, "NEAR", 4) || EQUAL(pszResampling, "AVERAGE") || EQUAL(pszResampling, "GAUSS")))
    {
        /* In the case of pixel interleaved compressed overviews, we want to generate */
        /* the overviews for all the bands block by block, and not band after band, */
        /* in order to write the block once and not loose space in the TIFF file */

        GDALRasterBand ***papapoOverviewBands;

        papapoOverviewBands = (GDALRasterBand ***) CPLCalloc(sizeof(void*),nBands);
        for( iBand = 0; iBand < nBands; iBand++ )
        {
            GDALRasterBand    *hDstBand = hODS->GetRasterBand( iBand+1 );
            papapoOverviewBands[iBand] = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews);
            papapoOverviewBands[iBand][0] = hDstBand;
            for( int i = 0; i < nOverviews-1; i++ )
            {
                papapoOverviewBands[iBand][i+1] = hDstBand->GetOverview(i);
            }
        }

        GDALRegenerateOverviewsMultiBand(nBands, papoBandList,
                                         nOverviews, papapoOverviewBands,
                                         pszResampling, pfnProgress, pProgressData );

        for( iBand = 0; iBand < nBands; iBand++ )
        {
            CPLFree(papapoOverviewBands[iBand]);
        }
        CPLFree(papapoOverviewBands);
    }
    else
    {
        GDALRasterBand   **papoOverviews;

        papoOverviews = (GDALRasterBand **) CPLCalloc(sizeof(void*),128);

        for( iBand = 0; iBand < nBands; iBand++ )
        {
            GDALRasterBand    *hSrcBand = papoBandList[iBand];
            GDALRasterBand    *hDstBand;
            int               nDstOverviews;
            CPLErr            eErr;

            hDstBand = hODS->GetRasterBand( iBand+1 );

            papoOverviews[0] = hDstBand;
            nDstOverviews = hDstBand->GetOverviewCount() + 1;
            CPLAssert( nDstOverviews < 128 );
            nDstOverviews = MIN(128,nDstOverviews);

            for( int i = 0; i < nDstOverviews-1; i++ )
            {
                papoOverviews[i+1] = hDstBand->GetOverview(i);
            }

            void         *pScaledProgressData;

            pScaledProgressData = 
                GDALCreateScaledProgress( iBand / (double) nBands, 
                                        (iBand+1) / (double) nBands,
                                        pfnProgress, pProgressData );

            eErr = 
                GDALRegenerateOverviews( (GDALRasterBandH) hSrcBand, 
                                        nDstOverviews, 
                                        (GDALRasterBandH *) papoOverviews, 
                                        pszResampling,
                                        GDALScaledProgress, 
                                        pScaledProgressData);

            GDALDestroyScaledProgress( pScaledProgressData );

            if( eErr != CE_None )
            {
                delete hODS;
                return eErr;
            }
        }

        CPLFree( papoOverviews );
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    hODS->FlushCache();
    delete hODS;

    pfnProgress( 1.0, NULL, pProgressData );

    return CE_None;
}
Exemple #28
0
CPLErr RawRasterBand::IRasterIO( GDALRWFlag eRWFlag,
                                 int nXOff, int nYOff, int nXSize, int nYSize,
                                 void * pData, int nBufXSize, int nBufYSize,
                                 GDALDataType eBufType,
                                 int nPixelSpace, int nLineSpace )

{
    int         nBandDataSize = GDALGetDataTypeSize(eDataType) / 8;
    int         nBufDataSize = GDALGetDataTypeSize( eBufType ) / 8;
    int         nBytesToRW = nPixelOffset * nXSize;

/* -------------------------------------------------------------------- */
/* Use direct IO without caching if:                                    */
/*                                                                      */
/* GDAL_ONE_BIG_READ is enabled                                         */
/*                                                                      */
/* or                                                                   */
/*                                                                      */
/* the length of a scanline on disk is more than 50000 bytes, and the   */
/* width of the requested chunk is less than 40% of the whole scanline  */
/* and none of the requested scanlines are already in the cache.        */
/* -------------------------------------------------------------------- */
    if( nPixelOffset < 0 ) 
    {
        return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
                                          nXSize, nYSize,
                                          pData, nBufXSize, nBufYSize,
                                          eBufType,
                                          nPixelSpace, nLineSpace );
    }

    if ( !CSLTestBoolean( CPLGetConfigOption( "GDAL_ONE_BIG_READ", "NO") ) )
    {
        if ( nLineSize < 50000
             || nBytesToRW > nLineSize / 5 * 2
             || IsLineLoaded( nYOff, nYSize ) )
        {

            return GDALRasterBand::IRasterIO( eRWFlag, nXOff, nYOff,
                                              nXSize, nYSize,
                                              pData, nBufXSize, nBufYSize,
                                              eBufType,
                                              nPixelSpace, nLineSpace );
        }
    }

/* ==================================================================== */
/*   Read data.                                                         */
/* ==================================================================== */
    if ( eRWFlag == GF_Read )
    {
/* -------------------------------------------------------------------- */
/*      Do we have overviews that would be appropriate to satisfy       */
/*      this request?                                                   */
/* -------------------------------------------------------------------- */
        if( (nBufXSize < nXSize || nBufYSize < nYSize)
            && GetOverviewCount() > 0 )
        {
            if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
                                  pData, nBufXSize, nBufYSize, 
                                  eBufType, nPixelSpace, nLineSpace ) == CE_None )
                return CE_None;
        }

/* ==================================================================== */
/*   1. Simplest case when we should get contiguous block               */
/*   of uninterleaved pixels.                                           */
/* ==================================================================== */
        if ( nXSize == GetXSize() 
             && nXSize == nBufXSize
             && nYSize == nBufYSize
             && eBufType == eDataType
             && nPixelOffset == nBandDataSize
             && nPixelSpace == nBufDataSize
             && nLineSpace == nPixelSpace * nXSize )
        {
            if ( AccessBlock( nImgOffset
                              + (vsi_l_offset)nYOff * nLineOffset + nXOff,
                              nXSize * nYSize * nBandDataSize, pData ) != CE_None )
            {
                CPLError( CE_Failure, CPLE_FileIO,
                          "Failed to read %d bytes at %lu.",
                          nXSize * nYSize * nBandDataSize,
                          (unsigned long)
                          (nImgOffset + (vsi_l_offset)nYOff * nLineOffset
                           + nXOff) );
            }
        }

/* ==================================================================== */
/*   2. Case when we need deinterleave and/or subsample data.           */
/* ==================================================================== */
        else
        {
            GByte   *pabyData;
            double  dfSrcXInc, dfSrcYInc;
            int     iLine;
            
            dfSrcXInc = (double)nXSize / nBufXSize;
            dfSrcYInc = (double)nYSize / nBufYSize;


            pabyData = (GByte *) CPLMalloc( nBytesToRW );

            for ( iLine = 0; iLine < nBufYSize; iLine++ )
            {
                if ( AccessBlock( nImgOffset
                                  + ((vsi_l_offset)nYOff
                                  + (int)(iLine * dfSrcYInc)) * nLineOffset
                                  + nXOff * nPixelOffset,
                                  nBytesToRW, pabyData ) != CE_None )
                {
                    CPLError( CE_Failure, CPLE_FileIO,
                              "Failed to read %d bytes at %lu.",
                              nBytesToRW,
                              (unsigned long)(nImgOffset
                              + ((vsi_l_offset)nYOff
                              + (int)(iLine * dfSrcYInc)) * nLineOffset
                              + nXOff * nPixelOffset) );
                }

/* -------------------------------------------------------------------- */
/*      Copy data from disk buffer to user block buffer and subsample,  */
/*      if needed.                                                      */
/* -------------------------------------------------------------------- */
                if ( nXSize == nBufXSize && nYSize == nBufYSize )
                {
                    GDALCopyWords( pabyData, eDataType, nPixelOffset,
                                   (GByte *)pData + iLine * nLineSpace,
                                   eBufType, nPixelSpace, nXSize );
                }
                else
                {
                    int     iPixel;

                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                    {
                        GDALCopyWords( pabyData +
                                       (int)(iPixel * dfSrcXInc) * nPixelOffset,
                                       eDataType, 0,
                                       (GByte *)pData + iLine * nLineSpace +
                                       iPixel * nBufDataSize,
                                       eBufType, nPixelSpace, 1 );
                    }
                }
            }

            CPLFree( pabyData );
        }
    }

/* ==================================================================== */
/*   Write data.                                                        */
/* ==================================================================== */
    else
    {
        int nBytesActuallyWritten;

/* ==================================================================== */
/*   1. Simplest case when we should write contiguous block             */
/*   of uninterleaved pixels.                                           */
/* ==================================================================== */
        if ( nXSize == GetXSize() 
             && nXSize == nBufXSize
             && nYSize == nBufYSize
             && eBufType == eDataType
             && nPixelOffset == nBandDataSize
             && nPixelSpace == nBufDataSize
             && nLineSpace == nPixelSpace * nXSize )
        {
/* -------------------------------------------------------------------- */
/*      Byte swap the data buffer, if required.                         */
/* -------------------------------------------------------------------- */
            if( !bNativeOrder && eDataType != GDT_Byte )
            {
                if( GDALDataTypeIsComplex( eDataType ) )
                {
                    int nWordSize;

                    nWordSize = GDALGetDataTypeSize(eDataType)/16;
                    GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
                    GDALSwapWords( ((GByte *) pData) + nWordSize, 
                                   nWordSize, nXSize, nPixelOffset );
                }
                else
                    GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
            }

/* -------------------------------------------------------------------- */
/*      Seek to the right block.                                        */
/* -------------------------------------------------------------------- */
            if( Seek( nImgOffset + (vsi_l_offset)nYOff * nLineOffset + nXOff,
                      SEEK_SET) == -1 )
            {
                CPLError( CE_Failure, CPLE_FileIO,
                          "Failed to seek to %lu to write data.\n",
                          (unsigned long)(nImgOffset + (vsi_l_offset)nYOff
                                          * nLineOffset + nXOff) );
        
                return CE_Failure;
            }

/* -------------------------------------------------------------------- */
/*      Write the block.                                                */
/* -------------------------------------------------------------------- */
            nBytesToRW = nXSize * nYSize * nBandDataSize;

            nBytesActuallyWritten = Write( pData, 1, nBytesToRW );
            if( nBytesActuallyWritten < nBytesToRW )
            {
                CPLError( CE_Failure, CPLE_FileIO,
                          "Failed to write %d bytes to file. %d bytes written",
                          nBytesToRW, nBytesActuallyWritten );
        
                return CE_Failure;
            }

/* -------------------------------------------------------------------- */
/*      Byte swap (if necessary) back into machine order so the         */
/*      buffer is still usable for reading purposes.                    */
/* -------------------------------------------------------------------- */
            if( !bNativeOrder  && eDataType != GDT_Byte )
            {
                if( GDALDataTypeIsComplex( eDataType ) )
                {
                    int nWordSize;

                    nWordSize = GDALGetDataTypeSize(eDataType)/16;
                    GDALSwapWords( pData, nWordSize, nXSize, nPixelOffset );
                    GDALSwapWords( ((GByte *) pData) + nWordSize, 
                                   nWordSize, nXSize, nPixelOffset );
                }
                else
                    GDALSwapWords( pData, nBandDataSize, nXSize, nPixelOffset );
            }
        }

/* ==================================================================== */
/*   2. Case when we need deinterleave and/or subsample data.           */
/* ==================================================================== */
        else
        {
            GByte   *pabyData;
            double  dfSrcXInc, dfSrcYInc;
            vsi_l_offset nBlockOff;
            int     iLine;
            
            dfSrcXInc = (double)nXSize / nBufXSize;
            dfSrcYInc = (double)nYSize / nBufYSize;

            pabyData = (GByte *) CPLMalloc( nBytesToRW );

            for ( iLine = 0; iLine < nBufYSize; iLine++ )
            {
                nBlockOff = nImgOffset
                    + ((vsi_l_offset)nYOff + (int)(iLine*dfSrcYInc))*nLineOffset
                    + nXOff * nPixelOffset;

/* -------------------------------------------------------------------- */
/*      If the data for this band is completely contiguous we don't     */
/*      have to worry about pre-reading from disk.                      */
/* -------------------------------------------------------------------- */
                if( nPixelOffset > nBandDataSize )
                    AccessBlock( nBlockOff, nBytesToRW, pabyData );

/* -------------------------------------------------------------------- */
/*      Copy data from user block buffer to disk buffer and subsample,  */
/*      if needed.                                                      */
/* -------------------------------------------------------------------- */
                if ( nXSize == nBufXSize && nYSize == nBufYSize )
                {
                    GDALCopyWords( (GByte *)pData + iLine * nLineSpace,
                                   eBufType, nPixelSpace,
                                   pabyData, eDataType, nPixelOffset, nXSize );
                }
                else
                {
                    int     iPixel;

                    for ( iPixel = 0; iPixel < nBufXSize; iPixel++ )
                    {
                        GDALCopyWords( (GByte *)pData+iLine*nLineSpace +
                                       iPixel * nBufDataSize,
                                       eBufType, nPixelSpace,
                                       pabyData +
                                       (int)(iPixel * dfSrcXInc) * nPixelOffset,
                                       eDataType, 0, 1 );
                    }
                }

/* -------------------------------------------------------------------- */
/*      Byte swap the data buffer, if required.                         */
/* -------------------------------------------------------------------- */
                if( !bNativeOrder && eDataType != GDT_Byte )
                {
                    if( GDALDataTypeIsComplex( eDataType ) )
                    {
                        int nWordSize;

                        nWordSize = GDALGetDataTypeSize(eDataType)/16;
                        GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
                        GDALSwapWords( ((GByte *) pabyData) + nWordSize, 
                                       nWordSize, nXSize, nPixelOffset );
                    }
                    else
                        GDALSwapWords( pabyData, nBandDataSize, nXSize,
                                       nPixelOffset );
                }

/* -------------------------------------------------------------------- */
/*      Seek to the right line in block.                                */
/* -------------------------------------------------------------------- */
                if( Seek( nBlockOff, SEEK_SET) == -1 )
                {
                    CPLError( CE_Failure, CPLE_FileIO,
                              "Failed to seek to %ld to read.\n",
                              (long)nBlockOff );

                    return CE_Failure;
                }

/* -------------------------------------------------------------------- */
/*      Write the line of block.                                        */
/* -------------------------------------------------------------------- */
                nBytesActuallyWritten = Write( pabyData, 1, nBytesToRW );
                if( nBytesActuallyWritten < nBytesToRW )
                {
                    CPLError( CE_Failure, CPLE_FileIO,
                              "Failed to write %d bytes to file. %d bytes written",
                              nBytesToRW, nBytesActuallyWritten );
            
                    return CE_Failure;
                }

/* -------------------------------------------------------------------- */
/*      Byte swap (if necessary) back into machine order so the         */
/*      buffer is still usable for reading purposes.                    */
/* -------------------------------------------------------------------- */
                if( !bNativeOrder && eDataType != GDT_Byte )
                {
                    if( GDALDataTypeIsComplex( eDataType ) )
                    {
                        int nWordSize;

                        nWordSize = GDALGetDataTypeSize(eDataType)/16;
                        GDALSwapWords( pabyData, nWordSize, nXSize, nPixelOffset );
                        GDALSwapWords( ((GByte *) pabyData) + nWordSize, 
                                       nWordSize, nXSize, nPixelOffset );
                    }
                    else
                        GDALSwapWords( pabyData, nBandDataSize, nXSize,
                                       nPixelOffset );
                }

            }

            bDirty = TRUE;
            CPLFree( pabyData );
        }
    }

    return CE_None;
}
CPLErr PhasePixelFunc(void **papoSources, int nSources, void *pData,
                      int nXSize, int nYSize,
                      GDALDataType eSrcType, GDALDataType eBufType,
                      int nPixelSpace, int nLineSpace)
{
    int ii, iLine, iCol;
    double dfPixVal, dfReal;

    /* ---- Init ---- */
    if (nSources != 1) return CE_Failure;

    if (GDALDataTypeIsComplex( eSrcType ))
    {
        double dfImag;
        void *pReal = papoSources[0];
        void *pImag = ((GByte *)papoSources[0])
                    + GDALGetDataTypeSize( eSrcType ) / 8 / 2;

        /* ---- Set pixels ---- */
        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfReal = SRCVAL(pReal, eSrcType, ii);
                dfImag = SRCVAL(pImag, eSrcType, ii);

                dfPixVal = atan2(dfImag, dfReal);

                GDALCopyWords(&dfPixVal, GDT_Float64, 0,
                          ((GByte *)pData) + nLineSpace * iLine +
                          iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    } else {
        /* ---- Set pixels ---- */
        /*
        for( iLine = 0; iLine < nYSize; ++iLine ) {
            / * always copy from the same location * /
            GDALCopyWords(&dfImag, eSrcType, 0,
                          ((GByte *)pData) + nLineSpace * iLine,
                          eBufType, nPixelSpace, nXSize);
        }
        */
        /* ---- Set pixels ---- */
        double pi = atan2(0, -1);
        for( iLine = 0, ii= 0; iLine < nYSize; ++iLine ) {
            for( iCol = 0; iCol < nXSize; ++iCol, ++ii ) {

                void *pReal = papoSources[0];

                /* Source raster pixels may be obtained with SRCVAL macro */
                dfReal = SRCVAL(pReal, eSrcType, ii);
                dfPixVal = (dfReal < 0) ? pi : 0;

                GDALCopyWords(&dfPixVal, GDT_Float64, dfPixVal,
                          ((GByte *)pData) + nLineSpace * iLine +
                          iCol * nPixelSpace, eBufType, nPixelSpace, 1);
            }
        }
    }

    /* ---- Return success ---- */
    return CE_None;
} /* PhasePixelFunc */