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 );
151 if ( mCellSizeX < 0 )
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 );
Tiny smart-pointer-like wrapper around CPLMalloc and CPLFree: this is needed because OpenCL C++ API m...
static QString sourceFromBaseName(const QString &baseName)
Returns the full path to a an OpenCL source file from the baseName ('.cl' extension is automatically ...
void setProgress(double progress)
Sets the current progress for the feedback object.
static bool available()
Checks whether a suitable OpenCL platform and device is available on this system and initialize the Q...
int processRaster(QgsFeedback *feedback=nullptr)
Starts the calculation, reads from mInputFile and stores the result in mOutputFile.
static bool supportsRasterCreate(GDALDriverH driver)
Reads whether a driver supports GDALCreate() for raster purposes.
static cl::Context context()
Context factory.
Base class for feedback objects to be used for cancellation of something running in a worker thread...
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.
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...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
static bool enabled()
Returns true if OpenCL is enabled in the user settings.
Custom exception class for processing related exceptions.
static QString errorText(const int errorCode)
Returns a string representation from an OpenCL errorCode.
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...
float mOutputNodataValue
The nodata value of the output layer.
bool isCanceled() const
Tells whether the operation has been canceled already.
static QLatin1String LOGMESSAGE_TAG
OpenCL string for message logs.
QgsNineCellFilter(const QString &inputFile, const QString &outputFile, const QString &outputFormat)
Constructor that takes input file, output file and output format (GDAL string)
double mZFactor
Scale factor for z-value if x-/y- units are different to z-units (111120 for degree->meters and 37040...
float mInputNodataValue
The nodata value of the input layer.
std::unique_ptr< std::remove_pointer< GDALDatasetH >::type, GDALDatasetCloser > dataset_unique_ptr
Scoped GDAL dataset.
static cl::CommandQueue commandQueue()
Create an OpenCL command queue from the default context.