21#include "cpl_string.h" 
   39  : mInputFile( inputFile )
 
   40  , mOutputFile( outputFile )
 
   41  , mOutputFormat( outputFormat )
 
   54    if ( ! source.isEmpty() )
 
   58        QgsDebugMsgLevel( QStringLiteral( 
"Running OpenCL program: %1" ).arg( openClProgramBaseName( ) ), 2 );
 
   59        return processRasterGPU( source, feedback );
 
   61      catch ( cl::Error &e )
 
   63        const QString err = QObject::tr( 
"Error running OpenCL program: %1 - %2" ).arg( e.what( ), 
QgsOpenClUtils::errorText( e.err( ) ) );
 
   70      const QString err = QObject::tr( 
"Error loading OpenCL program sources" );
 
   78    return processRasterCPU( feedback );
 
   84  return processRasterCPU( feedback );
 
   93    nCellsX = GDALGetRasterXSize( inputDataset.get() );
 
   94    nCellsY = GDALGetRasterYSize( inputDataset.get() );
 
   97    if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
 
  105GDALDriverH QgsNineCellFilter::openOutputDriver()
 
  108  GDALDriverH outputDriver = GDALGetDriverByName( 
mOutputFormat.toLocal8Bit().data() );
 
  131  const int xSize = GDALGetRasterXSize( inputDataset );
 
  132  const int ySize = GDALGetRasterYSize( inputDataset );
 
  135  char **papszOptions = 
nullptr;
 
  137  if ( !outputDataset )
 
  139    return outputDataset;
 
  143  double geotransform[6];
 
  144  if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
 
  148  GDALSetGeoTransform( outputDataset.get(), geotransform );
 
  162  const char *projection = GDALGetProjectionRef( inputDataset );
 
  163  GDALSetProjection( outputDataset.get(), projection );
 
  165  return outputDataset;
 
  171int QgsNineCellFilter::processRasterGPU( 
const QString &source, 
QgsFeedback *feedback )
 
  185  GDALDriverH outputDriver = openOutputDriver();
 
  192  if ( !outputDataset )
 
  198  GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
 
  205  GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
 
  206  if ( !outputRasterBand )
 
  211  GDALSetRasterNoDataValue( outputRasterBand, -9999 );
 
  228  std::vector<float> rasterParams;
 
  238  addExtraRasterParams( rasterParams );
 
  240  const std::size_t bufferSize( 
sizeof( 
float ) * ( xSize + 2 ) );
 
  241  const std::size_t inputSize( 
sizeof( 
float ) * ( xSize ) );
 
  243  cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(), 
true, 
false, 
nullptr );
 
  244  cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, 
nullptr, 
nullptr );
 
  245  cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, 
nullptr, 
nullptr );
 
  246  cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize, 
nullptr, 
nullptr );
 
  247  cl::Buffer *scanLineBuffer[3] = {&scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer};
 
  248  cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize, 
nullptr, 
nullptr );
 
  254  auto kernel = cl::KernelFunctor <
 
  260                > ( program, 
"processNineCellWindow" );
 
  263  std::vector<int> rowIndex = {0, 1, 2};
 
  266  for ( 
int i = 0; i < ySize; ++i )
 
  275      feedback->
setProgress( 100.0 * 
static_cast< double >( i ) / ySize );
 
  282      for ( 
int a = 0; a < xSize + 2 ; ++a )
 
  286      queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
 
  289      if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  293      queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
 
  296      if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  300      queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
 
  306      if ( i == ySize - 1 ) 
 
  308        for ( 
int a = 0; a < xSize + 2; ++a )
 
  312        queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); 
 
  317        if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  321        queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); 
 
  325    kernel( cl::EnqueueArgs(
 
  329            *scanLineBuffer[rowIndex[0]],
 
  330            *scanLineBuffer[rowIndex[1]],
 
  331            *scanLineBuffer[rowIndex[2]],
 
  336    queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
 
  338    if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  342    std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
 
  357int QgsNineCellFilter::processRasterCPU( 
QgsFeedback *feedback )
 
  371  GDALDriverH outputDriver = openOutputDriver();
 
  378  if ( !outputDataset )
 
  384  GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
 
  391  GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
 
  392  if ( !outputRasterBand )
 
  397  GDALSetRasterNoDataValue( outputRasterBand, -9999 );
 
  406  const std::size_t bufferSize( 
sizeof( 
float ) * ( xSize + 2 ) );
 
  407  float *scanLine1 = ( 
float * ) CPLMalloc( bufferSize );
 
  408  float *scanLine2 = ( 
float * ) CPLMalloc( bufferSize );
 
  409  float *scanLine3 = ( 
float * ) CPLMalloc( bufferSize );
 
  411  float *resultLine = ( 
float * ) CPLMalloc( 
sizeof( 
float ) * xSize );
 
  414  for ( 
int yIndex = 0; yIndex < ySize; ++yIndex )
 
  423      feedback->
setProgress( 100.0 * 
static_cast< double >( yIndex ) / ySize );
 
  429      for ( 
int a = 0; a < xSize + 2 ; ++a )
 
  434      if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  442      CPLFree( scanLine1 );
 
  443      scanLine1 = scanLine2;
 
  444      scanLine2 = scanLine3;
 
  445      scanLine3 = ( 
float * ) CPLMalloc( bufferSize );
 
  449    if ( yIndex == ySize - 1 ) 
 
  451      for ( 
int a = 0; a < xSize + 2; ++a )
 
  458      if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  471    for ( 
int xIndex = 0; xIndex < xSize ; ++xIndex )
 
  474      resultLine[ xIndex ] = 
processNineCellWindow( &scanLine1[ xIndex ], &scanLine1[ xIndex + 1 ], &scanLine1[ xIndex + 2 ],
 
  475                             &scanLine2[ xIndex ], &scanLine2[ xIndex + 1 ], &scanLine2[ xIndex + 2 ],
 
  476                             &scanLine3[ xIndex ], &scanLine3[ xIndex + 1 ], &scanLine3[ xIndex + 2 ] );
 
  480    if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  486  CPLFree( resultLine );
 
  487  CPLFree( scanLine1 );
 
  488  CPLFree( scanLine2 );
 
  489  CPLFree( scanLine3 );
 
Base class for feedback objects to be used for cancellation of something running in a worker thread.
 
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
 
void setProgress(double progress)
Sets the current progress for the feedback object.
 
static bool supportsRasterCreate(GDALDriverH driver)
Reads whether a driver supports GDALCreate() for raster purposes.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
 
int processRaster(QgsFeedback *feedback=nullptr)
Starts the calculation, reads from mInputFile and stores the result in mOutputFile.
 
float mInputNodataValue
The nodata value of the input layer.
 
virtual float processNineCellWindow(float *x11, float *x21, float *x31, float *x12, float *x22, float *x32, float *x13, float *x23, float *x33)=0
Calculates output value from nine input values.
 
QgsNineCellFilter(const QString &inputFile, const QString &outputFile, const QString &outputFormat)
Constructor that takes input file, output file and output format (GDAL string)
 
float mOutputNodataValue
The nodata value of the output layer.
 
double mZFactor
Scale factor for z-value if x-/y- units are different to z-units (111120 for degree->meters and 37040...
 
static Q_DECL_DEPRECATED cl::Program buildProgram(const cl::Context &context, const QString &source, ExceptionBehavior exceptionBehavior=Catch)
Build the program from source in the given context and depending on exceptionBehavior can throw or ca...
 
static cl::Context context()
Context factory.
 
static bool enabled()
Returns true if OpenCL is enabled in the user settings.
 
static bool available()
Checks whether a suitable OpenCL platform and device is available on this system and initialize the Q...
 
static QString errorText(const int errorCode)
Returns a string representation from an OpenCL errorCode.
 
static cl::CommandQueue commandQueue()
Create an OpenCL command queue from the default context.
 
static QString sourceFromBaseName(const QString &baseName)
Returns the full path to a an OpenCL source file from the baseName ('.cl' extension is automatically ...
 
static QLatin1String LOGMESSAGE_TAG
OpenCL string for message logs.
 
Custom exception class for processing related exceptions.
 
void CORE_EXPORT fast_delete_and_close(dataset_unique_ptr &dataset, GDALDriverH driver, const QString &path)
Performs a fast close of an unwanted GDAL dataset handle by deleting the underlying data store.
 
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
Tiny smart-pointer-like wrapper around CPLMalloc and CPLFree: this is needed because OpenCL C++ API m...