LCOV - code coverage report
Current view: directory - frmts/vrt - vrtfilters.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 195 144 73.8 %
Date: 2010-01-09 Functions: 16 14 87.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: vrtfilters.cpp 17636 2009-09-12 23:19:18Z warmerdam $
       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 17636 2009-09-12 23:19:18Z warmerdam $");
      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                 :         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                 : /* -------------------------------------------------------------------- */
     135                 : /*      Determine the data type we want to request.  We try to match    */
     136                 : /*      the source or destination request, and if both those fail we    */
     137                 : /*      fallback to the first supported type at least as expressive     */
     138                 : /*      as the request.                                                 */
     139                 : /* -------------------------------------------------------------------- */
     140             220 :     GDALDataType eOperDataType = GDT_Unknown;
     141                 :     int i;
     142                 :     
     143             220 :     if( IsTypeSupported( eBufType ) )
     144               0 :         eOperDataType = eBufType;
     145                 : 
     146             220 :     if( eOperDataType == GDT_Unknown 
     147                 :         && IsTypeSupported( poRasterBand->GetRasterDataType() ) )
     148               0 :         eOperDataType = poRasterBand->GetRasterDataType();
     149                 : 
     150             220 :     if( eOperDataType == GDT_Unknown )
     151                 :     {
     152             440 :         for( i = 0; i < nSupportedTypesCount; i++ )
     153                 :         {
     154             440 :             if( GDALDataTypeUnion( aeSupportedTypes[i], eBufType ) 
     155             220 :                 == aeSupportedTypes[i] )
     156                 :             {
     157             220 :                 eOperDataType = aeSupportedTypes[i];
     158                 :             }
     159                 :         }
     160                 :     }
     161                 : 
     162             220 :     if( eOperDataType == GDT_Unknown )
     163                 :     {
     164               0 :         eOperDataType = aeSupportedTypes[0];
     165                 : 
     166               0 :         for( i = 1; i < nSupportedTypesCount; i++ )
     167                 :         {
     168               0 :             if( GDALGetDataTypeSize( aeSupportedTypes[i] ) 
     169                 :                 > GDALGetDataTypeSize( eOperDataType ) )
     170                 :             {
     171               0 :                 eOperDataType = aeSupportedTypes[i];
     172                 :             }
     173                 :         }
     174                 :     }
     175                 : 
     176                 : /* -------------------------------------------------------------------- */
     177                 : /*      Allocate the buffer of data into which our imagery will be      */
     178                 : /*      read, with the extra edge pixels as well. This will be the      */
     179                 : /*      source data fed into the filter.                                */
     180                 : /* -------------------------------------------------------------------- */
     181                 :     int nPixelOffset, nLineOffset;
     182             220 :     int nExtraXSize = nBufXSize + 2 * nExtraEdgePixels;
     183             220 :     int nExtraYSize = nBufYSize + 2 * nExtraEdgePixels;
     184                 :     GByte *pabyWorkData;
     185                 : 
     186                 :     // FIXME? : risk of multiplication overflow
     187                 :     pabyWorkData = (GByte *) 
     188                 :         VSICalloc( nExtraXSize * nExtraYSize,
     189             220 :                    (GDALGetDataTypeSize(eOperDataType) / 8) );
     190                 :     
     191             220 :     if( pabyWorkData == NULL )
     192                 :     {
     193                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     194               0 :                   "Work buffer allocation failed." );
     195               0 :         return CE_Failure;
     196                 :     }
     197                 : 
     198             220 :     nPixelOffset = GDALGetDataTypeSize( eOperDataType ) / 8;
     199             220 :     nLineOffset = nPixelOffset * nExtraXSize;
     200                 : 
     201                 : /* -------------------------------------------------------------------- */
     202                 : /*      Allocate the output buffer if the passed in output buffer is    */
     203                 : /*      not of the same type as our working format, or if the passed    */
     204                 : /*      in buffer has an unusual organization.                          */
     205                 : /* -------------------------------------------------------------------- */
     206                 :     GByte *pabyOutData;
     207                 : 
     208             440 :     if( nPixelSpace != nPixelOffset || nLineSpace != nLineOffset
     209                 :         || eOperDataType != eBufType )
     210                 :     {
     211                 :         pabyOutData = (GByte *) 
     212             220 :             VSIMalloc3(nBufXSize, nBufYSize, nPixelOffset );
     213                 : 
     214             220 :         if( pabyOutData == NULL )
     215                 :         {
     216                 :             CPLError( CE_Failure, CPLE_OutOfMemory, 
     217               0 :                       "Work buffer allocation failed." );
     218               0 :             return CE_Failure;
     219                 :         }
     220                 :     }
     221                 :     else
     222               0 :         pabyOutData = (GByte *) pData;
     223                 : 
     224                 : /* -------------------------------------------------------------------- */
     225                 : /*      Figure out the extended window that we want to load.  Note      */
     226                 : /*      that we keep track of the file window as well as the amount     */
     227                 : /*      we will need to edge fill past the edge of the source dataset.  */
     228                 : /* -------------------------------------------------------------------- */
     229             220 :     int nTopFill=0, nLeftFill=0, nRightFill=0, nBottomFill=0;
     230                 :     int nFileXOff, nFileYOff, nFileXSize, nFileYSize;
     231                 : 
     232             220 :     nFileXOff = nXOff - nExtraEdgePixels;
     233             220 :     nFileYOff = nYOff - nExtraEdgePixels;
     234             220 :     nFileXSize = nExtraXSize;
     235             220 :     nFileYSize = nExtraYSize;
     236                 : 
     237             220 :     if( nFileXOff < 0 )
     238                 :     {
     239             220 :         nLeftFill = -nFileXOff;
     240             220 :         nFileXOff = 0;
     241             220 :         nFileXSize -= nLeftFill;
     242                 :     }
     243                 : 
     244             220 :     if( nFileYOff < 0 )
     245                 :     {
     246               5 :         nTopFill = -nFileYOff;
     247               5 :         nFileYOff = 0;
     248               5 :         nFileYSize -= nTopFill;
     249                 :     }
     250                 : 
     251             220 :     if( nFileXOff + nFileXSize > poRasterBand->GetXSize() )
     252                 :     {
     253             220 :         nRightFill = nFileXOff + nFileXSize - poRasterBand->GetXSize();
     254             220 :         nFileXSize -= nRightFill;
     255                 :     }
     256                 : 
     257             220 :     if( nFileYOff + nFileYSize > poRasterBand->GetYSize() )
     258                 :     {
     259               5 :         nBottomFill = nFileYOff + nFileYSize - poRasterBand->GetYSize();
     260               5 :         nFileYSize -= nBottomFill;
     261                 :     }
     262                 : 
     263                 : /* -------------------------------------------------------------------- */
     264                 : /*      Load the data.                                                  */
     265                 : /* -------------------------------------------------------------------- */
     266                 :     CPLErr eErr;
     267                 : 
     268                 :     eErr = 
     269                 :       VRTComplexSource::RasterIO( nFileXOff, nFileYOff, nFileXSize, nFileYSize,
     270                 :                                   pabyWorkData 
     271                 :                                   + nLineOffset * nTopFill
     272                 :                                   + nPixelOffset * nLeftFill,
     273                 :                                   nFileXSize, nFileYSize, eOperDataType, 
     274             220 :                                   nPixelOffset, nLineOffset );
     275                 : 
     276             220 :     if( eErr != CE_None )
     277                 :     {
     278               0 :         if( pabyWorkData != pData )
     279               0 :             VSIFree( pabyWorkData );
     280                 : 
     281               0 :         return eErr;
     282                 :     }
     283                 : 
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*      Fill in missing areas.  Note that we replicate the edge         */
     286                 : /*      valid values out.  We don't using "mirroring" which might be    */
     287                 : /*      more suitable for some times of filters.  We also don't mark    */
     288                 : /*      these pixels as "nodata" though perhaps we should.              */
     289                 : /* -------------------------------------------------------------------- */
     290             220 :     if( nLeftFill != 0 || nRightFill != 0 )
     291                 :     {
     292             870 :         for( i = nTopFill; i < nExtraYSize - nBottomFill; i++ )
     293                 :         {
     294             650 :             if( nLeftFill != 0 )
     295                 :                 GDALCopyWords( pabyWorkData + nPixelOffset * nLeftFill
     296                 :                                + i * nLineOffset, eOperDataType, 0, 
     297                 :                                pabyWorkData + i * nLineOffset, eOperDataType, 
     298             650 :                                nPixelOffset, nLeftFill );
     299                 : 
     300             650 :             if( nRightFill != 0 )
     301                 :                 GDALCopyWords( pabyWorkData + i * nLineOffset
     302                 :                                + nPixelOffset * (nExtraXSize - nRightFill - 1),
     303                 :                                eOperDataType, 0, 
     304                 :                                pabyWorkData + i * nLineOffset
     305                 :                                + nPixelOffset * (nExtraXSize - nRightFill),
     306             650 :                                eOperDataType, nPixelOffset, nRightFill );
     307                 :         }
     308                 :     }
     309                 : 
     310             225 :     for( i = 0; i < nTopFill; i++ )
     311                 :     {
     312                 :         memcpy( pabyWorkData + i * nLineOffset, 
     313                 :                 pabyWorkData + nTopFill * nLineOffset, 
     314               5 :                 nLineOffset );
     315                 :     }
     316                 : 
     317             225 :     for( i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ )
     318                 :     {
     319                 :         memcpy( pabyWorkData + i * nLineOffset, 
     320                 :                 pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset, 
     321               5 :                 nLineOffset );
     322                 :     }
     323                 :     
     324                 : /* -------------------------------------------------------------------- */
     325                 : /*      Filter the data.                                                */
     326                 : /* -------------------------------------------------------------------- */
     327                 :     eErr = FilterData( nBufXSize, nBufYSize, eOperDataType, 
     328             220 :                        pabyWorkData, pabyOutData );
     329                 : 
     330             220 :     VSIFree( pabyWorkData );
     331             220 :     if( eErr != CE_None )
     332                 :     {
     333               0 :         if( pabyOutData != pData )
     334               0 :             VSIFree( pabyOutData );
     335                 : 
     336               0 :         return eErr;
     337                 :     }
     338                 :     
     339                 : /* -------------------------------------------------------------------- */
     340                 : /*      Copy from work buffer to target buffer.                         */
     341                 : /* -------------------------------------------------------------------- */
     342             220 :     if( pabyOutData != pData )
     343                 :     {
     344             440 :         for( i = 0; i < nBufYSize; i++ )
     345                 :         {
     346                 :             GDALCopyWords( pabyOutData + i * (nPixelOffset * nBufXSize),
     347                 :                            eOperDataType, nPixelOffset,
     348                 :                            ((GByte *) pData) + i * nLineSpace, 
     349             220 :                            eBufType, nPixelSpace, nBufXSize );
     350                 :         }
     351                 : 
     352             220 :         VSIFree( pabyOutData );
     353                 :     }
     354                 : 
     355             220 :     return CE_None;
     356                 : }
     357                 : 
     358                 : /************************************************************************/
     359                 : /* ==================================================================== */
     360                 : /*                       VRTKernelFilteredSource                        */
     361                 : /* ==================================================================== */
     362                 : /************************************************************************/
     363                 : 
     364                 : /************************************************************************/
     365                 : /*                      VRTKernelFilteredSource()                       */
     366                 : /************************************************************************/
     367                 : 
     368               5 : VRTKernelFilteredSource::VRTKernelFilteredSource()
     369                 : 
     370                 : {
     371               5 :     GDALDataType aeSupTypes[] = { GDT_Float32 };
     372               5 :     padfKernelCoefs = NULL;
     373               5 :     nKernelSize = 0;
     374               5 :     bNormalized = FALSE;
     375                 : 
     376               5 :     SetFilteringDataTypesSupported( 1, aeSupTypes );
     377               5 : }
     378                 : 
     379                 : /************************************************************************/
     380                 : /*                      ~VRTKernelFilteredSource()                      */
     381                 : /************************************************************************/
     382                 : 
     383              10 : VRTKernelFilteredSource::~VRTKernelFilteredSource() 
     384                 : 
     385                 : {
     386               5 :     CPLFree( padfKernelCoefs );
     387              10 : }
     388                 : 
     389                 : /************************************************************************/
     390                 : /*                           SetNormalized()                            */
     391                 : /************************************************************************/
     392                 : 
     393               5 : void VRTKernelFilteredSource::SetNormalized( int bNormalizedIn )
     394                 : 
     395                 : {
     396               5 :     bNormalized = bNormalizedIn;
     397               5 : }
     398                 : 
     399                 : /************************************************************************/
     400                 : /*                             SetKernel()                              */
     401                 : /************************************************************************/
     402                 : 
     403               5 : CPLErr VRTKernelFilteredSource::SetKernel( int nNewKernelSize, 
     404                 :                                            double *padfNewCoefs )
     405                 : 
     406                 : {
     407               5 :     if( nNewKernelSize < 1 || (nNewKernelSize % 2) != 1 )
     408                 :     {
     409                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     410                 :                   "Illegal filtering kernel size %d, must be odd positive number.", 
     411               0 :                   nNewKernelSize );
     412               0 :         return CE_Failure;
     413                 :     }
     414                 : 
     415               5 :     CPLFree( padfKernelCoefs );
     416               5 :     nKernelSize = nNewKernelSize;
     417                 : 
     418                 :     padfKernelCoefs = (double *) 
     419               5 :         CPLMalloc(sizeof(double) * nKernelSize * nKernelSize );
     420                 :     memcpy( padfKernelCoefs, padfNewCoefs, 
     421               5 :             sizeof(double) * nKernelSize * nKernelSize );
     422                 : 
     423               5 :     SetExtraEdgePixels( (nNewKernelSize - 1) / 2 );
     424                 : 
     425               5 :     return CE_None;
     426                 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                             FilterData()                             */
     430                 : /************************************************************************/
     431                 : 
     432             220 : CPLErr VRTKernelFilteredSource::
     433                 : FilterData( int nXSize, int nYSize, GDALDataType eType, 
     434                 :             GByte *pabySrcData, GByte *pabyDstData )
     435                 : 
     436                 : {
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      Validate data type.                                             */
     439                 : /* -------------------------------------------------------------------- */
     440             220 :     if( eType != GDT_Float32 )
     441                 :     {
     442                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     443                 :                   "Unsupported data type (%s) in VRTKernelFilteredSource::FilterData()", 
     444               0 :                   GDALGetDataTypeName( eType ) );
     445               0 :         return CE_Failure; 
     446                 :     }
     447                 : 
     448                 :     CPLAssert( nExtraEdgePixels*2 + 1 == nKernelSize );
     449                 : 
     450                 : /* -------------------------------------------------------------------- */
     451                 : /*      Float32 case.                                                   */
     452                 : /* -------------------------------------------------------------------- */
     453             220 :     if( eType == GDT_Float32 )
     454                 :     {
     455                 :         int iX, iY;
     456                 : 
     457                 :         int bHasNoData;
     458             220 :         float fNoData = (float) poRasterBand->GetNoDataValue(&bHasNoData);
     459                 : 
     460             440 :         for( iY = 0; iY < nYSize; iY++ )
     461                 :         {
     462           10620 :             for( iX = 0; iX < nXSize; iX++ )
     463                 :             {
     464           10400 :                 int    iYY, iKern = 0;
     465           10400 :                 double dfSum = 0.0, dfKernSum = 0.0;
     466                 :                 float  fResult;
     467           10400 :                 int    iIndex = (iY+nKernelSize/2 ) * (nXSize+2*nExtraEdgePixels) + iX + nKernelSize/2;
     468           10400 :                 float  fCenter = ((float *)pabySrcData)[iIndex];
     469                 : 
     470                 :                 // Check if center srcpixel is NoData
     471           20600 :                 if(!bHasNoData || fCenter != fNoData)
     472                 :                 {
     473           40800 :                     for( iYY = 0; iYY < nKernelSize; iYY++ )
     474                 :                     {
     475                 :                         int i;
     476                 :                         float *pafData = ((float *)pabySrcData) 
     477           30600 :                                 + (iY+iYY) * (nXSize+2*nExtraEdgePixels) + iX;
     478                 : 
     479          122400 :                         for( i = 0; i < nKernelSize; i++, pafData++, iKern++ )
     480                 :                         {
     481           91800 :                             if(!bHasNoData || *pafData != fNoData)
     482                 :                             {
     483           90964 :                                 dfSum += *pafData * padfKernelCoefs[iKern];
     484           90964 :                                 dfKernSum += padfKernelCoefs[iKern];
     485                 :                             }
     486                 :                         }
     487                 :                     }
     488           10200 :                     if( bNormalized )
     489                 :                     {
     490             200 :                         if( dfKernSum != 0.0 )
     491             200 :                             fResult = (float) (dfSum / dfKernSum);
     492                 :                         else
     493               0 :                             fResult = 0.0;
     494                 :                     }
     495                 :                     else
     496           10000 :                         fResult = (float) dfSum;
     497                 : 
     498           10200 :                     ((float *) pabyDstData)[iX + iY * nXSize] = fResult;
     499                 :                 }
     500                 :                 else
     501             200 :                     ((float *) pabyDstData)[iX + iY * nXSize] = fNoData;
     502                 :             }
     503                 :         }
     504                 :     }
     505                 : 
     506             220 :     return CE_None;
     507                 : }
     508                 : 
     509                 : /************************************************************************/
     510                 : /*                              XMLInit()                               */
     511                 : /************************************************************************/
     512                 : 
     513               5 : CPLErr VRTKernelFilteredSource::XMLInit( CPLXMLNode *psTree, 
     514                 :                                          const char *pszVRTPath )
     515                 : 
     516                 : {
     517               5 :     CPLErr eErr = VRTFilteredSource::XMLInit( psTree, pszVRTPath );
     518                 :     int    nNewKernelSize, i, nCoefs;
     519                 :     double *padfNewCoefs;
     520                 : 
     521               5 :     if( eErr != CE_None )
     522               0 :         return eErr;
     523                 : 
     524               5 :     nNewKernelSize = atoi(CPLGetXMLValue(psTree,"Kernel.Size","0"));
     525                 : 
     526               5 :     if( nNewKernelSize == 0 )
     527               0 :         return CE_None;
     528                 : 
     529                 :     char **papszCoefItems = 
     530               5 :         CSLTokenizeString( CPLGetXMLValue(psTree,"Kernel.Coefs","") );
     531                 : 
     532               5 :     nCoefs = CSLCount(papszCoefItems);
     533                 : 
     534               5 :     if( nCoefs != nNewKernelSize * nNewKernelSize )
     535                 :     {
     536               0 :         CSLDestroy( papszCoefItems );
     537                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     538                 :                   "Got wrong number of filter kernel coefficients (%s).\n"
     539                 :                   "Expected %d, got %d.", 
     540                 :                   CPLGetXMLValue(psTree,"Kernel.Coefs",""),
     541               0 :                   nNewKernelSize * nNewKernelSize, nCoefs );
     542               0 :         return CE_Failure;
     543                 :     }
     544                 : 
     545               5 :     padfNewCoefs = (double *) CPLMalloc(sizeof(double) * nCoefs);
     546                 : 
     547              50 :     for( i = 0; i < nCoefs; i++ )
     548              45 :         padfNewCoefs[i] = atof(papszCoefItems[i]);
     549                 : 
     550               5 :     eErr = SetKernel( nNewKernelSize, padfNewCoefs );
     551                 : 
     552               5 :     CPLFree( padfNewCoefs );
     553               5 :     CSLDestroy( papszCoefItems );
     554                 : 
     555               5 :     SetNormalized( atoi(CPLGetXMLValue(psTree,"Kernel.normalized","0")) );
     556                 : 
     557               5 :     return eErr;
     558                 : }
     559                 : 
     560                 : /************************************************************************/
     561                 : /*                           SerializeToXML()                           */
     562                 : /************************************************************************/
     563                 : 
     564               0 : CPLXMLNode *VRTKernelFilteredSource::SerializeToXML( const char *pszVRTPath )
     565                 : 
     566                 : {
     567               0 :     CPLXMLNode *psSrc = VRTFilteredSource::SerializeToXML( pszVRTPath );
     568                 :     CPLXMLNode *psKernel;
     569                 :     char *pszKernelCoefs;
     570               0 :     int iCoef, nCoefCount = nKernelSize * nKernelSize;
     571                 : 
     572               0 :     if( psSrc == NULL )
     573               0 :         return NULL;
     574                 : 
     575               0 :     CPLFree( psSrc->pszValue );
     576               0 :     psSrc->pszValue = CPLStrdup("KernelFilteredSource" );
     577                 : 
     578               0 :     psKernel = CPLCreateXMLNode( psSrc, CXT_Element, "Kernel" );
     579                 : 
     580               0 :     if( bNormalized )
     581                 :         CPLCreateXMLNode( 
     582                 :             CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ), 
     583               0 :             CXT_Text, "1" );
     584                 :     else
     585                 :         CPLCreateXMLNode( 
     586                 :             CPLCreateXMLNode( psKernel, CXT_Attribute, "normalized" ), 
     587               0 :             CXT_Text, "0" );
     588                 : 
     589               0 :     pszKernelCoefs = (char *) CPLMalloc(nCoefCount * 32);
     590                 : 
     591               0 :     strcpy( pszKernelCoefs, "" );
     592               0 :     for( iCoef = 0; iCoef < nCoefCount; iCoef++ )
     593                 :         sprintf( pszKernelCoefs + strlen(pszKernelCoefs), 
     594               0 :                  "%.8g ", padfKernelCoefs[iCoef] );
     595                 :     
     596               0 :     CPLSetXMLValue( psKernel, "Size", CPLSPrintf( "%d", nKernelSize ) );
     597               0 :     CPLSetXMLValue( psKernel, "Coefs", pszKernelCoefs );
     598                 : 
     599               0 :     CPLFree( pszKernelCoefs );
     600                 : 
     601               0 :     return psSrc;
     602                 : }
     603                 : 
     604                 : /************************************************************************/
     605                 : /*                       VRTParseFilterSources()                        */
     606                 : /************************************************************************/
     607                 : 
     608               5 : VRTSource *VRTParseFilterSources( CPLXMLNode *psChild, const char *pszVRTPath )
     609                 : 
     610                 : {
     611                 :     VRTSource *poSrc;
     612                 : 
     613               5 :     if( EQUAL(psChild->pszValue,"KernelFilteredSource") )
     614                 :     {
     615               5 :         poSrc = new VRTKernelFilteredSource();
     616               5 :         if( poSrc->XMLInit( psChild, pszVRTPath ) == CE_None )
     617               5 :             return poSrc;
     618                 :         else
     619               0 :             delete poSrc;
     620                 :     }
     621                 : 
     622               0 :     return NULL;
     623                 : }
     624                 : 

Generated by: LCOV version 1.7