QGIS API Documentation  2.18.3-Las Palmas (77b8c3d)
qgsalignraster.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalignraster.cpp
3  --------------------------------------
4  Date : June 2015
5  Copyright : (C) 2015 by Martin Dobias
6  Email : wonder dot sk at gmail dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsalignraster.h"
17 
18 #include <gdalwarper.h>
19 #include <ogr_spatialref.h>
20 #include <cpl_conv.h>
21 #include <limits>
22 
23 #include <qmath.h>
24 #include <QPair>
25 #include <QString>
26 
28 #include "qgsrectangle.h"
29 
30 
31 static double ceil_with_tolerance( double value )
32 {
33  if ( qAbs( value - qRound( value ) ) < 1e-6 )
34  return qRound( value );
35  else
36  return qCeil( value );
37 }
38 
39 static double floor_with_tolerance( double value )
40 {
41  if ( qAbs( value - qRound( value ) ) < 1e-6 )
42  return qRound( value );
43  else
44  return qFloor( value );
45 }
46 
47 static double fmod_with_tolerance( double num, double denom )
48 {
49  return num - floor_with_tolerance( num / denom ) * denom;
50 }
51 
52 
53 static QgsRectangle transform_to_extent( const double* geotransform, double xSize, double ySize )
54 {
55  QgsRectangle r( geotransform[0],
56  geotransform[3],
57  geotransform[0] + geotransform[1] * xSize,
58  geotransform[3] + geotransform[5] * ySize );
59  r.normalize();
60  return r;
61 }
62 
63 
64 static int CPL_STDCALL _progress( double dfComplete, const char* pszMessage, void* pProgressArg )
65 {
66  Q_UNUSED( pszMessage );
67 
68  QgsAlignRaster::ProgressHandler* handler = (( QgsAlignRaster* ) pProgressArg )->progressHandler();
69  if ( handler )
70  return handler->progress( dfComplete );
71  else
72  return true;
73 }
74 
75 
76 static CPLErr rescalePreWarpChunkProcessor( void* pKern, void* pArg )
77 {
78  GDALWarpKernel* kern = ( GDALWarpKernel* ) pKern;
79  double cellsize = (( double* )pArg )[0];
80 
81  for ( int nBand = 0; nBand < kern->nBands; ++nBand )
82  {
83  float* bandData = ( float * ) kern->papabySrcImage[nBand];
84  for ( int nLine = 0; nLine < kern->nSrcYSize; ++nLine )
85  {
86  for ( int nPixel = 0; nPixel < kern->nSrcXSize; ++nPixel )
87  {
88  bandData[nPixel] /= cellsize;
89  }
90  bandData += kern->nSrcXSize;
91  }
92  }
93  return CE_None;
94 }
95 
96 
97 static CPLErr rescalePostWarpChunkProcessor( void* pKern, void* pArg )
98 {
99  GDALWarpKernel* kern = ( GDALWarpKernel* ) pKern;
100  double cellsize = (( double* )pArg )[1];
101 
102  for ( int nBand = 0; nBand < kern->nBands; ++nBand )
103  {
104  float* bandData = ( float * ) kern->papabyDstImage[nBand];
105  for ( int nLine = 0; nLine < kern->nDstYSize; ++nLine )
106  {
107  for ( int nPixel = 0; nPixel < kern->nDstXSize; ++nPixel )
108  {
109  bandData[nPixel] *= cellsize;
110  }
111  bandData += kern->nDstXSize;
112  }
113  }
114  return CE_None;
115 }
116 
117 
118 
120  : mProgressHandler( nullptr )
121 {
122  // parameters
123  mCellSizeX = mCellSizeY = 0;
125  mClipExtent[0] = mClipExtent[1] = mClipExtent[2] = mClipExtent[3] = 0;
126 
127  // derived variables
128  mXSize = mYSize = 0;
129  for ( int i = 0; i < 6; ++i )
130  mGeoTransform[i] = 0;
131 }
132 
133 void QgsAlignRaster::setClipExtent( double xmin, double ymin, double xmax, double ymax )
134 {
135  mClipExtent[0] = xmin;
136  mClipExtent[1] = ymin;
137  mClipExtent[2] = xmax;
138  mClipExtent[3] = ymax;
139 }
140 
142 {
143  setClipExtent( extent.xMinimum(), extent.yMinimum(),
144  extent.xMaximum(), extent.yMaximum() );
145 }
146 
148 {
149  return QgsRectangle( mClipExtent[0], mClipExtent[1],
150  mClipExtent[2], mClipExtent[3] );
151 }
152 
153 
154 bool QgsAlignRaster::setParametersFromRaster( const QString& filename, const QString& destWkt, QSizeF customCellSize, QPointF customGridOffset )
155 {
156  return setParametersFromRaster( RasterInfo( filename ), destWkt, customCellSize, customGridOffset );
157 }
158 
159 bool QgsAlignRaster::setParametersFromRaster( const RasterInfo& rasterInfo, const QString& customCRSWkt, QSizeF customCellSize, QPointF customGridOffset )
160 {
161  if ( customCRSWkt.isEmpty() || customCRSWkt == rasterInfo.crs() )
162  {
163  // use ref. layer to init input
164  mCrsWkt = rasterInfo.crs();
165 
166  if ( !customCellSize.isValid() )
167  {
168  mCellSizeX = rasterInfo.cellSize().width();
169  mCellSizeY = rasterInfo.cellSize().height();
170  }
171  else
172  {
173  mCellSizeX = customCellSize.width();
174  mCellSizeY = customCellSize.height();
175  }
176 
177  if ( customGridOffset.x() < 0 || customGridOffset.y() < 0 )
178  {
179  if ( !customCellSize.isValid() )
180  {
181  // using original raster's grid offset to be aligned with origin
182  mGridOffsetX = rasterInfo.gridOffset().x();
183  mGridOffsetY = rasterInfo.gridOffset().y();
184  }
185  else
186  {
187  // if using custom cell size: offset so that we are aligned
188  // with the original raster's origin point
189  mGridOffsetX = fmod_with_tolerance( rasterInfo.origin().x(), customCellSize.width() );
190  mGridOffsetY = fmod_with_tolerance( rasterInfo.origin().y(), customCellSize.height() );
191  }
192  }
193  else
194  {
195  mGridOffsetX = customGridOffset.x();
196  mGridOffsetY = customGridOffset.y();
197  }
198  }
199  else
200  {
201  QSizeF cs;
202  QPointF go;
203  if ( !suggestedWarpOutput( rasterInfo, customCRSWkt, &cs, &go ) )
204  {
205  mCrsWkt = "_error_";
206  mCellSizeX = mCellSizeY = 0;
208  return false;
209  }
210 
211  mCrsWkt = customCRSWkt;
212 
213  if ( !customCellSize.isValid() )
214  {
215  mCellSizeX = cs.width();
216  mCellSizeY = cs.height();
217  }
218  else
219  {
220  mCellSizeX = customCellSize.width();
221  mCellSizeY = customCellSize.height();
222  }
223 
224  if ( customGridOffset.x() < 0 || customGridOffset.y() < 0 )
225  {
226  mGridOffsetX = go.x();
227  mGridOffsetY = go.y();
228  }
229  else
230  {
231  mGridOffsetX = customGridOffset.x();
232  mGridOffsetY = customGridOffset.x();
233  }
234  }
235  return true;
236 }
237 
238 
240 {
242 
243  if ( mCrsWkt == "_error_" )
244  {
245  mErrorMessage = QObject::tr( "Unable to reproject." );
246  return false;
247  }
248 
249  if ( mCellSizeX == 0 || mCellSizeY == 0 )
250  {
251  mErrorMessage = QObject::tr( "Cell size must not be zero." );
252  return false;
253  }
254 
255  mXSize = mYSize = 0;
256  std::fill_n( mGeoTransform, 6, 0 );
257 
258  double finalExtent[4] = { 0, 0, 0, 0 };
259 
260  // for each raster: determine their extent in projected cfg
261  for ( int i = 0; i < mRasters.count(); ++i )
262  {
263  Item& r = mRasters[i];
264 
265  RasterInfo info( r.inputFilename );
266 
267  QSizeF cs;
268  QgsRectangle extent;
269  if ( !suggestedWarpOutput( info, mCrsWkt, &cs, nullptr, &extent ) )
270  {
271  mErrorMessage = QString( "Failed to get suggested warp output.\n\n"
272  "File:\n%1\n\n"
273  "Source WKT:\n%2\n\nDestination WKT:\n%3" )
274  .arg( r.inputFilename,
275  info.mCrsWkt,
276  mCrsWkt );
277  return false;
278  }
279 
280  r.srcCellSizeInDestCRS = cs.width() * cs.height();
281 
282  if ( finalExtent[0] == 0 && finalExtent[1] == 0 && finalExtent[2] == 0 && finalExtent[3] == 0 )
283  {
284  // initialize with the first layer
285  finalExtent[0] = extent.xMinimum();
286  finalExtent[1] = extent.yMinimum();
287  finalExtent[2] = extent.xMaximum();
288  finalExtent[3] = extent.yMaximum();
289  }
290  else
291  {
292  // use intersection of rects
293  if ( extent.xMinimum() > finalExtent[0] ) finalExtent[0] = extent.xMinimum();
294  if ( extent.yMinimum() > finalExtent[1] ) finalExtent[1] = extent.yMinimum();
295  if ( extent.xMaximum() < finalExtent[2] ) finalExtent[2] = extent.xMaximum();
296  if ( extent.yMaximum() < finalExtent[3] ) finalExtent[3] = extent.yMaximum();
297  }
298  }
299 
300  // count in extra clip extent (if present)
301  // 1. align requested rect to the grid - extend the rect if necessary
302  // 2. intersect with clip extent with final extent
303 
304  if ( !( mClipExtent[0] == 0 && mClipExtent[1] == 0 && mClipExtent[2] == 0 && mClipExtent[3] == 0 ) )
305  {
306  // extend clip extent to grid
309  double clipX1 = ceil_with_tolerance(( mClipExtent[2] - clipX0 ) / mCellSizeX ) * mCellSizeX + clipX0;
310  double clipY1 = ceil_with_tolerance(( mClipExtent[3] - clipY0 ) / mCellSizeY ) * mCellSizeY + clipY0;
311  if ( clipX0 > finalExtent[0] ) finalExtent[0] = clipX0;
312  if ( clipY0 > finalExtent[1] ) finalExtent[1] = clipY0;
313  if ( clipX1 < finalExtent[2] ) finalExtent[2] = clipX1;
314  if ( clipY1 < finalExtent[3] ) finalExtent[3] = clipY1;
315  }
316 
317  // align to grid - shrink the rect if necessary
318  // output raster grid configuration (with no rotation/shear)
319  // ... and raster width/height
320 
321  double originX = ceil_with_tolerance(( finalExtent[0] - mGridOffsetX ) / mCellSizeX ) * mCellSizeX + mGridOffsetX;
322  double originY = ceil_with_tolerance(( finalExtent[1] - mGridOffsetY ) / mCellSizeY ) * mCellSizeY + mGridOffsetY;
323  int xSize = floor_with_tolerance(( finalExtent[2] - originX ) / mCellSizeX );
324  int ySize = floor_with_tolerance(( finalExtent[3] - originY ) / mCellSizeY );
325 
326  if ( xSize <= 0 || ySize <= 0 )
327  {
328  mErrorMessage = QObject::tr( "No common intersecting area." );
329  return false;
330  }
331 
332  mXSize = xSize;
333  mYSize = ySize;
334 
335  // build final geotransform...
336  mGeoTransform[0] = originX;
338  mGeoTransform[2] = 0;
339  mGeoTransform[3] = originY + ( mCellSizeY * ySize );
340  mGeoTransform[4] = 0;
341  mGeoTransform[5] = -mCellSizeY;
342 
343  return true;
344 }
345 
346 
348 {
349  return QSize( mXSize, mYSize );
350 }
351 
353 {
355 }
356 
357 
359 {
361 
362  // consider extent of all layers and setup geotransform and output grid size
363  if ( !checkInputParameters() )
364  return false;
365 
366  //dump();
367 
368  Q_FOREACH ( const Item& r, mRasters )
369  {
370  if ( !createAndWarp( r ) )
371  return false;
372  }
373  return true;
374 }
375 
376 
378 {
379  qDebug( "---ALIGN------------------" );
380  qDebug( "wkt %s", mCrsWkt.toAscii().constData() );
381  qDebug( "w/h %d,%d", mXSize, mYSize );
382  qDebug( "transform" );
383  qDebug( "%6.2f %6.2f %6.2f", mGeoTransform[0], mGeoTransform[1], mGeoTransform[2] );
384  qDebug( "%6.2f %6.2f %6.2f", mGeoTransform[3], mGeoTransform[4], mGeoTransform[5] );
385 
387  qDebug( "extent %s", e.toString().toAscii().constData() );
388 }
389 
391 {
392  int bestIndex = -1;
393  double bestCellArea = qInf();
394  QSizeF cs;
395  int i = 0;
396 
397  // using WGS84 as a destination CRS... but maybe some projected CRS
398  // would be a better a choice to more accurately compute areas?
399  // (Why earth is not flat???)
400  QgsCoordinateReferenceSystem destCRS( "EPSG:4326" );
401  QString destWkt = destCRS.toWkt();
402 
403  Q_FOREACH ( const Item& raster, mRasters )
404  {
405  if ( !suggestedWarpOutput( RasterInfo( raster.inputFilename ), destWkt, &cs ) )
406  return false;
407 
408  double cellArea = cs.width() * cs.height();
409  if ( cellArea < bestCellArea )
410  {
411  bestCellArea = cellArea;
412  bestIndex = i;
413  }
414  ++i;
415  }
416 
417  return bestIndex;
418 }
419 
420 
421 bool QgsAlignRaster::createAndWarp( const Item& raster )
422 {
423  GDALDriverH hDriver = GDALGetDriverByName( "GTiff" );
424  if ( !hDriver )
425  {
426  mErrorMessage = QString( "GDALGetDriverByName(GTiff) failed." );
427  return false;
428  }
429 
430  // Open the source file.
431  GDALDatasetH hSrcDS = GDALOpen( raster.inputFilename.toLocal8Bit().constData(), GA_ReadOnly );
432  if ( !hSrcDS )
433  {
434  mErrorMessage = QObject::tr( "Unable to open input file: %1" ).arg( raster.inputFilename );
435  return false;
436  }
437 
438  // Create output with same datatype as first input band.
439 
440  int bandCount = GDALGetRasterCount( hSrcDS );
441  GDALDataType eDT = GDALGetRasterDataType( GDALGetRasterBand( hSrcDS, 1 ) );
442 
443  // Create the output file.
444  GDALDatasetH hDstDS;
445  hDstDS = GDALCreate( hDriver, raster.outputFilename.toLocal8Bit().constData(), mXSize, mYSize,
446  bandCount, eDT, nullptr );
447  if ( !hDstDS )
448  {
449  GDALClose( hSrcDS );
450  mErrorMessage = QObject::tr( "Unable to create output file: %1" ).arg( raster.outputFilename );
451  return false;
452  }
453 
454  // Write out the projection definition.
455  GDALSetProjection( hDstDS, mCrsWkt.toAscii().constData() );
456  GDALSetGeoTransform( hDstDS, mGeoTransform );
457 
458  // Copy the color table, if required.
459  GDALColorTableH hCT = GDALGetRasterColorTable( GDALGetRasterBand( hSrcDS, 1 ) );
460  if ( hCT )
461  GDALSetRasterColorTable( GDALGetRasterBand( hDstDS, 1 ), hCT );
462 
463  // -----------------------------------------------------------------------
464 
465  // Setup warp options.
466  GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
467  psWarpOptions->hSrcDS = hSrcDS;
468  psWarpOptions->hDstDS = hDstDS;
469 
470  psWarpOptions->nBandCount = GDALGetRasterCount( hSrcDS );
471  psWarpOptions->panSrcBands = ( int * ) CPLMalloc( sizeof( int ) * psWarpOptions->nBandCount );
472  psWarpOptions->panDstBands = ( int * ) CPLMalloc( sizeof( int ) * psWarpOptions->nBandCount );
473  for ( int i = 0; i < psWarpOptions->nBandCount; ++i )
474  {
475  psWarpOptions->panSrcBands[i] = i + 1;
476  psWarpOptions->panDstBands[i] = i + 1;
477  }
478 
479  psWarpOptions->eResampleAlg = static_cast< GDALResampleAlg >( raster.resampleMethod );
480 
481  // our progress function
482  psWarpOptions->pfnProgress = _progress;
483  psWarpOptions->pProgressArg = this;
484 
485  // Establish reprojection transformer.
486  psWarpOptions->pTransformerArg =
487  GDALCreateGenImgProjTransformer( hSrcDS, GDALGetProjectionRef( hSrcDS ),
488  hDstDS, GDALGetProjectionRef( hDstDS ),
489  FALSE, 0.0, 1 );
490  psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
491 
492  double rescaleArg[2];
493  if ( raster.rescaleValues )
494  {
495  rescaleArg[0] = raster.srcCellSizeInDestCRS; // source cell size
496  rescaleArg[1] = mCellSizeX * mCellSizeY; // destination cell size
497  psWarpOptions->pfnPreWarpChunkProcessor = rescalePreWarpChunkProcessor;
498  psWarpOptions->pfnPostWarpChunkProcessor = rescalePostWarpChunkProcessor;
499  psWarpOptions->pPreWarpProcessorArg = rescaleArg;
500  psWarpOptions->pPostWarpProcessorArg = rescaleArg;
501  // force use of float32 data type as that is what our pre/post-processor uses
502  psWarpOptions->eWorkingDataType = GDT_Float32;
503  }
504 
505  // Initialize and execute the warp operation.
506  GDALWarpOperation oOperation;
507  oOperation.Initialize( psWarpOptions );
508  oOperation.ChunkAndWarpImage( 0, 0, mXSize, mYSize );
509 
510  GDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );
511  GDALDestroyWarpOptions( psWarpOptions );
512 
513  GDALClose( hDstDS );
514  GDALClose( hSrcDS );
515  return true;
516 }
517 
519 {
520  // Create a transformer that maps from source pixel/line coordinates
521  // to destination georeferenced coordinates (not destination
522  // pixel line). We do that by omitting the destination dataset
523  // handle (setting it to nullptr).
524  void* hTransformArg = GDALCreateGenImgProjTransformer( info.mDataset, info.mCrsWkt.toAscii().constData(), nullptr, destWkt.toAscii().constData(), FALSE, 0, 1 );
525  if ( !hTransformArg )
526  return false;
527 
528  // Get approximate output georeferenced bounds and resolution for file.
529  double adfDstGeoTransform[6];
530  double extents[4];
531  int nPixels = 0, nLines = 0;
532  CPLErr eErr;
533  eErr = GDALSuggestedWarpOutput2( info.mDataset,
534  GDALGenImgProjTransform, hTransformArg,
535  adfDstGeoTransform, &nPixels, &nLines, extents, 0 );
536  GDALDestroyGenImgProjTransformer( hTransformArg );
537 
538  if ( eErr != CE_None )
539  return false;
540 
541  QSizeF cs( qAbs( adfDstGeoTransform[1] ), qAbs( adfDstGeoTransform[5] ) );
542 
543  if ( rect )
544  *rect = QgsRectangle( extents[0], extents[1], extents[2], extents[3] );
545  if ( cellSize )
546  *cellSize = cs;
547  if ( gridOffset )
548  *gridOffset = QPointF( fmod_with_tolerance( adfDstGeoTransform[0], cs.width() ),
549  fmod_with_tolerance( adfDstGeoTransform[3], cs.height() ) );
550  return true;
551 }
552 
553 
554 //----------
555 
556 
558  : mXSize( 0 )
559  , mYSize( 0 )
560  , mBandCnt( 0 )
561 {
562  mDataset = GDALOpen( layerpath.toLocal8Bit().constData(), GA_ReadOnly );
563  if ( !mDataset )
564  return;
565 
566  mXSize = GDALGetRasterXSize( mDataset );
567  mYSize = GDALGetRasterYSize( mDataset );
568 
569  ( void ) GDALGetGeoTransform( mDataset, mGeoTransform );
570 
571  // TODO: may be null or empty string
572  mCrsWkt = QString::fromAscii( GDALGetProjectionRef( mDataset ) );
573 
574  mBandCnt = GDALGetBandNumber( mDataset );
575 }
576 
578 {
579  if ( mDataset )
580  GDALClose( mDataset );
581 }
582 
584 {
585  return QSizeF( qAbs( mGeoTransform[1] ), qAbs( mGeoTransform[5] ) );
586 }
587 
589 {
590  return QPointF( fmod_with_tolerance( mGeoTransform[0], cellSize().width() ),
591  fmod_with_tolerance( mGeoTransform[3], cellSize().height() ) );
592 }
593 
595 {
597 }
598 
600 {
601  return QPointF( mGeoTransform[0], mGeoTransform[3] );
602 }
603 
605 {
606  qDebug( "---RASTER INFO------------------" );
607  qDebug( "wkt %s", mCrsWkt.toAscii().constData() );
608  qDebug( "w/h %d,%d", mXSize, mYSize );
609  qDebug( "cell x/y %f,%f", cellSize().width(), cellSize().width() );
610 
611  QgsRectangle r = extent();
612  qDebug( "extent %s", r.toString().toAscii().constData() );
613 
614  qDebug( "transform" );
615  qDebug( "%6.2f %6.2f %6.2f", mGeoTransform[0], mGeoTransform[1], mGeoTransform[2] );
616  qDebug( "%6.2f %6.2f %6.2f", mGeoTransform[3], mGeoTransform[4], mGeoTransform[5] );
617 }
618 
619 double QgsAlignRaster::RasterInfo::identify( double mx, double my )
620 {
621  GDALRasterBandH hBand = GDALGetRasterBand( mDataset, 1 );
622 
623  // must not be rotated in order for this to work
624  int px = int(( mx - mGeoTransform[0] ) / mGeoTransform[1] );
625  int py = int(( my - mGeoTransform[3] ) / mGeoTransform[5] );
626 
627  float* pafScanline = ( float * ) CPLMalloc( sizeof( float ) );
628  CPLErr err = GDALRasterIO( hBand, GF_Read, px, py, 1, 1,
629  pafScanline, 1, 1, GDT_Float32, 0, 0 );
630  double value = err == CE_None ? pafScanline[0] : std::numeric_limits<double>::quiet_NaN();
631  CPLFree( pafScanline );
632 
633  return value;
634 }
QString fromAscii(const char *str, int size)
A rectangle specified with double values.
Definition: qgsrectangle.h:35
double mCellSizeX
Destination cell size.
int suggestedReferenceLayer() const
Return index of the layer which has smallest cell size (returns -1 on error)
QPointF gridOffset() const
double mGridOffsetX
Destination grid offset - expected to be in interval <0,cellsize)
static bool suggestedWarpOutput(const RasterInfo &info, const QString &destWkt, QSizeF *cellSize=nullptr, QPointF *gridOffset=nullptr, QgsRectangle *rect=nullptr)
Determine suggested output of raster warp to a different CRS. Returns true on success.
QSizeF cellSize() const
Get output cell size.
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:197
bool setParametersFromRaster(const RasterInfo &rasterInfo, const QString &customCRSWkt=QString(), QSizeF customCellSize=QSizeF(), QPointF customGridOffset=QPointF(-1,-1))
Set destination CRS, cell size and grid offset from a raster file.
bool rescaleValues
rescaling of values according to the change of pixel size
double identify(double mx, double my)
Get raster value at the given coordinates (from the first band)
QString toWkt() const
Returns a WKT representation of this CRS.
bool isValid() const
List mRasters
List of rasters to be aligned (with their output files and other options)
QgsRectangle alignedRasterExtent() const
Return expected extent of the resulting aligned raster.
bool run()
Run the alignment process.
static double ceil_with_tolerance(double value)
static double fmod_with_tolerance(double num, double denom)
virtual bool progress(double complete)=0
Method to be overridden for progress reporting.
int mXSize
raster grid size
static CPLErr rescalePreWarpChunkProcessor(void *pKern, void *pArg)
QString tr(const char *sourceText, const char *disambiguation, int n)
QSizeF cellSize() const
Return cell size in map units.
void setClipExtent(double xmin, double ymin, double xmax, double ymax)
Configure clipping extent (region of interest).
QString outputFilename
filename of the newly created aligned raster (will be overwritten if exists already) ...
void clear()
static CPLErr rescalePostWarpChunkProcessor(void *pKern, void *pArg)
int mBandCnt
number of raster&#39;s bands
void dump() const
write contents of the object to standard error stream - for debugging
int count(const T &value) const
qreal x() const
qreal y() const
QgsRectangle clipExtent() const
Get clipping extent (region of interest).
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:202
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:187
QPointF gridOffset() const
Return grid offset.
Definition of one raster layer for alignment.
bool isEmpty() const
bool checkInputParameters()
Determine destination extent from the input rasters and calculate derived values. ...
const char * constData() const
QgsAlignRaster takes one or more raster layers and warps (resamples) them so they have the same: ...
Helper struct to be sub-classed for progress reporting.
double srcCellSizeInDestCRS
used for rescaling of values (if necessary)
static double floor_with_tolerance(double value)
void * GDALDatasetH
QString mCrsWkt
CRS stored in WKT format.
QgsRectangle extent() const
Return extent of the raster.
double mGeoTransform[6]
geotransform coefficients
QByteArray toLocal8Bit() const
int mXSize
Computed raster grid width/height.
void dump() const
write contents of the object to standard error stream - for debugging
QPointF origin() const
Return origin of the raster.
static QgsRectangle transform_to_extent(const double *geotransform, double xSize, double ySize)
double mClipExtent[4]
Optional clip extent: sets "requested area" which be extended to fit the raster grid.
RasterInfo(const QString &layerpath)
Construct raster info with a path to a raster file.
Class for storing a coordinate reference system (CRS)
static int CPL_STDCALL _progress(double dfComplete, const char *pszMessage, void *pProgressArg)
ResampleAlg resampleMethod
resampling method to be used
QSize alignedRasterSize() const
Return expected size of the resulting aligned raster.
QString mErrorMessage
Last error message from run()
QString inputFilename
filename of the source raster
void normalize()
Normalize the rectangle so it has non-negative width/height.
QString crs() const
Return CRS in WKT format.
qreal height() const
double mGeoTransform[6]
Computed geo-transform.
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
GDALDatasetH mDataset
handle to open GDAL dataset
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Utility class for gathering information about rasters.
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:192
QString mCrsWkt
Destination CRS - stored in well-known text (WKT) format.
qreal width() const
QByteArray toAscii() const
bool createAndWarp(const Item &raster)
Internal function for processing of one raster (1. create output, 2. do the alignment) ...