21#include "cpl_string.h"
37 : mInputFile( inputFile )
38 , mOutputFile( outputFile )
39 , mOutputFormat( outputFormat )
50 if ( !source.isEmpty() )
54 QgsDebugMsgLevel( QStringLiteral(
"Running OpenCL program: %1" ).arg( openClProgramBaseName() ), 2 );
55 return processRasterGPU( source, feedback );
57 catch ( cl::Error &e )
59 const QString err = QObject::tr(
"Error running OpenCL program: %1 - %2" ).arg( e.what(),
QgsOpenClUtils::errorText( e.err() ) );
66 const QString err = QObject::tr(
"Error loading OpenCL program sources" );
73 return processRasterCPU( feedback );
79 return processRasterCPU( feedback );
88 nCellsX = GDALGetRasterXSize( inputDataset.get() );
89 nCellsY = GDALGetRasterYSize( inputDataset.get() );
92 if ( GDALGetRasterCount( inputDataset.get() ) < 1 )
100GDALDriverH QgsNineCellFilter::openOutputDriver()
103 GDALDriverH outputDriver = GDALGetDriverByName(
mOutputFormat.toLocal8Bit().data() );
125 const int xSize = GDALGetRasterXSize( inputDataset );
126 const int ySize = GDALGetRasterYSize( inputDataset );
131 CSLDestroy( papszOptions );
132 if ( !outputDataset )
134 return outputDataset;
138 double geotransform[6];
139 if ( GDALGetGeoTransform( inputDataset, geotransform ) != CE_None )
143 GDALSetGeoTransform( outputDataset.get(), geotransform );
157 const char *projection = GDALGetProjectionRef( inputDataset );
158 GDALSetProjection( outputDataset.get(), projection );
160 return outputDataset;
178 GDALDriverH outputDriver = openOutputDriver();
185 if ( !outputDataset )
191 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
198 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
199 if ( !outputRasterBand )
220 std::vector<float> rasterParams;
230 addExtraRasterParams( rasterParams );
232 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
233 const std::size_t inputSize(
sizeof(
float ) * ( xSize ) );
235 cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(),
true,
false,
nullptr );
236 cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
237 cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
238 cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
239 cl::Buffer *scanLineBuffer[3] = { &scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer };
240 cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize,
nullptr,
nullptr );
246 auto kernel = cl::KernelFunctor<
251 cl::Buffer &>( program,
"processNineCellWindow" );
254 std::vector<int> rowIndex = { 0, 1, 2 };
257 for (
int i = 0; i < ySize; ++i )
266 feedback->
setProgress( 100.0 *
static_cast<double>( i ) / ySize );
273 for (
int a = 0; a < xSize + 2; ++a )
277 queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
280 if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
284 queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
287 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
291 queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
297 if ( i == ySize - 1 )
299 for (
int a = 0; a < xSize + 2; ++a )
303 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
308 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
312 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
316 kernel( cl::EnqueueArgs( queue, cl::NDRange( xSize ) ), *scanLineBuffer[rowIndex[0]], *scanLineBuffer[rowIndex[1]], *scanLineBuffer[rowIndex[2]], resultLineBuffer, rasterParamsBuffer );
318 queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
320 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
324 std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
351 GDALDriverH outputDriver = openOutputDriver();
358 if ( !outputDataset )
364 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
371 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
372 if ( !outputRasterBand )
385 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
386 float *scanLine1 = (
float * ) CPLMalloc( bufferSize );
387 float *scanLine2 = (
float * ) CPLMalloc( bufferSize );
388 float *scanLine3 = (
float * ) CPLMalloc( bufferSize );
390 float *resultLine = (
float * ) CPLMalloc(
sizeof(
float ) * xSize );
393 for (
int yIndex = 0; yIndex < ySize; ++yIndex )
402 feedback->
setProgress( 100.0 *
static_cast<double>( yIndex ) / ySize );
408 for (
int a = 0; a < xSize + 2; ++a )
413 if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
421 CPLFree( scanLine1 );
422 scanLine1 = scanLine2;
423 scanLine2 = scanLine3;
424 scanLine3 = (
float * ) CPLMalloc( bufferSize );
428 if ( yIndex == ySize - 1 )
430 for (
int a = 0; a < xSize + 2; ++a )
437 if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
449 for (
int xIndex = 0; xIndex < xSize; ++xIndex )
452 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] );
455 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
461 CPLFree( resultLine );
462 CPLFree( scanLine1 );
463 CPLFree( scanLine2 );
464 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).
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.
Result
Result of the calculation.
@ Canceled
User canceled calculation.
@ InputLayerError
Error reading input file.
@ RasterSizeError
Raster height is too small (need at least 3 rows)
@ Success
Operation completed successfully.
@ CreateOutputError
Error creating output file.
@ DriverError
Could not open the driver for the specified format.
@ InputBandError
Error reading input raster band.
@ OutputBandError
Error reading output raster band.
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.
Result processRaster(QgsFeedback *feedback=nullptr)
Starts the calculation, reads from mInputFile and stores the result in mOutputFile.
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...