21#include "cpl_string.h"
38 : mInputFile( inputFile )
39 , mOutputFile( outputFile )
40 , mOutputFormat( outputFormat )
52 if ( !source.isEmpty() )
56 QgsDebugMsgLevel( QStringLiteral(
"Running OpenCL program: %1" ).arg( openClProgramBaseName() ), 2 );
57 return processRasterGPU( source, feedback );
59 catch ( cl::Error &e )
61 const QString err = QObject::tr(
"Error running OpenCL program: %1 - %2" ).arg( e.what(),
QgsOpenClUtils::errorText( e.err() ) );
68 const QString err = QObject::tr(
"Error loading OpenCL program sources" );
75 return processRasterCPU( feedback );
81 return processRasterCPU( feedback );
90 nCellsX = GDALGetRasterXSize( inputDataset.get() );
91 nCellsY = GDALGetRasterYSize( inputDataset.get() );
94 if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
102GDALDriverH QgsNineCellFilter::openOutputDriver()
105 GDALDriverH outputDriver = GDALGetDriverByName(
mOutputFormat.toLocal8Bit().data() );
128 const int xSize = GDALGetRasterXSize( inputDataset );
129 const 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 );
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 )
207 GDALSetRasterNoDataValue( outputRasterBand, -9999 );
224 std::vector<float> rasterParams;
234 addExtraRasterParams( rasterParams );
236 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
237 const std::size_t inputSize(
sizeof(
float ) * ( xSize ) );
239 cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(),
true,
false,
nullptr );
240 cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
241 cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
242 cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
243 cl::Buffer *scanLineBuffer[3] = { &scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer };
244 cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize,
nullptr,
nullptr );
250 auto kernel = cl::KernelFunctor<
255 cl::Buffer &>( program,
"processNineCellWindow" );
258 std::vector<int> rowIndex = { 0, 1, 2 };
261 for (
int i = 0; i < ySize; ++i )
270 feedback->
setProgress( 100.0 *
static_cast<double>( i ) / ySize );
277 for (
int a = 0; a < xSize + 2; ++a )
281 queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
284 if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
288 queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
291 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
295 queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
301 if ( i == ySize - 1 )
303 for (
int a = 0; a < xSize + 2; ++a )
307 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
312 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
316 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
320 kernel( cl::EnqueueArgs( queue, cl::NDRange( xSize ) ), *scanLineBuffer[rowIndex[0]], *scanLineBuffer[rowIndex[1]], *scanLineBuffer[rowIndex[2]], resultLineBuffer, rasterParamsBuffer );
322 queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
324 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
328 std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
343int QgsNineCellFilter::processRasterCPU(
QgsFeedback *feedback )
356 GDALDriverH outputDriver = openOutputDriver();
363 if ( !outputDataset )
369 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
376 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
377 if ( !outputRasterBand )
382 GDALSetRasterNoDataValue( outputRasterBand, -9999 );
391 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
392 float *scanLine1 = (
float * ) CPLMalloc( bufferSize );
393 float *scanLine2 = (
float * ) CPLMalloc( bufferSize );
394 float *scanLine3 = (
float * ) CPLMalloc( bufferSize );
396 float *resultLine = (
float * ) CPLMalloc(
sizeof(
float ) * xSize );
399 for (
int yIndex = 0; yIndex < ySize; ++yIndex )
408 feedback->
setProgress( 100.0 *
static_cast<double>( yIndex ) / ySize );
414 for (
int a = 0; a < xSize + 2; ++a )
419 if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
427 CPLFree( scanLine1 );
428 scanLine1 = scanLine2;
429 scanLine2 = scanLine3;
430 scanLine3 = (
float * ) CPLMalloc( bufferSize );
434 if ( yIndex == ySize - 1 )
436 for (
int a = 0; a < xSize + 2; ++a )
443 if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
455 for (
int xIndex = 0; xIndex < xSize; ++xIndex )
458 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] );
461 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
467 CPLFree( resultLine );
468 CPLFree( scanLine1 );
469 CPLFree( scanLine2 );
470 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...