@@ -45,8 +45,24 @@ QgsRasterCalculator::QgsRasterCalculator( const QString& formulaString, const QS
45
45
, mNumOutputRows( nOutputRows )
46
46
, mRasterEntries( rasterEntries )
47
47
{
48
+ // default to first layer's crs
49
+ mOutputCrs = mRasterEntries .at ( 0 ).raster ->crs ();
48
50
}
49
51
52
+ QgsRasterCalculator::QgsRasterCalculator ( const QString& formulaString, const QString& outputFile, const QString& outputFormat,
53
+ const QgsRectangle& outputExtent, const QgsCoordinateReferenceSystem& outputCrs, int nOutputColumns, int nOutputRows, const QVector<QgsRasterCalculatorEntry>& rasterEntries )
54
+ : mFormulaString( formulaString )
55
+ , mOutputFile( outputFile )
56
+ , mOutputFormat( outputFormat )
57
+ , mOutputRectangle( outputExtent )
58
+ , mOutputCrs( outputCrs )
59
+ , mNumOutputColumns( nOutputColumns )
60
+ , mNumOutputRows( nOutputRows )
61
+ , mRasterEntries( rasterEntries )
62
+ {
63
+ }
64
+
65
+
50
66
QgsRasterCalculator::~QgsRasterCalculator ()
51
67
{
52
68
}
@@ -62,56 +78,31 @@ int QgsRasterCalculator::processCalculation( QProgressDialog* p )
62
78
return 4 ;
63
79
}
64
80
65
- double targetGeoTransform[6 ];
66
- outputGeoTransform ( targetGeoTransform );
67
-
68
- // open all input rasters for reading
69
- QMap< QString, GDALRasterBandH > mInputRasterBands ; // raster references and corresponding scanline data
70
- QMap< QString, QgsRasterMatrix* > inputScanLineData; // stores raster references and corresponding scanline data
71
- QVector< GDALDatasetH > mInputDatasets ; // raster references and corresponding dataset
72
-
81
+ QMap< QString, QgsRasterBlock* > inputBlocks;
73
82
QVector<QgsRasterCalculatorEntry>::const_iterator it = mRasterEntries .constBegin ();
74
83
for ( ; it != mRasterEntries .constEnd (); ++it )
75
84
{
76
85
if ( !it->raster ) // no raster layer in entry
77
86
{
78
87
return 2 ;
79
88
}
80
- GDALDatasetH inputDataset = GDALOpen ( TO8F ( it->raster ->source () ), GA_ReadOnly );
81
- if ( !inputDataset )
82
- {
83
- return 2 ;
84
- }
85
89
86
- // check if the input dataset is south up or rotated. If yes, use GDALAutoCreateWarpedVRT to create a north up raster
87
- double inputGeoTransform[6 ];
88
- if ( GDALGetGeoTransform ( inputDataset, inputGeoTransform ) == CE_None
89
- && ( inputGeoTransform[1 ] < 0.0
90
- || inputGeoTransform[2 ] != 0.0
91
- || inputGeoTransform[4 ] != 0.0
92
- || inputGeoTransform[5 ] > 0.0 ) )
90
+ QgsRasterBlock* block = 0 ;
91
+ // if crs transform needed
92
+ if ( it->raster ->crs () != mOutputCrs )
93
93
{
94
- GDALDatasetH vDataset = GDALAutoCreateWarpedVRT ( inputDataset, NULL , NULL , GRA_NearestNeighbour, 0.2 , NULL );
95
- mInputDatasets .push_back ( vDataset );
96
- mInputDatasets .push_back ( inputDataset );
97
- inputDataset = vDataset;
94
+ QgsRasterProjector* proj = new QgsRasterProjector ();
95
+ proj->setCRS ( it->raster ->crs (), mOutputCrs );
96
+ proj->setInput ( it->raster ->dataProvider ()->clone () );
97
+ proj->setPrecision ( QgsRasterProjector::Exact );
98
+
99
+ block = proj->block ( it->bandNumber , mOutputRectangle , mNumOutputColumns , mNumOutputRows );
98
100
}
99
101
else
100
102
{
101
- mInputDatasets . push_back ( inputDataset );
103
+ block = it-> raster -> dataProvider ()-> block ( it-> bandNumber , mOutputRectangle , mNumOutputColumns , mNumOutputRows );
102
104
}
103
-
104
- GDALRasterBandH inputRasterBand = GDALGetRasterBand ( inputDataset, it->bandNumber );
105
- if ( inputRasterBand == NULL )
106
- {
107
- return 2 ;
108
- }
109
-
110
- int nodataSuccess;
111
- double nodataValue = GDALGetRasterNoDataValue ( inputRasterBand, &nodataSuccess );
112
-
113
- mInputRasterBands .insert ( it->ref , inputRasterBand );
114
- inputScanLineData.insert ( it->ref , new QgsRasterMatrix ( mNumOutputColumns , 1 , new double [mNumOutputColumns ], nodataValue ) );
105
+ inputBlocks.insert ( it->ref , block );
115
106
}
116
107
117
108
// open output dataset for writing
@@ -120,44 +111,21 @@ int QgsRasterCalculator::processCalculation( QProgressDialog* p )
120
111
{
121
112
return 1 ;
122
113
}
123
- GDALDatasetH outputDataset = openOutputFile ( outputDriver );
124
-
125
- // copy the projection info from the first input raster
126
- if ( mRasterEntries .size () > 0 )
127
- {
128
- QgsRasterLayer* rl = mRasterEntries .at ( 0 ).raster ;
129
- if ( rl )
130
- {
131
- char * crsWKT = 0 ;
132
- OGRSpatialReferenceH ogrSRS = OSRNewSpatialReference ( NULL );
133
- if ( OSRSetFromUserInput ( ogrSRS, rl->crs ().authid ().toUtf8 ().constData () ) == OGRERR_NONE )
134
- {
135
- OSRExportToWkt ( ogrSRS, &crsWKT );
136
- GDALSetProjection ( outputDataset, crsWKT );
137
- }
138
- else
139
- {
140
- GDALSetProjection ( outputDataset, TO8 ( rl->crs ().toWkt () ) );
141
- }
142
- OSRDestroySpatialReference ( ogrSRS );
143
- CPLFree ( crsWKT );
144
- }
145
- }
146
-
147
114
115
+ GDALDatasetH outputDataset = openOutputFile ( outputDriver );
116
+ GDALSetProjection ( outputDataset, mOutputCrs .toWkt ().toLocal8Bit ().data () );
148
117
GDALRasterBandH outputRasterBand = GDALGetRasterBand ( outputDataset, 1 );
149
118
150
119
float outputNodataValue = -FLT_MAX;
151
120
GDALSetRasterNoDataValue ( outputRasterBand, outputNodataValue );
152
121
153
- float * resultScanLine = ( float * ) CPLMalloc ( sizeof ( float ) * mNumOutputColumns );
154
-
155
122
if ( p )
156
123
{
157
124
p->setMaximum ( mNumOutputRows );
158
125
}
159
126
160
127
QgsRasterMatrix resultMatrix;
128
+ resultMatrix.setNodataValue ( -FLT_MAX );
161
129
162
130
// read / write line by line
163
131
for ( int i = 0 ; i < mNumOutputRows ; ++i )
@@ -172,28 +140,7 @@ int QgsRasterCalculator::processCalculation( QProgressDialog* p )
172
140
break ;
173
141
}
174
142
175
- // fill buffers
176
- QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin ();
177
- for ( ; bufferIt != inputScanLineData.end (); ++bufferIt )
178
- {
179
- double sourceTransformation[6 ];
180
- GDALRasterBandH sourceRasterBand = mInputRasterBands [bufferIt.key ()];
181
- if ( GDALGetGeoTransform ( GDALGetBandDataset ( sourceRasterBand ), sourceTransformation ) != CE_None )
182
- {
183
- qWarning ( " GDALGetGeoTransform failed!" );
184
- }
185
-
186
- float * inputScanLine = ( float * ) CPLMalloc ( sizeof ( float ) * mNumOutputColumns );
187
-
188
- // the function readRasterPart calls GDALRasterIO (and ev. does some conversion if raster transformations are not the same)
189
- readRasterPart ( targetGeoTransform, 0 , i, mNumOutputColumns , 1 , sourceTransformation, sourceRasterBand, inputScanLine );
190
- for ( int col = 0 ; col < mNumOutputColumns ; ++col )
191
- {
192
- bufferIt.value ()->data ()[col] = ( double )inputScanLine[col];
193
- }
194
- }
195
-
196
- if ( calcNode->calculate ( inputScanLineData, resultMatrix ) )
143
+ if ( calcNode->calculate ( inputBlocks, resultMatrix, i ) )
197
144
{
198
145
bool resultIsNumber = resultMatrix.isNumber ();
199
146
float * calcData = new float [mNumOutputColumns ];
@@ -225,18 +172,8 @@ int QgsRasterCalculator::processCalculation( QProgressDialog* p )
225
172
226
173
// close datasets and release memory
227
174
delete calcNode;
228
- QMap< QString, QgsRasterMatrix* >::iterator bufferIt = inputScanLineData.begin ();
229
- for ( ; bufferIt != inputScanLineData.end (); ++bufferIt )
230
- {
231
- delete bufferIt.value ();
232
- }
233
- inputScanLineData.clear ();
234
-
235
- QVector< GDALDatasetH >::iterator datasetIt = mInputDatasets .begin ();
236
- for ( ; datasetIt != mInputDatasets .end (); ++ datasetIt )
237
- {
238
- GDALClose ( *datasetIt );
239
- }
175
+ qDeleteAll ( inputBlocks );
176
+ inputBlocks.clear ();
240
177
241
178
if ( p && p->wasCanceled () )
242
179
{
@@ -245,7 +182,7 @@ int QgsRasterCalculator::processCalculation( QProgressDialog* p )
245
182
return 3 ;
246
183
}
247
184
GDALClose ( outputDataset );
248
- CPLFree ( resultScanLine );
185
+
249
186
return 0 ;
250
187
}
251
188
0 commit comments