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 );
81 return processRasterCPU( feedback );
90 nCellsX = GDALGetRasterXSize( inputDataset.get() );
91 nCellsY = GDALGetRasterYSize( inputDataset.get() );
94 if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
102 GDALDriverH QgsNineCellFilter::openOutputDriver()
105 GDALDriverH outputDriver = GDALGetDriverByName(
mOutputFormat.toLocal8Bit().data() );
128 int xSize = GDALGetRasterXSize( inputDataset );
129 int ySize = GDALGetRasterYSize( inputDataset );
132 char **papszOptions =
nullptr;
134 if ( !outputDataset )
136 return outputDataset;
140 double geotransform[6];
141 if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
145 GDALSetGeoTransform( outputDataset.get(), geotransform );
149 if ( mCellSizeX < 0 )
159 const char *projection = GDALGetProjectionRef( inputDataset );
160 GDALSetProjection( outputDataset.get(), projection );
162 return outputDataset;
168 int QgsNineCellFilter::processRasterGPU(
const QString &source,
QgsFeedback *feedback )
182 GDALDriverH outputDriver = openOutputDriver();
189 if ( !outputDataset )
195 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
202 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
203 if ( !outputRasterBand )
208 GDALSetRasterNoDataValue( outputRasterBand, -9999 );
225 std::vector<float> rasterParams;
235 addExtraRasterParams( rasterParams );
237 std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
238 std::size_t inputSize(
sizeof(
float ) * ( xSize ) );
240 cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(),
true,
false, nullptr );
241 cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
242 cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
243 cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
244 cl::Buffer *scanLineBuffer[3] = {&scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer};
245 cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize,
nullptr,
nullptr );
251 auto kernel = cl::KernelFunctor <
257 > ( program,
"processNineCellWindow" );
260 std::vector<int> rowIndex = {0, 1, 2};
263 for (
int i = 0; i < ySize; ++i )
272 feedback->
setProgress( 100.0 * static_cast< double >( i ) / ySize );
279 for (
int a = 0; a < xSize + 2 ; ++a )
283 queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.
get() );
286 if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
288 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
290 queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.
get() );
293 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
295 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
297 queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.
get() );
303 if ( i == ySize - 1 )
305 for (
int a = 0; a < xSize + 2; ++a )
309 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.
get() );
314 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
316 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
318 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.
get() );
322 kernel( cl::EnqueueArgs(
326 *scanLineBuffer[rowIndex[0]],
327 *scanLineBuffer[rowIndex[1]],
328 *scanLineBuffer[rowIndex[2]],
333 queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.
get() );
335 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.
get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
337 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
339 std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
354 int QgsNineCellFilter::processRasterCPU(
QgsFeedback *feedback )
368 GDALDriverH outputDriver = openOutputDriver();
375 if ( !outputDataset )
381 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
388 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
389 if ( !outputRasterBand )
394 GDALSetRasterNoDataValue( outputRasterBand, -9999 );
403 std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
404 float *scanLine1 = (
float * ) CPLMalloc( bufferSize );
405 float *scanLine2 = (
float * ) CPLMalloc( bufferSize );
406 float *scanLine3 = (
float * ) CPLMalloc( bufferSize );
408 float *resultLine = (
float * ) CPLMalloc(
sizeof(
float ) * xSize );
411 for (
int yIndex = 0; yIndex < ySize; ++yIndex )
420 feedback->
setProgress( 100.0 * static_cast< double >( yIndex ) / ySize );
426 for (
int a = 0; a < xSize + 2 ; ++a )
431 if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
433 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
439 CPLFree( scanLine1 );
440 scanLine1 = scanLine2;
441 scanLine2 = scanLine3;
442 scanLine3 = (
float * ) CPLMalloc( bufferSize );
446 if ( yIndex == ySize - 1 )
448 for (
int a = 0; a < xSize + 2; ++a )
455 if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
457 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
468 for (
int xIndex = 0; xIndex < xSize ; ++xIndex )
471 resultLine[ xIndex ] =
processNineCellWindow( &scanLine1[ xIndex ], &scanLine1[ xIndex + 1 ], &scanLine1[ xIndex + 2 ],
472 &scanLine2[ xIndex ], &scanLine2[ xIndex + 1 ], &scanLine2[ xIndex + 2 ],
473 &scanLine3[ xIndex ], &scanLine3[ xIndex + 1 ], &scanLine3[ xIndex + 2 ] );
477 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
479 QgsDebugMsg( QStringLiteral(
"Raster IO Error" ) );
483 CPLFree( resultLine );
484 CPLFree( scanLine1 );
485 CPLFree( scanLine2 );
486 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 cancelation 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.