LCOV - code coverage report
Current view: top level - analysis/raster - qgsninecellfilter.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 127 0.0 %
Date: 2021-04-10 08:29:14 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                           qgsninecellfilter.h  -  description
       3                 :            :                              -------------------
       4                 :            :     begin                : August 6th, 2009
       5                 :            :     copyright            : (C) 2009 by Marco Hugentobler
       6                 :            :     email                : marco dot hugentobler at karto dot baug dot ethz dot ch
       7                 :            :  ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #include "qgsgdalutils.h"
      19                 :            : #include "qgsninecellfilter.h"
      20                 :            : #include "qgslogger.h"
      21                 :            : #include "cpl_string.h"
      22                 :            : #include "qgsfeedback.h"
      23                 :            : #include "qgsogrutils.h"
      24                 :            : #include "qgsmessagelog.h"
      25                 :            : 
      26                 :            : #ifdef HAVE_OPENCL
      27                 :            : #include "qgsopenclutils.h"
      28                 :            : #endif
      29                 :            : 
      30                 :            : #include <QFile>
      31                 :            : #include <QDebug>
      32                 :            : #include <QFileInfo>
      33                 :            : #include <iterator>
      34                 :            : 
      35                 :            : 
      36                 :            : 
      37                 :          0 : QgsNineCellFilter::QgsNineCellFilter( const QString &inputFile, const QString &outputFile, const QString &outputFormat )
      38                 :          0 :   : mInputFile( inputFile )
      39                 :          0 :   , mOutputFile( outputFile )
      40                 :          0 :   , mOutputFormat( outputFormat )
      41                 :          0 : {
      42                 :            : 
      43                 :          0 : }
      44                 :            : 
      45                 :            : // TODO: return an anum instead of an int
      46                 :          0 : int QgsNineCellFilter::processRaster( QgsFeedback *feedback )
      47                 :            : {
      48                 :            : #ifdef HAVE_OPENCL
      49                 :            :   if ( QgsOpenClUtils::enabled() && QgsOpenClUtils::available() && ! openClProgramBaseName( ).isEmpty() )
      50                 :            :   {
      51                 :            :     // Load the program sources
      52                 :            :     QString source( QgsOpenClUtils::sourceFromBaseName( openClProgramBaseName( ) ) );
      53                 :            :     if ( ! source.isEmpty() )
      54                 :            :     {
      55                 :            :       try
      56                 :            :       {
      57                 :            :         QgsDebugMsg( QObject::tr( "Running OpenCL program: %1" ).arg( openClProgramBaseName( ) ) );
      58                 :            :         return processRasterGPU( source, feedback );
      59                 :            :       }
      60                 :            :       catch ( cl::Error &e )
      61                 :            :       {
      62                 :            :         QString err = QObject::tr( "Error running OpenCL program: %1 - %2" ).arg( e.what( ), QgsOpenClUtils::errorText( e.err( ) ) );
      63                 :            :         QgsMessageLog::logMessage( err, QgsOpenClUtils::LOGMESSAGE_TAG, Qgis::Critical );
      64                 :            :         throw QgsProcessingException( err );
      65                 :            :       }
      66                 :            :     }
      67                 :            :     else
      68                 :            :     {
      69                 :            :       QString err = QObject::tr( "Error loading OpenCL program sources" );
      70                 :            :       QgsMessageLog::logMessage( err,
      71                 :            :                                  QgsOpenClUtils::LOGMESSAGE_TAG, Qgis::Critical );
      72                 :            :       throw QgsProcessingException( err );
      73                 :            :     }
      74                 :            :   }
      75                 :            :   else
      76                 :            :   {
      77                 :            :     return processRasterCPU( feedback );
      78                 :            :   }
      79                 :            : #ifndef _MSC_VER
      80                 :            :   return 1;
      81                 :            : #endif
      82                 :            : #else
      83                 :          0 :   return processRasterCPU( feedback );
      84                 :            : #endif
      85                 :            : }
      86                 :            : 
      87                 :          0 : gdal::dataset_unique_ptr QgsNineCellFilter::openInputFile( int &nCellsX, int &nCellsY )
      88                 :            : {
      89                 :          0 :   gdal::dataset_unique_ptr inputDataset( GDALOpen( mInputFile.toUtf8().constData(), GA_ReadOnly ) );
      90                 :          0 :   if ( inputDataset )
      91                 :            :   {
      92                 :          0 :     nCellsX = GDALGetRasterXSize( inputDataset.get() );
      93                 :          0 :     nCellsY = GDALGetRasterYSize( inputDataset.get() );
      94                 :            : 
      95                 :            :     //we need at least one band
      96                 :          0 :     if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
      97                 :            :     {
      98                 :          0 :       return nullptr;
      99                 :            :     }
     100                 :          0 :   }
     101                 :          0 :   return inputDataset;
     102                 :          0 : }
     103                 :            : 
     104                 :          0 : GDALDriverH QgsNineCellFilter::openOutputDriver()
     105                 :            : {
     106                 :            :   //open driver
     107                 :          0 :   GDALDriverH outputDriver = GDALGetDriverByName( mOutputFormat.toLocal8Bit().data() );
     108                 :            : 
     109                 :          0 :   if ( !outputDriver )
     110                 :            :   {
     111                 :          0 :     return outputDriver; //return nullptr, driver does not exist
     112                 :            :   }
     113                 :            : 
     114                 :          0 :   if ( !QgsGdalUtils::supportsRasterCreate( outputDriver ) )
     115                 :            :   {
     116                 :          0 :     return nullptr; //driver exist, but it does not support the create operation
     117                 :            :   }
     118                 :            : 
     119                 :          0 :   return outputDriver;
     120                 :          0 : }
     121                 :            : 
     122                 :            : 
     123                 :          0 : gdal::dataset_unique_ptr QgsNineCellFilter::openOutputFile( GDALDatasetH inputDataset, GDALDriverH outputDriver )
     124                 :            : {
     125                 :          0 :   if ( !inputDataset )
     126                 :            :   {
     127                 :          0 :     return nullptr;
     128                 :            :   }
     129                 :            : 
     130                 :          0 :   int xSize = GDALGetRasterXSize( inputDataset );
     131                 :          0 :   int ySize = GDALGetRasterYSize( inputDataset );
     132                 :            : 
     133                 :            :   //open output file
     134                 :          0 :   char **papszOptions = nullptr;
     135                 :          0 :   gdal::dataset_unique_ptr outputDataset( GDALCreate( outputDriver, mOutputFile.toUtf8().constData(), xSize, ySize, 1, GDT_Float32, papszOptions ) );
     136                 :          0 :   if ( !outputDataset )
     137                 :            :   {
     138                 :          0 :     return outputDataset;
     139                 :            :   }
     140                 :            : 
     141                 :            :   //get geotransform from inputDataset
     142                 :            :   double geotransform[6];
     143                 :          0 :   if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
     144                 :          0 :   {
     145                 :          0 :     return nullptr;
     146                 :          0 :   }
     147                 :          0 :   GDALSetGeoTransform( outputDataset.get(), geotransform );
     148                 :          0 : 
     149                 :            :   //make sure mCellSizeX and mCellSizeY are always > 0
     150                 :          0 :   mCellSizeX = geotransform[1];
     151                 :          0 :   if ( mCellSizeX < 0 )
     152                 :            :   {
     153                 :          0 :     mCellSizeX = -mCellSizeX;
     154                 :          0 :   }
     155                 :          0 :   mCellSizeY = geotransform[5];
     156                 :          0 :   if ( mCellSizeY < 0 )
     157                 :            :   {
     158                 :          0 :     mCellSizeY = -mCellSizeY;
     159                 :          0 :   }
     160                 :            : 
     161                 :          0 :   const char *projection = GDALGetProjectionRef( inputDataset );
     162                 :          0 :   GDALSetProjection( outputDataset.get(), projection );
     163                 :            : 
     164                 :          0 :   return outputDataset;
     165                 :          0 : }
     166                 :            : 
     167                 :            : #ifdef HAVE_OPENCL
     168                 :            : 
     169                 :            : // TODO: return an anum instead of an int
     170                 :            : int QgsNineCellFilter::processRasterGPU( const QString &source, QgsFeedback *feedback )
     171                 :            : {
     172                 :            : 
     173                 :            :   GDALAllRegister();
     174                 :            : 
     175                 :            :   //open input file
     176                 :            :   int xSize, ySize;
     177                 :            :   gdal::dataset_unique_ptr inputDataset( openInputFile( xSize, ySize ) );
     178                 :            :   if ( !inputDataset )
     179                 :            :   {
     180                 :            :     return 1; //opening of input file failed
     181                 :            :   }
     182                 :            : 
     183                 :            :   //output driver
     184                 :            :   GDALDriverH outputDriver = openOutputDriver();
     185                 :            :   if ( !outputDriver )
     186                 :            :   {
     187                 :            :     return 2;
     188                 :            :   }
     189                 :            : 
     190                 :            :   gdal::dataset_unique_ptr outputDataset( openOutputFile( inputDataset.get(), outputDriver ) );
     191                 :            :   if ( !outputDataset )
     192                 :            :   {
     193                 :            :     return 3; //create operation on output file failed
     194                 :            :   }
     195                 :            : 
     196                 :            :   //open first raster band for reading (operation is only for single band raster)
     197                 :            :   GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
     198                 :            :   if ( !rasterBand )
     199                 :            :   {
     200                 :            :     return 4;
     201                 :            :   }
     202                 :            :   mInputNodataValue = GDALGetRasterNoDataValue( rasterBand, nullptr );
     203                 :            : 
     204                 :            :   GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
     205                 :            :   if ( !outputRasterBand )
     206                 :            :   {
     207                 :            :     return 5;
     208                 :            :   }
     209                 :            :   //try to set -9999 as nodata value
     210                 :            :   GDALSetRasterNoDataValue( outputRasterBand, -9999 );
     211                 :            :   mOutputNodataValue = GDALGetRasterNoDataValue( outputRasterBand, nullptr );
     212                 :            : 
     213                 :            :   if ( ySize < 3 ) //we require at least three rows (should be true for most datasets)
     214                 :            :   {
     215                 :            :     return 6;
     216                 :            :   }
     217                 :            : 
     218                 :            :   // Prepare context and queue
     219                 :            :   cl::Context ctx = QgsOpenClUtils::context();
     220                 :            :   cl::CommandQueue queue = QgsOpenClUtils::commandQueue();
     221                 :            : 
     222                 :            :   //keep only three scanlines in memory at a time, make room for initial and final nodata
     223                 :            :   QgsOpenClUtils::CPLAllocator<float> scanLine( xSize + 2 );
     224                 :            :   QgsOpenClUtils::CPLAllocator<float> resultLine( xSize );
     225                 :            : 
     226                 :            :   // Cast to float (because double just crashes on some GPUs)
     227                 :            :   std::vector<float> rasterParams;
     228                 :            : 
     229                 :            :   rasterParams.push_back( mInputNodataValue ); //  0
     230                 :            :   rasterParams.push_back( mOutputNodataValue ); // 1
     231                 :            :   rasterParams.push_back( mZFactor ); // 2
     232                 :            :   rasterParams.push_back( mCellSizeX ); // 3
     233                 :            :   rasterParams.push_back( mCellSizeY ); // 4
     234                 :            : 
     235                 :            :   // Allow subclasses to add extra params needed for computation:
     236                 :            :   // used to pass additional args to opencl program
     237                 :            :   addExtraRasterParams( rasterParams );
     238                 :            : 
     239                 :            :   std::size_t bufferSize( sizeof( float ) * ( xSize + 2 ) );
     240                 :            :   std::size_t inputSize( sizeof( float ) * ( xSize ) );
     241                 :            : 
     242                 :            :   cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(), true, false, nullptr );
     243                 :            :   cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
     244                 :            :   cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
     245                 :            :   cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, nullptr, nullptr );
     246                 :            :   cl::Buffer *scanLineBuffer[3] = {&scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer};
     247                 :            :   cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize, nullptr, nullptr );
     248                 :            : 
     249                 :            :   // Create a program from the kernel source
     250                 :            :   cl::Program program( QgsOpenClUtils::buildProgram( source, QgsOpenClUtils::ExceptionBehavior::Throw ) );
     251                 :            : 
     252                 :            :   // Create the OpenCL kernel
     253                 :            :   auto kernel = cl::KernelFunctor <
     254                 :            :                 cl::Buffer &,
     255                 :            :                 cl::Buffer &,
     256                 :            :                 cl::Buffer &,
     257                 :            :                 cl::Buffer &,
     258                 :            :                 cl::Buffer &
     259                 :            :                 > ( program, "processNineCellWindow" );
     260                 :            : 
     261                 :            :   // Rotate buffer index
     262                 :            :   std::vector<int> rowIndex = {0, 1, 2};
     263                 :            : 
     264                 :            :   // values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values
     265                 :            :   for ( int i = 0; i < ySize; ++i )
     266                 :            :   {
     267                 :            :     if ( feedback && feedback->isCanceled() )
     268                 :            :     {
     269                 :            :       break;
     270                 :            :     }
     271                 :            : 
     272                 :            :     if ( feedback )
     273                 :            :     {
     274                 :            :       feedback->setProgress( 100.0 * static_cast< double >( i ) / ySize );
     275                 :            :     }
     276                 :            : 
     277                 :            :     if ( i == 0 )
     278                 :            :     {
     279                 :            :       // Fill scanline 1 with (input) nodata for the values above the first row and
     280                 :            :       // feed scanline2 with the first actual data row
     281                 :            :       for ( int a = 0; a < xSize + 2 ; ++a )
     282                 :            :       {
     283                 :            :         scanLine[a] = mInputNodataValue;
     284                 :            :       }
     285                 :            :       queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
     286                 :            : 
     287                 :            :       // Read scanline2: first real raster row
     288                 :            :       if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     289                 :            :       {
     290                 :            :         QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     291                 :            :       }
     292                 :            :       queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
     293                 :            : 
     294                 :            :       // Read scanline3: second real raster row
     295                 :            :       if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     296                 :            :       {
     297                 :            :         QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     298                 :            :       }
     299                 :            :       queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
     300                 :            :     }
     301                 :            :     else
     302                 :            :     {
     303                 :            :       // Normally fetch only scanLine3 and move forward one row
     304                 :            :       // Read scanline 3, fill the last row with nodata values if it's the last iteration
     305                 :            :       if ( i == ySize - 1 ) //fill the row below the bottom with nodata values
     306                 :            :       {
     307                 :            :         for ( int a = 0; a < xSize + 2; ++a )
     308                 :            :         {
     309                 :            :           scanLine[a] = mInputNodataValue;
     310                 :            :         }
     311                 :            :         queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); // row 0
     312                 :            :       }
     313                 :            :       else // Read line i + 1 and put it into scanline 3
     314                 :            :         // Overwrite from input, skip first and last
     315                 :            :       {
     316                 :            :         if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     317                 :            :         {
     318                 :            :           QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     319                 :            :         }
     320                 :            :         queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); // row 0
     321                 :            :       }
     322                 :            :     }
     323                 :            : 
     324                 :            :     kernel( cl::EnqueueArgs(
     325                 :            :               queue,
     326                 :            :               cl::NDRange( xSize )
     327                 :            :             ),
     328                 :            :             *scanLineBuffer[rowIndex[0]],
     329                 :            :             *scanLineBuffer[rowIndex[1]],
     330                 :            :             *scanLineBuffer[rowIndex[2]],
     331                 :            :             resultLineBuffer,
     332                 :            :             rasterParamsBuffer
     333                 :            :           );
     334                 :            : 
     335                 :            :     queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
     336                 :            : 
     337                 :            :     if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     338                 :            :     {
     339                 :            :       QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     340                 :            :     }
     341                 :            :     std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
     342                 :            :   }
     343                 :            : 
     344                 :            :   if ( feedback && feedback->isCanceled() )
     345                 :            :   {
     346                 :            :     //delete the dataset without closing (because it is faster)
     347                 :            :     gdal::fast_delete_and_close( outputDataset, outputDriver, mOutputFile );
     348                 :            :     return 7;
     349                 :            :   }
     350                 :            :   return 0;
     351                 :            : }
     352                 :            : #endif
     353                 :            : 
     354                 :            : 
     355                 :            : // TODO: return an anum instead of an int
     356                 :          0 : int QgsNineCellFilter::processRasterCPU( QgsFeedback *feedback )
     357                 :            : {
     358                 :            : 
     359                 :          0 :   GDALAllRegister();
     360                 :            : 
     361                 :            :   //open input file
     362                 :            :   int xSize, ySize;
     363                 :          0 :   gdal::dataset_unique_ptr inputDataset( openInputFile( xSize, ySize ) );
     364                 :          0 :   if ( !inputDataset )
     365                 :            :   {
     366                 :          0 :     return 1; //opening of input file failed
     367                 :            :   }
     368                 :            : 
     369                 :            :   //output driver
     370                 :          0 :   GDALDriverH outputDriver = openOutputDriver();
     371                 :          0 :   if ( !outputDriver )
     372                 :            :   {
     373                 :          0 :     return 2;
     374                 :            :   }
     375                 :            : 
     376                 :          0 :   gdal::dataset_unique_ptr outputDataset( openOutputFile( inputDataset.get(), outputDriver ) );
     377                 :          0 :   if ( !outputDataset )
     378                 :            :   {
     379                 :          0 :     return 3; //create operation on output file failed
     380                 :            :   }
     381                 :            : 
     382                 :            :   //open first raster band for reading (operation is only for single band raster)
     383                 :          0 :   GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
     384                 :          0 :   if ( !rasterBand )
     385                 :            :   {
     386                 :          0 :     return 4;
     387                 :            :   }
     388                 :          0 :   mInputNodataValue = GDALGetRasterNoDataValue( rasterBand, nullptr );
     389                 :            : 
     390                 :          0 :   GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
     391                 :          0 :   if ( !outputRasterBand )
     392                 :            :   {
     393                 :          0 :     return 5;
     394                 :            :   }
     395                 :            :   //try to set -9999 as nodata value
     396                 :          0 :   GDALSetRasterNoDataValue( outputRasterBand, -9999 );
     397                 :          0 :   mOutputNodataValue = GDALGetRasterNoDataValue( outputRasterBand, nullptr );
     398                 :            : 
     399                 :          0 :   if ( ySize < 3 ) //we require at least three rows (should be true for most datasets)
     400                 :            :   {
     401                 :          0 :     return 6;
     402                 :            :   }
     403                 :            : 
     404                 :            :   //keep only three scanlines in memory at a time, make room for initial and final nodata
     405                 :          0 :   std::size_t bufferSize( sizeof( float ) * ( xSize + 2 ) );
     406                 :          0 :   float *scanLine1 = ( float * ) CPLMalloc( bufferSize );
     407                 :          0 :   float *scanLine2 = ( float * ) CPLMalloc( bufferSize );
     408                 :          0 :   float *scanLine3 = ( float * ) CPLMalloc( bufferSize );
     409                 :            : 
     410                 :          0 :   float *resultLine = ( float * ) CPLMalloc( sizeof( float ) * xSize );
     411                 :            : 
     412                 :            :   //values outside the layer extent (if the 3x3 window is on the border) are sent to the processing method as (input) nodata values
     413                 :          0 :   for ( int yIndex = 0; yIndex < ySize; ++yIndex )
     414                 :            :   {
     415                 :          0 :     if ( feedback && feedback->isCanceled() )
     416                 :            :     {
     417                 :          0 :       break;
     418                 :            :     }
     419                 :            : 
     420                 :          0 :     if ( feedback )
     421                 :            :     {
     422                 :          0 :       feedback->setProgress( 100.0 * static_cast< double >( yIndex ) / ySize );
     423                 :          0 :     }
     424                 :            : 
     425                 :          0 :     if ( yIndex == 0 )
     426                 :            :     {
     427                 :            :       //fill scanline 1 with (input) nodata for the values above the first row and feed scanline2 with the first row
     428                 :          0 :       for ( int a = 0; a < xSize + 2 ; ++a )
     429                 :            :       {
     430                 :          0 :         scanLine1[a] = mInputNodataValue;
     431                 :          0 :       }
     432                 :            :       // Read scanline2
     433                 :          0 :       if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     434                 :            :       {
     435                 :          0 :         QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     436                 :          0 :       }
     437                 :          0 :     }
     438                 :            :     else
     439                 :            :     {
     440                 :            :       //normally fetch only scanLine3 and release scanline 1 if we move forward one row
     441                 :          0 :       CPLFree( scanLine1 );
     442                 :          0 :       scanLine1 = scanLine2;
     443                 :          0 :       scanLine2 = scanLine3;
     444                 :          0 :       scanLine3 = ( float * ) CPLMalloc( bufferSize );
     445                 :            :     }
     446                 :            : 
     447                 :            :     // Read scanline 3
     448                 :          0 :     if ( yIndex == ySize - 1 ) //fill the row below the bottom with nodata values
     449                 :            :     {
     450                 :          0 :       for ( int a = 0; a < xSize + 2; ++a )
     451                 :            :       {
     452                 :          0 :         scanLine3[a] = mInputNodataValue;
     453                 :          0 :       }
     454                 :          0 :     }
     455                 :            :     else
     456                 :            :     {
     457                 :          0 :       if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     458                 :            :       {
     459                 :          0 :         QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     460                 :          0 :       }
     461                 :            :     }
     462                 :            :     // Set first and last extra columns to nodata
     463                 :          0 :     scanLine1[0] = scanLine1[xSize + 1] = mInputNodataValue;
     464                 :          0 :     scanLine2[0] = scanLine2[xSize + 1] = mInputNodataValue;
     465                 :          0 :     scanLine3[0] = scanLine3[xSize + 1] = mInputNodataValue;
     466                 :            : 
     467                 :            : 
     468                 :            : 
     469                 :            :     // j is the x axis index, skip 0 and last cell that have been filled with nodata
     470                 :          0 :     for ( int xIndex = 0; xIndex < xSize ; ++xIndex )
     471                 :            :     {
     472                 :            :       // cells(x, y) x11, x21, x31, x12, x22, x32, x13, x23, x33
     473                 :          0 :       resultLine[ xIndex ] = processNineCellWindow( &scanLine1[ xIndex ], &scanLine1[ xIndex + 1 ], &scanLine1[ xIndex + 2 ],
     474                 :          0 :                              &scanLine2[ xIndex ], &scanLine2[ xIndex + 1 ], &scanLine2[ xIndex + 2 ],
     475                 :          0 :                              &scanLine3[ xIndex ], &scanLine3[ xIndex + 1 ], &scanLine3[ xIndex + 2 ] );
     476                 :            : 
     477                 :          0 :     }
     478                 :            : 
     479                 :          0 :     if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
     480                 :            :     {
     481                 :          0 :       QgsDebugMsg( QStringLiteral( "Raster IO Error" ) );
     482                 :          0 :     }
     483                 :          0 :   }
     484                 :            : 
     485                 :          0 :   CPLFree( resultLine );
     486                 :          0 :   CPLFree( scanLine1 );
     487                 :          0 :   CPLFree( scanLine2 );
     488                 :          0 :   CPLFree( scanLine3 );
     489                 :            : 
     490                 :          0 :   if ( feedback && feedback->isCanceled() )
     491                 :            :   {
     492                 :            :     //delete the dataset without closing (because it is faster)
     493                 :          0 :     gdal::fast_delete_and_close( outputDataset, outputDriver, mOutputFile );
     494                 :          0 :     return 7;
     495                 :            :   }
     496                 :          0 :   return 0;
     497                 :          0 : }

Generated by: LCOV version 1.14