LCOV - code coverage report
Current view: directory - frmts/vrt - vrtfilters.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 202 147 72.8 %
Date: 2012-12-26 Functions: 20 13 65.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtfilters.cpp 24530 2012-06-02 16:28:14Z rouault $
       3                 :  *
       4                 :  * Project:  Virtual GDAL Datasets
       5                 :  * Purpose:  Implementation of some filter types.
       6                 :  * Author:   Frank Warmerdam <warmerdam@pobox.com>
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "vrtdataset.h"
      31                 : #include "cpl_minixml.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: vrtfilters.cpp 24530 2012-06-02 16:28:14Z rouault $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /* ==================================================================== */
      38                 : /*                          VRTFilteredSource                           */
      39                 : /* ==================================================================== */
      40                 : /************************************************************************/
      41                 : 
      42                 : /************************************************************************/
      43                 : /*                         VRTFilteredSource()                          */
      44                 : /************************************************************************/
      45                 : 
      46               5 : VRTFilteredSource::VRTFilteredSource()
      47                 : 
      48                 : {
      49               5 :     nExtraEdgePixels = 0;
      50               5 :     nSupportedTypesCount = 1;
      51               5 :     aeSupportedTypes[0] = GDT_Float32;
      52               5 : }
      53                 : 
      54                 : /************************************************************************/
      55                 : /*                         ~VRTFilteredSource()                         */
      56                 : /************************************************************************/
      57                 : 
      58               5 : VRTFilteredSource::~VRTFilteredSource()
      59                 : 
      60                 : {
      61               5 : }
      62                 : 
      63                 : /************************************************************************/
      64                 : /*                         SetExtraEdgePixels()                         */
      65                 : /************************************************************************/
      66                 : 
      67               5 : void VRTFilteredSource::SetExtraEdgePixels( int nEdgePixels )
      68                 : 
      69                 : {
      70               5 :     nExtraEdgePixels = nEdgePixels;
      71               5 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                   SetFilteringDataTypesSupported()                   */
      75                 : /************************************************************************/
      76                 : 
      77               5 : void VRTFilteredSource::SetFilteringDataTypesSupported( int nTypeCount, 
      78                 :                                                         GDALDataType *paeTypes)
      79                 : 
      80                 : {
      81               5 :     if( nTypeCount > 
      82                 :         (int) sizeof(sizeof(aeSupportedTypes)/sizeof(GDALDataType)) )
      83                 :     {
      84               0 :         CPLAssert( FALSE );
      85                 :         nTypeCount = (int) 
      86               0 :             sizeof(sizeof(aeSupportedTypes)/sizeof(GDALDataType));
      87                 :     }
      88                 : 
      89               5 :     nSupportedTypesCount = nTypeCount;
      90               5 :     memcpy( aeSupportedTypes, paeTypes, sizeof(GDALDataType) * nTypeCount );
      91               5 : }
      92                 : 
      93                 : /************************************************************************/
      94                 : /*                          IsTypeSupported()                           */
      95                 : /************************************************************************/
      96                 : 
      97             440 : int VRTFilteredSource::IsTypeSupported( GDALDataType eTestType )
      98                 : 
      99                 : {
     100                 :     int i;
     101                 : 
     102             880 :     for( i = 0; i < nSupportedTypesCount; i++ )
     103                 :     {
     104             440 :         if( eTestType == aeSupportedTypes[i] )
     105               0 :             return TRUE;
     106                 :     }
     107                 : 
     108             440 :     return FALSE;
     109                 : }
     110                 : 
     111                 : /************************************************************************/
     112                 : /*                              RasterIO()                              */
     113                 : /************************************************************************/
     114                 : 
     115                 : CPLErr
     116             220 : VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
     117                 :                              void *pData, int nBufXSize, int nBufYSize, 
     118                 :                              GDALDataType eBufType, 
     119                 :                              int nPixelSpace, int nLineSpace )
     120                 : 
     121                 : {
     122                 : /* -------------------------------------------------------------------- */
     123                 : /*      For now we don't support filtered access to non-full            */
     124                 : /*      resolution requests. Just collect the data directly without     */
     125                 : /*      any operator.                                                   */
     126                 : /* -------------------------------------------------------------------- */
     127             220 :     if( nBufXSize != nXSize || nBufYSize != nYSize )
     128                 :     {
     129                 :         return VRTComplexSource::RasterIO( nXOff, nYOff, nXSize, nYSize, 
     130                 :                                            pData, nBufXSize, nBufYSize, 
     131               0 :                                            eBufType, nPixelSpace, nLineSpace );
     132                 :     }
     133                 : 
     134                 :     // The window we will actually request from the source raster band.
     135                 :     int nReqXOff, nReqYOff, nReqXSize, nReqYSize;
     136                 : 
     137                 :     // The window we will actual set _within_ the pData buffer.
     138                 :     int nOutXOff, nOutYOff, nOutXSize, nOutYSize;
     139                 : 
     140             220 :     if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
     141                 :                         &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
     142                 :                         &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
     143               0 :         return CE_None;
     144                 : 
     145                 :     pData = ((GByte *)pData)
     146                 :                             + nPixelSpace * nOutXOff
     147             220 :                             + nLineSpace * nOutYOff;
     148                 : 
     149                 : /* -------------------------------------------------------------------- */
     150                 : /*      Determine the data type we want to request.  We try to match    */
     151                 : /*      the source or destination request, and if both those fail we    */
     152                 : /*      fallback to the first supported type at least as expressive     */
     153                 : /*      as the request.                                                 */
     154                 : /* -------------------------------------------------------------------- */
     155             220 :     GDALDataType eOperDataType = GDT_Unknown;
     156                 :     int i;
     157                 :     
     158             220 :     if( IsTypeSupported( eBufType ) )
     159               0 :         eOperDataType = eBufType;
     160                 : 
     161             220 :     if( eOperDataType == GDT_Unknown 
     162                 :         && IsTypeSupported( poRasterBand->GetRasterDataType() ) )
     163               0 :         eOperDataType = poRasterBand->GetRasterDataType();
     164                 : 
     165             220 :     if( eOperDataType == GDT_Unknown )
     166                 :     {
     167             440 :         for( i = 0; i < nSupportedTypesCount; i++ )
     168                 :         {
     169             440 :             if( GDALDataTypeUnion( aeSupportedTypes[i], eBufType ) 
     170             220 :                 == aeSupportedTypes[i] )
     171                 :             {
     172             220 :                 eOperDataType = aeSupportedTypes[i];
     173                 :             }
     174                 :         }
     175                 :     }
     176                 : 
     177             220 :     if( eOperDataType == GDT_Unknown )
     178                 :     {
     179               0 :         eOperDataType = aeSupportedTypes[0];
     180                 : 
     181               0 :         for( i = 1; i < nSupportedTypesCount; i++ )
     182                 :         {
     183               0 :             if( GDALGetDataTypeSize( aeSupportedTypes[i] ) 
     184                 :                 > GDALGetDataTypeSize( eOperDataType ) )
     185                 :             {
     186               0 :                 eOperDataType = aeSupportedTypes[i];
     187                 :             }
     188                 :         }
     189                 :     }
     190                 : 
     191                 : /* -------------------------------------------------------------------- */
     192                 : /*      Allocate the buffer of data into which our imagery will be      */
     193                 : /*      read, with the extra edge pixels as well. This will be the      */
     194                 : /*      source data fed into the filter.                                */
     195                 : /* -------------------------------------------------------------------- */
     196                 :     int nPixelOffset, nLineOffset;
     197             220 :     int nExtraXSize = nOutXSize + 2 * nExtraEdgePixels;
     198             220 :     int nExtraYSize = nOutYSize + 2 * nExtraEdgePixels;
     199                 :     GByte *pabyWorkData;
     200                 : 
     201                 :     // FIXME? : risk of multiplication overflow
     202                 :     pabyWorkData = (GByte *) 
     203                 :         VSICalloc( nExtraXSize * nExtraYSize,
     204             220 :                    (GDALGetDataTypeSize(eOperDataType) / 8) );
     205                 :     
     206             220 :     if( pabyWorkData == NULL )
     207                 :     {
     208                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     209               0 :                   "Work buffer allocation failed." );
     210               0 :         return CE_Failure;
     211                 :     }
     212                 : 
     213             220 :     nPixelOffset = GDALGetDataTypeSize( eOperDataType ) / 8;
     214             220 :     nLineOffset = nPixelOffset * nExtraXSize;
     215                 : 
     216                 : /* -------------------------------------------------------------------- */
     217                 : /*      Allocate the output buffer if the passed in output buffer is    */
     218                 : /*      not of the same type as our working format, or if the passed    */
     219                 : /*      in buffer has an unusual organization.                          */
     220                 : /* -------------------------------------------------------------------- */
     221                 :     GByte *pabyOutData;
     222                 : 
     223             440 :     if( nPixelSpace != nPixelOffset || nLineSpace != nLineOffset
     224                 :         || eOperDataType != eBufType )
     225                 :     {
     226                 :         pabyOutData = (GByte *) 
     227             220 :             VSIMalloc3(nOutXSize, nOutYSize, nPixelOffset );
     228                 : 
     229             220 :         if( pabyOutData == NULL )
     230                 :         {
     231                 :             CPLError( CE_Failure, CPLE_OutOfMemory, 
     232               0 :                       "Work buffer allocation failed." );
     233               0 :             return CE_Failure;
     234                 :         }
     235                 :     }
     236                 :     else
     237               0 :         pabyOutData = (GByte *) pData;
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Figure out the extended window that we want to load.  Note      */
     241                 : /*      that we keep track of the file window as well as the amount     */
     242                 : /*      we will need to edge fill past the edge of the source dataset.  */
     243                 : /* -------------------------------------------------------------------- */
     244             220 :     int nTopFill=0, nLeftFill=0, nRightFill=0, nBottomFill=0;
     245                 :     int nFileXOff, nFileYOff, nFileXSize, nFileYSize;
     246                 : 
     247             220 :     nFileXOff = nReqXOff - nExtraEdgePixels;
     248             220 :     nFileYOff = nReqYOff - nExtraEdgePixels;
     249             220 :     nFileXSize = nExtraXSize;
     250             220 :     nFileYSize = nExtraYSize;
     251                 : 
     252             220 :     if( nFileXOff < 0 )
     253                 :     {
     254             220 :         nLeftFill = -nFileXOff;
     255             220 :         nFileXOff = 0;
     256             220 :         nFileXSize -= nLeftFill;
     257                 :     }
     258                 : 
     259             220 :     if( nFileYOff < 0 )
     260                 :     {
     261               5 :         nTopFill = -nFileYOff;
     262               5 :         nFileYOff = 0;
     263               5 :         nFileYSize -= nTopFill;
     264                 :     }
     265                 : 
     266             220 :     if( nFileXOff + nFileXSize > poRasterBand->GetXSize() )
     267                 :     {
     268             220 :         nRightFill = nFileXOff + nFileXSize - poRasterBand->GetXSize();
     269             220 :         nFileXSize -= nRightFill;
     270                 :     }
     271                 : 
     272             220 :     if( nFileYOff + nFileYSize > poRasterBand->GetYSize() )
     273                 :     {
     274               5 :         nBottomFill = nFileYOff + nFileYSize - poRasterBand->GetYSize();
     275               5 :         nFileYSize -= nBottomFill;
     276                 :     }
     277                 : 
     278                 : /* -------------------------------------------------------------------- */
     279                 : /*      Load the data.                                                  */
     280                 : /* -------------------------------------------------------------------- */
     281                 :     CPLErr eErr;
     282                 : 
     283                 :     eErr =
     284                 :         VRTComplexSource::RasterIOInternal( nFileXOff, nFileYOff, nFileXSize, nFileYSize,
     285                 :                                             pabyWorkData
     286                 :                                               + nLineOffset * nTopFill
     287                 :                                               + nPixelOffset * nLeftFill,
     288                 :                                             nFileXSize, nFileYSize, eOperDataType,
     289             220 :                                             nPixelOffset, nLineOffset );
     290                 : 
     291             220 :     if( eErr != CE_None )
     292                 :     {
     293               0 :         if( pabyWorkData != pData )
     294               0 :             VSIFree( pabyWorkData );
     295                 : 
     296               0 :         return eErr;
     297                 :     }
     298                 : 
     299                 : /* -------------------------------------------------------------------- */
     300                 : /*      Fill in missing areas.  Note that we replicate the edge         */
     301                 : /*      valid values out.  We don't using "mirroring" which might be    */
     302                 : /*      more suitable for some times of filters.  We also don't mark    */
     303                 : /*      these pixels as "nodata" though perhaps we should.              */
     304                 : /* -------------------------------------------------------------------- */
     305             220 :     if( nLeftFill != 0 || nRightFill != 0 )
     306                 :     {
     307             870 :         for( i = nTopFill; i < nExtraYSize - nBottomFill; i++ )
     308                 :         {
     309             650 :             if( nLeftFill != 0 )
     310                 :                 GDALCopyWords( pabyWorkData + nPixelOffset * nLeftFill
     311                 :                                + i * nLineOffset, eOperDataType, 0, 
     312                 :                                pabyWorkData + i * nLineOffset, eOperDataType, 
     313             650 :                                nPixelOffset, nLeftFill );
     314                 : 
     315             650 :             if( nRightFill != 0 )
     316                 :                 GDALCopyWords( pabyWorkData + i * nLineOffset
     317                 :                                + nPixelOffset * (nExtraXSize - nRightFill - 1),
     318                 :                                eOperDataType, 0, 
     319                 :                                pabyWorkData + i * nLineOffset
     320                 :                                + nPixelOffset * (nExtraXSize - nRightFill),
     321             650 :                                eOperDataType, nPixelOffset, nRightFill );
     322                 :         }
     323                 :     }
     324                 : 
     325             225 :     for( i = 0; i < nTopFill; i++ )
     326                 :     {
     327                 :         memcpy( pabyWorkData + i * nLineOffset, 
     328                 :                 pabyWorkData + nTopFill * nLineOffset, 
     329               5 :                 nLineOffset );
     330                 :     }
     331                 : 
     332             225 :     for( i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ )
     333                 :     {
     334                 :         memcpy( pabyWorkData + i * nLineOffset, 
     335                 :                 pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset, 
     336               5 :                 nLineOffset );
     337                 :     }
     338                 :     
     339                 : /* -------------------------------------------------------------------- */
     340                 : /*      Filter the data.                                                */
     341                 : /* -------------------------------------------------------------------- */
     342                 :     eErr = FilterData( nOutXSize, nOutYSize, eOperDataType,
     343             220 :                        pabyWorkData, pabyOutData );
     344                 : 
     345             220 :     VSIFree( pabyWorkData );
     346             220 :     if( eErr != CE_None )
     347                 :     {
     348               0 :         if( pabyOutData != pData )
     349               0 :             VSIFree( pabyOutData );
     350                 : 
     351               0 :         return eErr;
     352                 :     }
     353                 :     
     354                 : /* -------------------------------------------------------------------- */
     355                 : /*      Copy from work buffer to target buffer.                         */
     356                 : /* -------------------------------------------------------------------- */
     357             220 :     if( pabyOutData != pData )
     358                 :     {
     359             440 :         for( i = 0; i < nOutYSize; i++ )
     360                 :         {
     361                 :             GDALCopyWords( pabyOutData + i * (nPixelOffset * nOutXSize),
     362                 :                            eOperDataType, nPixelOffset,
     363                 :                            ((GByte *) pData) + i * nLineSpace, 
     364             220 :                            eBufType, nPixelSpace, nOutXSize );
     365                 :         }
     366                 : 
     367             220 :         VSIFree( pabyOutData );
     368                 :     }
     369                 : 
     370             220 :     return CE_None;
     371                 : }
     372                 : 
     373                 : /************************************************************************/
     374                 : /* ==================================================================== */
     375                 : /*                       VRTKernelFilteredSource                        */
     376                 : /* ==================================================================== */
     377                 : /************************************************************************/
     378                 : 
     379                 : /************************************************************************/
     380                 : /*                      VRTKernelFilteredSource()                       */
     381                 : /************************************************************************/
     382                 : 
     383               5 : VRTKernelFilteredSource::VRTKernelFilteredSource()
     384                 : 
     385                 : {
     386               5 :     GDALDataType aeSupTypes[] = { GDT_Float32 };
     387               5 :     padfKernelCoefs = NULL;
     388               5 :     nKernelSize = 0;
     389               5 :     bNormalized = FALSE;
     390                 : 
     391               5 :     SetFilteringDataTypesSupported( 1, aeSupTypes );
     392               5 : }
     393                 : 
     394                 : /************************************************************************/
     395                 : /*                      ~VRTKernelFilteredSource()                      */
     396                 : /************************************************************************/
     397                 : 
     398               5 : VRTKernelFilteredSource::~VRTKernelFilteredSource() 
     399                 : 
     400                 : {
     401               5 :     CPLFree( padfKernelCoefs );
     402               5 : }
     403                 : 
     404                 : /************************************************************************/
     405                 : /*                           SetNormalized()                            */
     406                 : /************************************************************************/
     407                 : 
     408               5 : void VRTKernelFilteredSource::SetNormalized( int bNormalizedIn )
     409                 : 
     410                 : {
     411               5 :     bNormalized = bNormalizedIn;
     412               5 : }
     413                 : 
     414                 : /************************************************************************/
     415                 : /*                             SetKernel()                              */
     416                 : /************************************************************************/
     417                 : 
     418               5 : CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize, 
     419                 :                                            double *padfNewCoefs )
     420                 : 
     421                 : {
     422               5 :     if( nNewKernelSize < 1 || (nNewKernelSize % 2) != 1 )
     423                 :     {
     424                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     425                 :                   "Illegal filtering kernel size %d, must be odd positive number.", 
     426               0 :                   nNewKernelSize );
     427               0 :         return CE_Failure;
     428                 :     }
     429                 : 
     430               5 :     CPLFree( padfKernelCoefs );
     431               5 :     nKernelSize = nNewKernelSize;
     432                 : 
     433                 :     padfKernelCoefs = (double *) 
     434               5 :         CPLMalloc(sizeof(double) * nKernelSize * nKernelSize );
     435                 :     memcpy( padfKernelCoefs, padfNewCoefs, 
     436               5 :             sizeof(double) * nKernelSize * nKernelSize );
     437                 : 
     438               5 :     SetExtraEdgePixels( (nNewKernelSize - 1) / 2 );
     439                 : 
     440               5 :     return CE_None;
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                             FilterData()                             */
     445                 : /************************************************************************/
     446                 : 
     447             220 : CPLErr VRTKernelFilteredSource::
     448                 : FilterData( int nXSize, int nYSize, GDALDataType eType, 
     449                 :             GByte *pabySrcData, GByte *pabyDstData )
     450                 : 
     451                 : {
     452                 : /* -------------------------------------------------------------------- */
     453                 : /*      Validate data type.                                             */
     454                 : /* -------------------------------------------------------------------- */
     455             220 :     if( eType != GDT_Float32 )
     456                 :     {
     457                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     458                 :                   "Unsupported data type (%s) in VRTKernelFilteredSource::FilterData()", 
     459               0 :                   GDALGetDataTypeName( eType ) );
     460               0 :         return CE_Failure; 
     461                 :     }
     462                 : 
     463                 :     CPLAssert( nExtraEdgePixels*2 + 1 == nKernelSize ||
     464             220 :                (nKernelSize == 0 && nExtraEdgePixels == 0) );
     465                 : 
     466                 : /* -------------------------------------------------------------------- */
     467                 : /*      Float32 case.                                                   */
     468                 : /* -------------------------------------------------------------------- */
     469             220 :     if( eType == GDT_Float32 )
     470                 :     {
     471                 :         int iX, iY;
     472                 : 
     473                 :         int bHasNoData;
     474             220 :         float fNoData = (float) poRasterBand->GetNoDataValue(&bHasNoData);
     475                 : 
     476             440 :         for( iY = 0; iY < nYSize; iY++ )
     477                 :         {
     478           10620 :             for( iX = 0; iX < nXSize; iX++ )
     479                 :             {
     480           10400 :                 int    iYY, iKern = 0;
     481           10400 :                 double dfSum = 0.0, dfKernSum = 0.0;
     482                 :                 float  fResult;
     483           10400 :                 int    iIndex = (iY+nKernelSize/2 ) * (nXSize+2*nExtraEdgePixels) + iX + nKernelSize/2;
     484           10400 :                 float  fCenter = ((float *)pabySrcData)[iIndex];
     485                 : 
     486                 :                 // Check if center srcpixel is NoData
     487           20600 :                 if(!bHasNoData || fCenter != fNoData)
     488                 :                 {
     489           40800 :                     for( iYY = 0; iYY < nKernelSize; iYY++ )
     490                 :                     {
     491                 :                         int i;
     492                 :                         float *pafData = ((float *)pabySrcData) 
     493           30600 :                                 + (iY+iYY) * (nXSize+2*nExtraEdgePixels) + iX;
     494                 : 
     495          122400 :                         for( i = 0; i < nKernelSize; i++, pafData++, iKern++ )
     496                 :                         {
     497           91800 :                             if(!bHasNoData || *pafData != fNoData)
     498                 :                             {
     499           90964 :                                 dfSum += *pafData * padfKernelCoefs[iKern];
     500           90964 :                                 dfKernSum += padfKernelCoefs[iKern];
     501                 :                             }
     502                 :                         }
     503                 :                     }
     504           10200 :                     if( bNormalized )
     505                 :                     {
     506             200 :                         if( dfKernSum != 0.0 )
     507             200 :                             fResult = (float) (dfSum / dfKernSum);
     508                 :                         else
     509               0 :                             fResult = 0.0;
     510                 :                     }
     511                 :                     else
     512           10000 :                         fResult = (float) dfSum;
     513                 : 
     514           10200 :                     ((float *) pabyDstData)[iX + iY * nXSize] = fResult;
     515                 :                 }
     516                 :                 else
     517             200 :                     ((float *) pabyDstData)[iX + iY * nXSize] = fNoData;
     518                 :             }
     519                 :         }
     520                 :     }
     521                 : 
     522             220 :     return CE_None;
     523                 : }
     524                 : 
     525                 : /************************************************************************/
     526                 : /*                              XMLInit()                               */
     527                 : /************************************************************************/
     528                 : 
     529               5 : CPLErr VRTKernelFilteredSource::XMLInit( CPLXMLNode *psTree, 
     530                 :                                          const char *pszVRTPath )
     531                 : 
     532                 : {
     533               5 :     CPLErr eErr = VRTFilteredSource::XMLInit( psTree, pszVRTPath );
     534                 :     int    nNewKernelSize, i, nCoefs;
     535                 :     double *padfNewCoefs;
     536                 : 
     537               5 :     if( eErr != CE_None )
     538               0 :         return eErr;
     539                 : 
     540               5 :     nNewKernelSize = atoi(CPLGetXMLValue(psTree,"Kernel.Size","0"));
     541                 : 
     542               5 :     if( nNewKernelSize == 0 )
     543               0 :         return CE_None;
     544                 : 
     545                 :     char **papszCoefItems = 
     546               5 :         CSLTokenizeString( CPLGetXMLValue(psTree,"Kernel.Coefs","") );
     547                 : 
     548               5 :     nCoefs = CSLCount(papszCoefItems);
     549                 : 
     550               5 :     if( nCoefs != nNewKernelSize * nNewKernelSize )
     551                 :     {
     552               0 :         CSLDestroy( papszCoefItems );
     553                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     554                 :                   "Got wrong number of filter kernel coefficients (%s).\n"
     555                 :                   "Expected %d, got %d.", 
     556                 :                   CPLGetXMLValue(psTree,"Kernel.Coefs",""),
     557               0 :                   nNewKernelSize * nNewKernelSize, nCoefs );
     558               0 :         return CE_Failure;
     559                 :     }
     560                 : 
     561               5 :     padfNewCoefs = (double *) CPLMalloc(sizeof(double) * nCoefs);
     562                 : 
     563              50 :     for( i = 0; i < nCoefs; i++ )
     564              45 :         padfNewCoefs[i] = atof(papszCoefItems[i]);
     565                 : 
     566               5 :     eErr = SetKernel( nNewKernelSize, padfNewCoefs );
     567                 : 
     568               5 :     CPLFree( padfNewCoefs );
     569               5 :     CSLDestroy( papszCoefItems );
     570                 : 
     571               5 :     SetNormalized( atoi(CPLGetXMLValue(psTree,"Kernel.normalized","0")) );
     572                 : 
     573               5 :     return eErr;
     574                 : }
     575                 : 
     576                 : /************************************************************************/
     577                 : /*                           SerializeToXML()                           */
     578                 : /************************************************************************/
     579                 : 
     580               0 : CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
     581                 : 
     582                 : {
     583               0 :     CPLXMLNode *psSrc = VRTFilteredSource::SerializeToXML( pszVRTPath );
     584                 :     CPLXMLNode *psKernel;
     585                 :     char *pszKernelCoefs;
     586               0 :     int iCoef, nCoefCount = nKernelSize * nKernelSize;
     587                 : 
     588               0 :     if( psSrc == NULL )
     589               0 :         return NULL;
     590                 : 
     591               0 :     CPLFree( psSrc->pszValue );
     592               0 :     psSrc->pszValue = CPLStrdup("KernelFilteredSource" );
     593                 : 
     594               0 :     if( nKernelSize == 0 )
     595               0 :         return psSrc;
     596                 : 
     597               0 :     psKernel = CPLCreateXMLNode( psSrc, CXT_Element, "Kernel" );
     598                 : 
     599               0 :     if( bNormalized )
     600                 :         CPLCreateXMLNode( 
     601                 :             CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ), 
     602               0 :             CXT_Text, "1" );
     603                 :     else
     604                 :         CPLCreateXMLNode( 
     605                 :             CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ), 
     606               0 :             CXT_Text, "0" );
     607                 : 
     608               0 :     pszKernelCoefs = (char *) CPLMalloc(nCoefCount * 32);
     609                 : 
     610               0 :     strcpy( pszKernelCoefs, "" );
     611               0 :     for( iCoef = 0; iCoef < nCoefCount; iCoef++ )
     612                 :         sprintf( pszKernelCoefs + strlen(pszKernelCoefs), 
     613               0 :                  "%.8g ", padfKernelCoefs[iCoef] );
     614                 :     
     615               0 :     CPLSetXMLValue( psKernel, "Size", CPLSPrintf( "%d", nKernelSize ) );
     616               0 :     CPLSetXMLValue( psKernel, "Coefs", pszKernelCoefs );
     617                 : 
     618               0 :     CPLFree( pszKernelCoefs );
     619                 : 
     620               0 :     return psSrc;
     621                 : }
     622                 : 
     623                 : /************************************************************************/
     624                 : /*                       VRTParseFilterSources()                        */
     625                 : /************************************************************************/
     626                 : 
     627               5 : VRTSource *VRTParseFilterSources( CPLXMLNode *psChild, const char *pszVRTPath )
     628                 : 
     629                 : {
     630                 :     VRTSource *poSrc;
     631                 : 
     632               5 :     if( EQUAL(psChild->pszValue,"KernelFilteredSource") )
     633                 :     {
     634               5 :         poSrc = new VRTKernelFilteredSource();
     635               5 :         if( poSrc->XMLInit( psChild, pszVRTPath ) == CE_None )
     636               5 :             return poSrc;
     637                 :         else
     638               0 :             delete poSrc;
     639                 :     }
     640                 : 
     641               0 :     return NULL;
     642                 : }
     643                 : 

Generated by: LCOV version 1.7