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 );
@ Critical
Critical/error message.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
bool isCanceled() const
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 ...
@ Throw
Write errors in the message log and re-throw exceptions.
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...