Example #1
0
static CPLErr
GDALMultiFilter( GDALRasterBandH hTargetBand,
                 GDALRasterBandH hTargetMaskBand,
                 GDALRasterBandH hFiltMaskBand,
                 int nIterations,
                 GDALProgressFunc pfnProgress,
                 void * pProgressArg )

{
    const int nXSize = GDALGetRasterBandXSize(hTargetBand);
    const int nYSize = GDALGetRasterBandYSize(hTargetBand);

/* -------------------------------------------------------------------- */
/*      Report starting progress value.                                 */
/* -------------------------------------------------------------------- */
    if( !pfnProgress( 0.0, "Smoothing Filter...", pProgressArg ) )
    {
        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Allocate rotating buffers.                                      */
/* -------------------------------------------------------------------- */
    const int nBufLines = nIterations + 2;

    GByte *pabyTMaskBuf =
        static_cast<GByte *>(VSI_MALLOC2_VERBOSE(nXSize, nBufLines));
    GByte *pabyFMaskBuf =
        static_cast<GByte *>(VSI_MALLOC2_VERBOSE(nXSize, nBufLines));

    float *paf3PassLineBuf = static_cast<float *>(
        VSI_MALLOC3_VERBOSE(nXSize, nBufLines, 3 * sizeof(float)));
    if( pabyTMaskBuf == nullptr || pabyFMaskBuf == nullptr ||
        paf3PassLineBuf == nullptr )
    {
        CPLFree( pabyTMaskBuf );
        CPLFree( pabyFMaskBuf );
        CPLFree( paf3PassLineBuf );

        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Process rotating buffers.                                       */
/* -------------------------------------------------------------------- */

    CPLErr eErr = CE_None;

    int iPassCounter = 0;

    for( int nNewLine = 0;  // Line being loaded (zero based scanline).
         eErr == CE_None && nNewLine < nYSize+nIterations;
         nNewLine++ )
    {
/* -------------------------------------------------------------------- */
/*      Rotate pass buffers.                                            */
/* -------------------------------------------------------------------- */
        iPassCounter = (iPassCounter + 1) % 3;

        float * const pafSLastPass =
            paf3PassLineBuf + ((iPassCounter + 0) % 3) * nXSize * nBufLines;
        float * const pafLastPass =
            paf3PassLineBuf + ((iPassCounter + 1) % 3) * nXSize * nBufLines;
        float * const pafThisPass =
            paf3PassLineBuf + ((iPassCounter + 2) % 3) * nXSize * nBufLines;

/* -------------------------------------------------------------------- */
/*      Where does the new line go in the rotating buffer?              */
/* -------------------------------------------------------------------- */
        const int iBufOffset = nNewLine % nBufLines;

/* -------------------------------------------------------------------- */
/*      Read the new data line if it is't off the bottom of the         */
/*      image.                                                          */
/* -------------------------------------------------------------------- */
        if( nNewLine < nYSize )
        {
            eErr =
                GDALRasterIO( hTargetMaskBand, GF_Read,
                              0, nNewLine, nXSize, 1,
                              pabyTMaskBuf + nXSize * iBufOffset, nXSize, 1,
                              GDT_Byte, 0, 0 );

            if( eErr != CE_None )
                break;

            eErr =
                GDALRasterIO( hFiltMaskBand, GF_Read,
                              0, nNewLine, nXSize, 1,
                              pabyFMaskBuf + nXSize * iBufOffset, nXSize, 1,
                              GDT_Byte, 0, 0 );

            if( eErr != CE_None )
                break;

            eErr =
                GDALRasterIO( hTargetBand, GF_Read,
                              0, nNewLine, nXSize, 1,
                              pafThisPass + nXSize * iBufOffset, nXSize, 1,
                              GDT_Float32, 0, 0 );

            if( eErr != CE_None )
                break;
        }

/* -------------------------------------------------------------------- */
/*      Loop over the loaded data, applying the filter to all loaded    */
/*      lines with neighbours.                                          */
/* -------------------------------------------------------------------- */
        for( int iFLine = nNewLine-1;
             eErr == CE_None && iFLine >= nNewLine-nIterations;
             iFLine-- )
        {
            const int iLastOffset = (iFLine-1) % nBufLines;
            const int iThisOffset = (iFLine  ) % nBufLines;
            const int iNextOffset = (iFLine+1) % nBufLines;

            // Default to preserving the old value.
            if( iFLine >= 0 )
                memcpy( pafThisPass + iThisOffset * nXSize,
                        pafLastPass + iThisOffset * nXSize,
                        sizeof(float) * nXSize );

            // TODO: Enable first and last line.
            // Skip the first and last line.
            if( iFLine < 1 || iFLine >= nYSize-1 )
            {
                continue;
            }

            GDALFilterLine(
                pafSLastPass + iLastOffset * nXSize,
                pafLastPass  + iThisOffset * nXSize,
                pafThisPass  + iNextOffset * nXSize,
                pafThisPass  + iThisOffset * nXSize,
                pabyTMaskBuf + iLastOffset * nXSize,
                pabyTMaskBuf + iThisOffset * nXSize,
                pabyTMaskBuf + iNextOffset * nXSize,
                pabyFMaskBuf + iThisOffset * nXSize,
                nXSize );
        }

/* -------------------------------------------------------------------- */
/*      Write out the top data line that will be rolling out of our     */
/*      buffer.                                                         */
/* -------------------------------------------------------------------- */
        const int iLineToSave = nNewLine - nIterations;

        if( iLineToSave >= 0 && eErr == CE_None )
        {
            const int iBufOffset2 = iLineToSave % nBufLines;

            eErr =
                GDALRasterIO( hTargetBand, GF_Write,
                              0, iLineToSave, nXSize, 1,
                              pafThisPass + nXSize * iBufOffset2, nXSize, 1,
                              GDT_Float32, 0, 0 );
        }

/* -------------------------------------------------------------------- */
/*      Report progress.                                                */
/* -------------------------------------------------------------------- */
        if( eErr == CE_None &&
            !pfnProgress(
                (nNewLine + 1) / static_cast<double>(nYSize+nIterations),
                "Smoothing Filter...", pProgressArg) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            eErr = CE_Failure;
        }
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    CPLFree( pabyTMaskBuf );
    CPLFree( pabyFMaskBuf );
    CPLFree( paf3PassLineBuf );

    return eErr;
}
Example #2
0
CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
                                       void * pImage )

{
    GDALDataType eWrkDT = GetWorkDataType( poParent->GetRasterDataType() );

/* -------------------------------------------------------------------- */
/*      Read the image data.                                            */
/* -------------------------------------------------------------------- */
    // TODO(schwehr): pabySrc would probably be better as a void ptr.
    GByte *pabySrc = static_cast<GByte *>(
        VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDT),
                             nBlockXSize, nBlockYSize ) );
    if (pabySrc == nullptr)
    {
        return CE_Failure;
    }

    int nXSizeRequest = nBlockXSize;
    if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize)
        nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize;
    int nYSizeRequest = nBlockYSize;
    if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize)
        nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize;

    if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
    {
        // memset the whole buffer to avoid Valgrind warnings in case RasterIO
        // fetches a partial block.
        memset( pabySrc, 0,
                GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize );
    }

    CPLErr eErr =
        poParent->RasterIO( GF_Read,
                            nXBlockOff * nBlockXSize,
                            nYBlockOff * nBlockYSize,
                            nXSizeRequest, nYSizeRequest,
                            pabySrc, nXSizeRequest, nYSizeRequest,
                            eWrkDT, 0,
                            nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
                            nullptr );
    if( eErr != CE_None )
    {
        CPLFree(pabySrc);
        return eErr;
    }

    const bool bIsNoDataNan = CPLIsNan(dfNoDataValue) != 0;

/* -------------------------------------------------------------------- */
/*      Process different cases.                                        */
/* -------------------------------------------------------------------- */
    switch( eWrkDT )
    {
      case GDT_Byte:
      {
        GByte byNoData = static_cast<GByte>( dfNoDataValue );

        for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
        {
            static_cast<GByte *>(pImage)[i] = pabySrc[i] == byNoData ? 0: 255;
        }
      }
      break;

      case GDT_UInt32:
      {
        GUInt32 nNoData = static_cast<GUInt32>( dfNoDataValue );

        for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
        {
            static_cast<GByte *>(pImage)[i] =
                reinterpret_cast<GUInt32 *>(pabySrc)[i] == nNoData ? 0 : 255;
        }
      }
      break;

      case GDT_Int32:
      {
        GInt32 nNoData = static_cast<GInt32>( dfNoDataValue );

        for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
        {
            static_cast<GByte *>(pImage)[i] =
                reinterpret_cast<GInt32 *>(pabySrc)[i] == nNoData ? 0 : 255;
        }
      }
      break;

      case GDT_Float32:
      {
        float fNoData = static_cast<float>( dfNoDataValue );

        for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
        {
            const float fVal = reinterpret_cast<float *>(pabySrc)[i];
            if( bIsNoDataNan && CPLIsNan(fVal))
                static_cast<GByte *>(pImage)[i] = 0;
            else if( ARE_REAL_EQUAL(fVal, fNoData) )
                static_cast<GByte *>(pImage)[i] = 0;
            else
                static_cast<GByte *>(pImage)[i] = 255;
        }
      }
      break;

      case GDT_Float64:
      {
          for( int i = 0; i < nBlockXSize * nBlockYSize; i++ )
          {
              const double dfVal = reinterpret_cast<double *>(pabySrc)[i];
              if( bIsNoDataNan && CPLIsNan(dfVal))
                  static_cast<GByte *>(pImage)[i] = 0;
              else if( ARE_REAL_EQUAL(dfVal, dfNoDataValue) )
                  static_cast<GByte *>(pImage)[i] = 0;
              else
                  static_cast<GByte *>(pImage)[i] = 255;
          }
      }
      break;

      default:
        CPLAssert( false );
        break;
    }

    CPLFree( pabySrc );

    return CE_None;
}
CPLErr GDALNoDataMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
                                         void * pImage )

{
    GDALDataType eWrkDT;

/* -------------------------------------------------------------------- */
/*      Decide on a working type.                                       */
/* -------------------------------------------------------------------- */
    switch( poParent->GetRasterDataType() )
    {
      case GDT_Byte:
        eWrkDT = GDT_Byte;
        break;

      case GDT_UInt16:
      case GDT_UInt32:
        eWrkDT = GDT_UInt32;
        break;

      case GDT_Int16:
      case GDT_Int32:
      case GDT_CInt16:
      case GDT_CInt32:
        eWrkDT = GDT_Int32;
        break;

      case GDT_Float32:
      case GDT_CFloat32:
        eWrkDT = GDT_Float32;
        break;

      case GDT_Float64:
      case GDT_CFloat64:
        eWrkDT = GDT_Float64;
        break;

      default:
        CPLAssert( FALSE );
        eWrkDT = GDT_Float64;
        break;
    }

/* -------------------------------------------------------------------- */
/*      Read the image data.                                            */
/* -------------------------------------------------------------------- */
    CPLErr eErr;

    GByte *pabySrc = static_cast<GByte *>(
        VSI_MALLOC3_VERBOSE( GDALGetDataTypeSizeBytes(eWrkDT),
                             nBlockXSize, nBlockYSize ) );
    if (pabySrc == NULL)
    {
        return CE_Failure;
    }


    int nXSizeRequest = nBlockXSize;
    if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize)
        nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize;
    int nYSizeRequest = nBlockYSize;
    if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize)
        nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize;

    if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
    {
        /* memset the whole buffer to avoid Valgrind warnings in case we can't */
        /* fetch a full block */
        memset( pabySrc, 0,
                GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize );
    }

    eErr = poParent->RasterIO( GF_Read,
                               nXBlockOff * nBlockXSize,
                               nYBlockOff * nBlockYSize,
                               nXSizeRequest, nYSizeRequest,
                               pabySrc, nXSizeRequest, nYSizeRequest,
                               eWrkDT, 0,
                               nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
                               NULL );
    if( eErr != CE_None )
    {
        CPLFree(pabySrc);
        return eErr;
    }

    int bIsNoDataNan = CPLIsNan(dfNoDataValue);

/* -------------------------------------------------------------------- */
/*      Process different cases.                                        */
/* -------------------------------------------------------------------- */
    int i;
    switch( eWrkDT )
    {
      case GDT_Byte:
      {
          GByte byNoData = (GByte) dfNoDataValue;

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              if( pabySrc[i] == byNoData )
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }
      }
      break;

      case GDT_UInt32:
      {
          GUInt32 nNoData = (GUInt32) dfNoDataValue;

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              if( ((GUInt32 *)pabySrc)[i] == nNoData )
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }
      }
      break;

      case GDT_Int32:
      {
          GInt32 nNoData = (GInt32) dfNoDataValue;

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              if( ((GInt32 *)pabySrc)[i] == nNoData )
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }
      }
      break;

      case GDT_Float32:
      {
          float fNoData = (float) dfNoDataValue;

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              float fVal =((float *)pabySrc)[i];
              if( bIsNoDataNan && CPLIsNan(fVal))
                  ((GByte *) pImage)[i] = 0;
              else if( ARE_REAL_EQUAL(fVal, fNoData) )
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }
      }
      break;

      case GDT_Float64:
      {
          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              double dfVal =((double *)pabySrc)[i];
              if( bIsNoDataNan && CPLIsNan(dfVal))
                  ((GByte *) pImage)[i] = 0;
              else if( ARE_REAL_EQUAL(dfVal, dfNoDataValue) )
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }
      }
      break;

      default:
        CPLAssert( FALSE );
        break;
    }

    CPLFree( pabySrc );

    return CE_None;
}
Example #4
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;
}
CPLErr GDALNoDataValuesMaskBand::IReadBlock( int nXBlockOff, int nYBlockOff,
                                         void * pImage )

{
    int iBand;
    GDALDataType eWrkDT;

/* -------------------------------------------------------------------- */
/*      Decide on a working type.                                       */
/* -------------------------------------------------------------------- */
    switch( poDS->GetRasterBand(1)->GetRasterDataType() )
    {
      case GDT_Byte:
        eWrkDT = GDT_Byte;
        break;

      case GDT_UInt16:
      case GDT_UInt32:
        eWrkDT = GDT_UInt32;
        break;

      case GDT_Int16:
      case GDT_Int32:
      case GDT_CInt16:
      case GDT_CInt32:
        eWrkDT = GDT_Int32;
        break;

      case GDT_Float32:
      case GDT_CFloat32:
        eWrkDT = GDT_Float32;
        break;

      case GDT_Float64:
      case GDT_CFloat64:
        eWrkDT = GDT_Float64;
        break;

      default:
        CPLAssert( FALSE );
        eWrkDT = GDT_Float64;
        break;
    }

/* -------------------------------------------------------------------- */
/*      Read the image data.                                            */
/* -------------------------------------------------------------------- */
    CPLErr eErr;

    int nBands = poDS->GetRasterCount();
    GByte *pabySrc = static_cast<GByte *>(
        VSI_MALLOC3_VERBOSE( nBands * GDALGetDataTypeSizeBytes(eWrkDT),
                             nBlockXSize, nBlockYSize ) );
    if (pabySrc == NULL)
    {
        return CE_Failure;
    }

    int nXSizeRequest = nBlockXSize;
    if (nXBlockOff * nBlockXSize + nBlockXSize > nRasterXSize)
        nXSizeRequest = nRasterXSize - nXBlockOff * nBlockXSize;
    int nYSizeRequest = nBlockYSize;
    if (nYBlockOff * nBlockYSize + nBlockYSize > nRasterYSize)
        nYSizeRequest = nRasterYSize - nYBlockOff * nBlockYSize;

    if (nXSizeRequest != nBlockXSize || nYSizeRequest != nBlockYSize)
    {
        /* memset the whole buffer to avoid Valgrind warnings in case we can't */
        /* fetch a full block */
        memset( pabySrc, 0,
                nBands * GDALGetDataTypeSizeBytes(eWrkDT) *
                nBlockXSize * nBlockYSize );
    }

    int nBlockOffsetPixels = nBlockXSize * nBlockYSize;
    const int nBandOffsetByte =
        GDALGetDataTypeSizeBytes(eWrkDT) * nBlockXSize * nBlockYSize;
    for(iBand=0;iBand<nBands;iBand++)
    {
        eErr = poDS->GetRasterBand(iBand + 1)->RasterIO(
            GF_Read,
            nXBlockOff * nBlockXSize,
            nYBlockOff * nBlockYSize,
            nXSizeRequest,
            nYSizeRequest,
            pabySrc + iBand * nBandOffsetByte,
            nXSizeRequest,
            nYSizeRequest,
            eWrkDT, 0,
            nBlockXSize * GDALGetDataTypeSizeBytes(eWrkDT),
            NULL );
        if( eErr != CE_None )
            return eErr;
    }

/* -------------------------------------------------------------------- */
/*      Process different cases.                                        */
/* -------------------------------------------------------------------- */
    int i;
    switch( eWrkDT )
    {
      case GDT_Byte:
      {
          GByte* pabyNoData = (GByte*) CPLMalloc(nBands * sizeof(GByte));
          for(iBand=0;iBand<nBands;iBand++)
          {
              pabyNoData[iBand] = (GByte)padfNodataValues[iBand];
          }

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              int nCountNoData = 0;
              for(iBand=0;iBand<nBands;iBand++)
              {
                  if( pabySrc[i + iBand * nBlockOffsetPixels] == pabyNoData[iBand] )
                      nCountNoData ++;
              }
              if (nCountNoData == nBands)
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }

          CPLFree(pabyNoData);
      }
      break;

      case GDT_UInt32:
      {
          GUInt32* panNoData = (GUInt32*) CPLMalloc(nBands * sizeof(GUInt32));
          for(iBand=0;iBand<nBands;iBand++)
          {
              panNoData[iBand] = (GUInt32)padfNodataValues[iBand];
          }

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              int nCountNoData = 0;
              for(iBand=0;iBand<nBands;iBand++)
              {
                  if( ((GUInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
                      nCountNoData ++;
              }
              if (nCountNoData == nBands)
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }

          CPLFree(panNoData);
      }
      break;

      case GDT_Int32:
      {
          GInt32* panNoData = (GInt32*) CPLMalloc(nBands * sizeof(GInt32));
          for(iBand=0;iBand<nBands;iBand++)
          {
              panNoData[iBand] = (GInt32)padfNodataValues[iBand];
          }

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              int nCountNoData = 0;
              for(iBand=0;iBand<nBands;iBand++)
              {
                  if( ((GInt32 *)pabySrc)[i + iBand * nBlockOffsetPixels] == panNoData[iBand] )
                      nCountNoData ++;
              }
              if (nCountNoData == nBands)
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }

          CPLFree(panNoData);
      }
      break;

      case GDT_Float32:
      {
          float* pafNoData = (float*) CPLMalloc(nBands * sizeof(float));
          for(iBand=0;iBand<nBands;iBand++)
          {
              pafNoData[iBand] = (float)padfNodataValues[iBand];
          }

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              int nCountNoData = 0;
              for(iBand=0;iBand<nBands;iBand++)
              {
                  if( ((float *)pabySrc)[i + iBand * nBlockOffsetPixels] == pafNoData[iBand] )
                      nCountNoData ++;
              }
              if (nCountNoData == nBands)
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }

          CPLFree(pafNoData);
      }
      break;

      case GDT_Float64:
      {
          double* padfNoData = (double*) CPLMalloc(nBands * sizeof(double));
          for(iBand=0;iBand<nBands;iBand++)
          {
              padfNoData[iBand] = (double)padfNodataValues[iBand];
          }

          for( i = nBlockXSize * nBlockYSize - 1; i >= 0; i-- )
          {
              int nCountNoData = 0;
              for(iBand=0;iBand<nBands;iBand++)
              {
                  if( ((double *)pabySrc)[i + iBand * nBlockOffsetPixels] == padfNoData[iBand] )
                      nCountNoData ++;
              }
              if (nCountNoData == nBands)
                  ((GByte *) pImage)[i] = 0;
              else
                  ((GByte *) pImage)[i] = 255;
          }

          CPLFree(padfNoData);
      }
      break;

      default:
        CPLAssert( FALSE );
        break;
    }

    CPLFree( pabySrc );

    return CE_None;
}
Example #6
0
static int GeoLocLoadFullData( GDALGeoLocTransformInfo *psTransform )

{
    int nXSize, nYSize;

    int nXSize_XBand = GDALGetRasterXSize( psTransform->hDS_X );
    int nYSize_XBand = GDALGetRasterYSize( psTransform->hDS_X );
    int nXSize_YBand = GDALGetRasterXSize( psTransform->hDS_Y );
    int nYSize_YBand = GDALGetRasterYSize( psTransform->hDS_Y );
    if (nYSize_XBand == 1 && nYSize_YBand == 1)
    {
        nXSize = nXSize_XBand;
        nYSize = nXSize_YBand;
    }
    else
    {
        nXSize = nXSize_XBand;
        nYSize = nYSize_XBand;
    }

    psTransform->nGeoLocXSize = nXSize;
    psTransform->nGeoLocYSize = nYSize;

    psTransform->padfGeoLocY = (double *)
        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize);
    psTransform->padfGeoLocX = (double *)
        VSI_MALLOC3_VERBOSE(sizeof(double), nXSize, nYSize);

    if( psTransform->padfGeoLocX == NULL ||
        psTransform->padfGeoLocY == NULL )
    {
        return FALSE;
    }

    if (nYSize_XBand == 1 && nYSize_YBand == 1)
    {
        /* Case of regular grid */
        /* The XBAND contains the x coordinates for all lines */
        /* The YBAND contains the y coordinates for all columns */

        double* padfTempX = (double*)VSI_MALLOC2_VERBOSE(nXSize, sizeof(double));
        double* padfTempY = (double*)VSI_MALLOC2_VERBOSE(nYSize, sizeof(double));
        if (padfTempX == NULL || padfTempY == NULL)
        {
            CPLFree(padfTempX);
            CPLFree(padfTempY);
            return FALSE;
        }

        CPLErr eErr = CE_None;

        eErr = GDALRasterIO( psTransform->hBand_X, GF_Read,
                             0, 0, nXSize, 1,
                             padfTempX, nXSize, 1,
                             GDT_Float64, 0, 0 );

        int i,j;
        for(j=0;j<nYSize;j++)
        {
            memcpy( psTransform->padfGeoLocX + j * nXSize,
                    padfTempX,
                    nXSize * sizeof(double) );
        }

        if (eErr == CE_None)
        {
            eErr = GDALRasterIO( psTransform->hBand_Y, GF_Read,
                                0, 0, nYSize, 1,
                                padfTempY, nYSize, 1,
                                GDT_Float64, 0, 0 );

            for(j=0;j<nYSize;j++)
            {
                for(i=0;i<nXSize;i++)
                {
                    psTransform->padfGeoLocY[j * nXSize + i] = padfTempY[j];
                }
            }
        }

        CPLFree(padfTempX);
        CPLFree(padfTempY);

        if (eErr != CE_None)
            return FALSE;
    }
    else
    {
        if( GDALRasterIO( psTransform->hBand_X, GF_Read,
                        0, 0, nXSize, nYSize,
                        psTransform->padfGeoLocX, nXSize, nYSize,
                        GDT_Float64, 0, 0 ) != CE_None
            || GDALRasterIO( psTransform->hBand_Y, GF_Read,
                            0, 0, nXSize, nYSize,
                            psTransform->padfGeoLocY, nXSize, nYSize,
                            GDT_Float64, 0, 0 ) != CE_None )
            return FALSE;
    }

    psTransform->dfNoDataX = GDALGetRasterNoDataValue( psTransform->hBand_X,
                                                       &(psTransform->bHasNoData) );

    return TRUE;
}
Example #7
0
static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )

{
    int nXSize = psTransform->nGeoLocXSize;
    int nYSize = psTransform->nGeoLocYSize;
    int nMaxIter = 3;

/* -------------------------------------------------------------------- */
/*      Scan forward map for lat/long extents.                          */
/* -------------------------------------------------------------------- */
    double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0;
    int i, bInit = FALSE;

    for( i = nXSize * nYSize - 1; i >= 0; i-- )
    {
        if( !psTransform->bHasNoData ||
            psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
        {
            if( bInit )
            {
                dfMinX = MIN(dfMinX,psTransform->padfGeoLocX[i]);
                dfMaxX = MAX(dfMaxX,psTransform->padfGeoLocX[i]);
                dfMinY = MIN(dfMinY,psTransform->padfGeoLocY[i]);
                dfMaxY = MAX(dfMaxY,psTransform->padfGeoLocY[i]);
            }
            else
            {
                bInit = TRUE;
                dfMinX = dfMaxX = psTransform->padfGeoLocX[i];
                dfMinY = dfMaxY = psTransform->padfGeoLocY[i];
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Decide on resolution for backmap.  We aim for slightly          */
/*      higher resolution than the source but we can't easily           */
/*      establish how much dead space there is in the backmap, so it    */
/*      is approximate.                                                 */
/* -------------------------------------------------------------------- */
    double dfTargetPixels = (nXSize * nYSize * 1.3);
    double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY)
                              / dfTargetPixels);
    int nBMXSize, nBMYSize;

    nBMYSize = psTransform->nBackMapHeight =
        (int) ((dfMaxY - dfMinY) / dfPixelSize + 1);
    nBMXSize= psTransform->nBackMapWidth =
        (int) ((dfMaxX - dfMinX) / dfPixelSize + 1);

    if (nBMXSize > INT_MAX / nBMYSize)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
                 nBMXSize, nBMYSize);
        return FALSE;
    }

    dfMinX -= dfPixelSize/2.0;
    dfMaxY += dfPixelSize/2.0;

    psTransform->adfBackMapGeoTransform[0] = dfMinX;
    psTransform->adfBackMapGeoTransform[1] = dfPixelSize;
    psTransform->adfBackMapGeoTransform[2] = 0.0;
    psTransform->adfBackMapGeoTransform[3] = dfMaxY;
    psTransform->adfBackMapGeoTransform[4] = 0.0;
    psTransform->adfBackMapGeoTransform[5] = -dfPixelSize;

/* -------------------------------------------------------------------- */
/*      Allocate backmap, and initialize to nodata value (-1.0).        */
/* -------------------------------------------------------------------- */
    GByte  *pabyValidFlag;

    pabyValidFlag = (GByte *)
        VSI_CALLOC_VERBOSE(nBMXSize, nBMYSize);

    psTransform->pafBackMapX = (float *)
        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float));
    psTransform->pafBackMapY = (float *)
        VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float));

    if( pabyValidFlag == NULL ||
        psTransform->pafBackMapX == NULL ||
        psTransform->pafBackMapY == NULL )
    {
        CPLFree( pabyValidFlag );
        return FALSE;
    }

    for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
    {
        psTransform->pafBackMapX[i] = -1.0;
        psTransform->pafBackMapY[i] = -1.0;
    }

/* -------------------------------------------------------------------- */
/*      Run through the whole geoloc array forward projecting and       */
/*      pushing into the backmap.                                       */
/*      Initialize to the nMaxIter+1 value so we can spot genuinely     */
/*      valid pixels in the hole-filling loop.                          */
/* -------------------------------------------------------------------- */
    int iBMX, iBMY;
    int iX, iY;

    for( iY = 0; iY < nYSize; iY++ )
    {
        for( iX = 0; iX < nXSize; iX++ )
        {
            if( psTransform->bHasNoData &&
                psTransform->padfGeoLocX[iX + iY * nXSize]
                == psTransform->dfNoDataX )
                continue;

            i = iX + iY * nXSize;

            iBMX = (int) ((psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize);
            iBMY = (int) ((dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize);

            if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize )
                continue;

            psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] =
                (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET);
            psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] =
                (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET);

            pabyValidFlag[iBMX + iBMY * nBMXSize] = (GByte) (nMaxIter+1);

        }
    }

/* -------------------------------------------------------------------- */
/*      Now, loop over the backmap trying to fill in holes with         */
/*      nearby values.                                                  */
/* -------------------------------------------------------------------- */
    int iIter;
    int nNumValid;

    for( iIter = 0; iIter < nMaxIter; iIter++ )
    {
        nNumValid = 0;
        for( iBMY = 0; iBMY < nBMYSize; iBMY++ )
        {
            for( iBMX = 0; iBMX < nBMXSize; iBMX++ )
            {
                // if this point is already set, ignore it.
                if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
                {
                    nNumValid++;
                    continue;
                }

                int nCount = 0;
                double dfXSum = 0.0, dfYSum = 0.0;
                int nMarkedAsGood = nMaxIter - iIter;

                // left?
                if( iBMX > 0 &&
                    pabyValidFlag[iBMX-1+iBMY*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX-1+iBMY*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize];
                    nCount++;
                }
                // right?
                if( iBMX + 1 < nBMXSize &&
                    pabyValidFlag[iBMX+1+iBMY*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+1+iBMY*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize];
                    nCount++;
                }
                // top?
                if( iBMY > 0 &&
                    pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+(iBMY-1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize];
                    nCount++;
                }
                // bottom?
                if( iBMY + 1 < nBMYSize &&
                    pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+(iBMY+1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+(iBMY+1)*nBMXSize];
                    nCount++;
                }
                // top-left?
                if( iBMX > 0 && iBMY > 0 &&
                    pabyValidFlag[iBMX-1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
                    nCount++;
                }
                // top-right?
                if( iBMX + 1 < nBMXSize && iBMY > 0 &&
                    pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
                    nCount++;
                }
                // bottom-left?
                if( iBMX > 0 && iBMY + 1 < nBMYSize &&
                    pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
                    nCount++;
                }
                // bottom-right?
                if( iBMX + 1 < nBMXSize && iBMY + 1 < nBMYSize &&
                    pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize];
                    nCount++;
                }

                if( nCount > 0 )
                {
                    psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(dfXSum/nCount);
                    psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(dfYSum/nCount);
                    // genuinely valid points will have value iMaxIter+1
                    // On each iteration mark newly valid points with a
                    // descending value so that it will not be used on the
                    // current iteration only on subsequent ones.
                    pabyValidFlag[iBMX+iBMY*nBMXSize] = (GByte) (nMaxIter - iIter);
                }
            }
        }
        if (nNumValid == nBMXSize * nBMYSize)
            break;
    }

#ifdef notdef
    GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ),
                                     "backmap.tif", nBMXSize, nBMYSize, 2,
                                     GDT_Float32, NULL );
    GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform );
    GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write,
                  0, 0, nBMXSize, nBMYSize,
                  psTransform->pafBackMapX, nBMXSize, nBMYSize,
                  GDT_Float32, 0, 0 );
    GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write,
                  0, 0, nBMXSize, nBMYSize,
                  psTransform->pafBackMapY, nBMXSize, nBMYSize,
                  GDT_Float32, 0, 0 );
    GDALClose( hBMDS );
#endif

    CPLFree( pabyValidFlag );

    return TRUE;
}