21#include <cpl_string.h>
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() );
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;
180 GDALDriverH outputDriver = openOutputDriver();
187 if ( !outputDataset )
193 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
200 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
201 if ( !outputRasterBand )
218 QgsOpenClUtils::CPLAllocator<float> scanLine( xSize + 2 );
219 QgsOpenClUtils::CPLAllocator<float> resultLine( xSize );
222 std::vector<float> rasterParams;
232 addExtraRasterParams( rasterParams );
234 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
235 const std::size_t inputSize(
sizeof(
float ) * ( xSize ) );
237 cl::Buffer rasterParamsBuffer( queue, rasterParams.begin(), rasterParams.end(),
true,
false,
nullptr );
238 cl::Buffer scanLine1Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
239 cl::Buffer scanLine2Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
240 cl::Buffer scanLine3Buffer( ctx, CL_MEM_READ_ONLY, bufferSize,
nullptr,
nullptr );
241 cl::Buffer *scanLineBuffer[3] = { &scanLine1Buffer, &scanLine2Buffer, &scanLine3Buffer };
242 cl::Buffer resultLineBuffer( ctx, CL_MEM_WRITE_ONLY, inputSize,
nullptr,
nullptr );
248 auto kernel = cl::KernelFunctor<
253 cl::Buffer &>( program,
"processNineCellWindow" );
256 std::vector<int> rowIndex = { 0, 1, 2 };
259 for (
int i = 0; i < ySize; ++i )
268 feedback->
setProgress( 100.0 *
static_cast<double>( i ) / ySize );
275 for (
int a = 0; a < xSize + 2; ++a )
279 queue.enqueueWriteBuffer( scanLine1Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
282 if ( GDALRasterIO( rasterBand, GF_Read, 0, i, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
286 queue.enqueueWriteBuffer( scanLine2Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
289 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
293 queue.enqueueWriteBuffer( scanLine3Buffer, CL_TRUE, 0, bufferSize, scanLine.get() );
299 if ( i == ySize - 1 )
301 for (
int a = 0; a < xSize + 2; ++a )
305 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
310 if ( GDALRasterIO( rasterBand, GF_Read, 0, i + 1, xSize, 1, &scanLine[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
314 queue.enqueueWriteBuffer( *scanLineBuffer[rowIndex[2]], CL_TRUE, 0, bufferSize, scanLine.get() );
318 kernel( cl::EnqueueArgs( queue, cl::NDRange( xSize ) ), *scanLineBuffer[rowIndex[0]], *scanLineBuffer[rowIndex[1]], *scanLineBuffer[rowIndex[2]], resultLineBuffer, rasterParamsBuffer );
320 queue.enqueueReadBuffer( resultLineBuffer, CL_TRUE, 0, inputSize, resultLine.get() );
322 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, i, xSize, 1, resultLine.get(), xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
326 std::rotate( rowIndex.begin(), rowIndex.begin() + 1, rowIndex.end() );
353 GDALDriverH outputDriver = openOutputDriver();
360 if ( !outputDataset )
366 GDALRasterBandH rasterBand = GDALGetRasterBand( inputDataset.get(), 1 );
373 GDALRasterBandH outputRasterBand = GDALGetRasterBand( outputDataset.get(), 1 );
374 if ( !outputRasterBand )
387 const std::size_t bufferSize(
sizeof(
float ) * ( xSize + 2 ) );
388 float *scanLine1 = (
float * ) CPLMalloc( bufferSize );
389 float *scanLine2 = (
float * ) CPLMalloc( bufferSize );
390 float *scanLine3 = (
float * ) CPLMalloc( bufferSize );
392 float *resultLine = (
float * ) CPLMalloc(
sizeof(
float ) * xSize );
395 for (
int yIndex = 0; yIndex < ySize; ++yIndex )
404 feedback->
setProgress( 100.0 *
static_cast<double>( yIndex ) / ySize );
410 for (
int a = 0; a < xSize + 2; ++a )
415 if ( GDALRasterIO( rasterBand, GF_Read, 0, 0, xSize, 1, &scanLine2[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
423 CPLFree( scanLine1 );
424 scanLine1 = scanLine2;
425 scanLine2 = scanLine3;
426 scanLine3 = (
float * ) CPLMalloc( bufferSize );
430 if ( yIndex == ySize - 1 )
432 for (
int a = 0; a < xSize + 2; ++a )
439 if ( GDALRasterIO( rasterBand, GF_Read, 0, yIndex + 1, xSize, 1, &scanLine3[1], xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
451 for (
int xIndex = 0; xIndex < xSize; ++xIndex )
454 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] );
457 if ( GDALRasterIO( outputRasterBand, GF_Write, 0, yIndex, xSize, 1, resultLine, xSize, 1, GDT_Float32, 0, 0 ) != CE_None )
463 CPLFree( resultLine );
464 CPLFree( scanLine1 );
465 CPLFree( scanLine2 );
466 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)