21 #include "cpl_string.h" 
   38   : mInputFile( inputFile )
 
   39   , mOutputFile( outputFile )
 
   40   , mOutputFormat( outputFormat )
 
   53     if ( ! source.isEmpty() )
 
   57         QgsDebugMsg( QObject::tr( 
"Running OpenCL program: %1" ).arg( openClProgramBaseName( ) ) );
 
   58         return processRasterGPU( source, feedback );
 
   60       catch ( cl::Error &e )
 
   62         QString err = QObject::tr( 
"Error running OpenCL program: %1 - %2" ).arg( e.what( ), 
QgsOpenClUtils::errorText( e.err( ) ) );
 
   69       QString err = QObject::tr( 
"Error loading OpenCL program sources" );
 
   77     return processRasterCPU( feedback );
 
   83   return processRasterCPU( feedback );
 
   92     nCellsX = GDALGetRasterXSize( inputDataset.get() );
 
   93     nCellsY = GDALGetRasterYSize( inputDataset.get() );
 
   96     if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
 
  104 GDALDriverH QgsNineCellFilter::openOutputDriver()
 
  107   GDALDriverH outputDriver = GDALGetDriverByName( 
mOutputFormat.toLocal8Bit().data() );
 
  130   int xSize = GDALGetRasterXSize( inputDataset );
 
  131   int ySize = GDALGetRasterYSize( inputDataset );
 
  134   char **papszOptions = 
nullptr;
 
  136   if ( !outputDataset )
 
  138     return outputDataset;
 
  142   double geotransform[6];
 
  143   if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
 
  147   GDALSetGeoTransform( outputDataset.get(), geotransform );
 
  161   const char *projection = GDALGetProjectionRef( inputDataset );
 
  162   GDALSetProjection( outputDataset.get(), projection );
 
  164   return outputDataset;
 
  170 int QgsNineCellFilter::processRasterGPU( 
const QString &source, 
QgsFeedback *feedback )
 
  184   GDALDriverH outputDriver = openOutputDriver();
 
  191   if ( !outputDataset )
 
  197   GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
 
  204   GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
 
  205   if ( !outputRasterBand )
 
  210   GDALSetRasterNoDataValue( outputRasterBand, -9999 );
 
  227   std::vector<float> rasterParams;
 
  237   addExtraRasterParams( rasterParams );
 
  239   std::size_t bufferSize( 
sizeof( 
float ) * ( xSize + 2 ) );
 
  240   std::size_t inputSize( 
sizeof( 
float ) * ( xSize ) );
 
  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 );
 
  253   auto kernel = cl::KernelFunctor <
 
  259                 > ( program, 
"processNineCellWindow" );
 
  262   std::vector<int> rowIndex = {0, 1, 2};
 
  265   for ( 
int i = 0; i < ySize; ++i )
 
  274       feedback->
setProgress( 100.0 * 
static_cast< double >( i ) / ySize );
 
  281       for ( 
int a = 0; a < xSize + 2 ; ++a )
 
  285       queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
 
  288       if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  290         QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  292       queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
 
  295       if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  297         QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  299       queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
 
  305       if ( i == ySize - 1 ) 
 
  307         for ( 
int a = 0; a < xSize + 2; ++a )
 
  311         queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); 
 
  316         if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  318           QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  320         queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() ); 
 
  324     kernel( cl::EnqueueArgs(
 
  328             *scanLineBuffer[rowIndex[0]],
 
  329             *scanLineBuffer[rowIndex[1]],
 
  330             *scanLineBuffer[rowIndex[2]],
 
  335     queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
 
  337     if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  339       QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  341     std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
 
  356 int QgsNineCellFilter::processRasterCPU( 
QgsFeedback *feedback )
 
  370   GDALDriverH outputDriver = openOutputDriver();
 
  377   if ( !outputDataset )
 
  383   GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
 
  390   GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
 
  391   if ( !outputRasterBand )
 
  396   GDALSetRasterNoDataValue( outputRasterBand, -9999 );
 
  405   std::size_t bufferSize( 
sizeof( 
float ) * ( xSize + 2 ) );
 
  406   float *scanLine1 = ( 
float * ) CPLMalloc( bufferSize );
 
  407   float *scanLine2 = ( 
float * ) CPLMalloc( bufferSize );
 
  408   float *scanLine3 = ( 
float * ) CPLMalloc( bufferSize );
 
  410   float *resultLine = ( 
float * ) CPLMalloc( 
sizeof( 
float ) * xSize );
 
  413   for ( 
int yIndex = 0; yIndex < ySize; ++yIndex )
 
  422       feedback->
setProgress( 100.0 * 
static_cast< double >( yIndex ) / ySize );
 
  428       for ( 
int a = 0; a < xSize + 2 ; ++a )
 
  433       if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  435         QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  441       CPLFree( scanLine1 );
 
  442       scanLine1 = scanLine2;
 
  443       scanLine2 = scanLine3;
 
  444       scanLine3 = ( 
float * ) CPLMalloc( bufferSize );
 
  448     if ( yIndex == ySize - 1 ) 
 
  450       for ( 
int a = 0; a < xSize + 2; ++a )
 
  457       if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  459         QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  470     for ( 
int xIndex = 0; xIndex < xSize ; ++xIndex )
 
  473       resultLine[ xIndex ] = 
processNineCellWindow( &scanLine1[ xIndex ], &scanLine1[ xIndex + 1 ], &scanLine1[ xIndex + 2 ],
 
  474                              &scanLine2[ xIndex ], &scanLine2[ xIndex + 1 ], &scanLine2[ xIndex + 2 ],
 
  475                              &scanLine3[ xIndex ], &scanLine3[ xIndex + 1 ], &scanLine3[ xIndex + 2 ] );
 
  479     if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
 
  481       QgsDebugMsg( QStringLiteral( 
"Raster IO Error" ) );
 
  485   CPLFree( resultLine );
 
  486   CPLFree( scanLine1 );
 
  487   CPLFree( scanLine2 );
 
  488   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.
Tiny smart-pointer-like wrapper around CPLMalloc and CPLFree: this is needed because OpenCL C++ API m...