21#include "cpl_string.h"
37 : mInputFile( inputFile )
38 , mOutputFile( outputFile )
39 , mOutputFormat( outputFormat )
51 if ( !source.isEmpty() )
55 QgsDebugMsgLevel( QStringLiteral(
"Running OpenCL program: %1" ).arg( openClProgramBaseName() ), 2 );
56 return processRasterGPU( source, feedback );
58 catch ( cl::Error &e )
60 const QString err = QObject::tr(
"Error running OpenCL program: %1 - %2" ).arg( e.what(),
QgsOpenClUtils::errorText( e.err() ) );
67 const QString err = QObject::tr(
"Error loading OpenCL program sources" );
74 return processRasterCPU( feedback );
80 return processRasterCPU( feedback );
89 nCellsX = GDALGetRasterXSize( inputDataset.get() );
90 nCellsY = GDALGetRasterYSize( inputDataset.get() );
93 if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
101GDALDriverH QgsNineCellFilter::openOutputDriver()
104 GDALDriverH outputDriver = GDALGetDriverByName(
mOutputFormat.toLocal8Bit().data() );
127 const int xSize = GDALGetRasterXSize( inputDataset );
128 const int ySize = GDALGetRasterYSize( inputDataset );
133 CSLDestroy( papszOptions );
134 if ( !outputDataset )
136 return outputDataset;
140 double geotransform[6];
141 if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
145 GDALSetGeoTransform( outputDataset.get(), geotransform );
159 const char *projection = GDALGetProjectionRef( inputDataset );
160 GDALSetProjection( outputDataset.get(), projection );
162 return outputDataset;
168int QgsNineCellFilter::processRasterGPU(
const QString &source,
QgsFeedback *feedback )
181 GDALDriverH outputDriver = openOutputDriver();
188 if ( !outputDataset )
194 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
201 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
202 if ( !outputRasterBand )
223 std::vector<float> rasterParams;
233 addExtraRasterParams( rasterParams );
235 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
236 const std::size_t inputSize(
sizeof(
float ) * ( xSize ) );
238 cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(),
true,
false,
nullptr );
239 cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
240 cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
241 cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
242 cl::Buffer *scanLineBuffer[3] = { &scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer };
243 cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize,
nullptr,
nullptr );
249 auto kernel = cl::KernelFunctor<
254 cl::Buffer &>( program,
"processNineCellWindow" );
257 std::vector<int> rowIndex = { 0, 1, 2 };
260 for (
int i = 0; i < ySize; ++i )
269 feedback->
setProgress( 100.0 *
static_cast<double>( i ) / ySize );
276 for (
int a = 0; a < xSize + 2; ++a )
280 queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
283 if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
287 queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
290 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
294 queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
300 if ( i == ySize - 1 )
302 for (
int a = 0; a < xSize + 2; ++a )
306 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
311 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
315 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
319 kernel( cl::EnqueueArgs( queue, cl::NDRange( xSize ) ), *scanLineBuffer[rowIndex[0]], *scanLineBuffer[rowIndex[1]], *scanLineBuffer[rowIndex[2]], resultLineBuffer, rasterParamsBuffer );
321 queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
323 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
327 std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
342int QgsNineCellFilter::processRasterCPU(
QgsFeedback *feedback )
355 GDALDriverH outputDriver = openOutputDriver();
362 if ( !outputDataset )
368 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
375 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
376 if ( !outputRasterBand )
389 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
390 float *scanLine1 = (
float * ) CPLMalloc( bufferSize );
391 float *scanLine2 = (
float * ) CPLMalloc( bufferSize );
392 float *scanLine3 = (
float * ) CPLMalloc( bufferSize );
394 float *resultLine = (
float * ) CPLMalloc(
sizeof(
float ) * xSize );
397 for (
int yIndex = 0; yIndex < ySize; ++yIndex )
406 feedback->
setProgress( 100.0 *
static_cast<double>( yIndex ) / ySize );
412 for (
int a = 0; a < xSize + 2; ++a )
417 if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
425 CPLFree( scanLine1 );
426 scanLine1 = scanLine2;
427 scanLine2 = scanLine3;
428 scanLine3 = (
float * ) CPLMalloc( bufferSize );
432 if ( yIndex == ySize - 1 )
434 for (
int a = 0; a < xSize + 2; ++a )
441 if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
453 for (
int xIndex = 0; xIndex < xSize; ++xIndex )
456 resultLine[xIndex] =
processNineCellWindow( &scanLine1[xIndex], &scanLine1[xIndex + 1], &scanLine1[xIndex + 2], &scanLine2[xIndex], &scanLine2[xIndex + 1], &scanLine2[xIndex + 2], &scanLine3[xIndex], &scanLine3[xIndex + 1], &scanLine3[xIndex + 2] );
459 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
465 CPLFree( resultLine );
466 CPLFree( scanLine1 );
467 CPLFree( scanLine2 );
468 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 char ** papszFromStringList(const QStringList &list)
Helper function.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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.
QStringList mCreationOptions
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)
double mOutputNodataValue
The nodata value of the output layer.
double mInputNodataValue
The nodata value of the input 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...