1
1
#include " qgsrasterfilewriter.h"
2
2
#include " qgsproviderregistry.h"
3
- #include " qgsrasterdataprovider.h"
4
3
#include " qgsrasterinterface.h"
5
4
#include " qgsrasteriterator.h"
6
5
#include " qgsrasterlayer.h"
@@ -39,129 +38,152 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRaster( QgsRasterIter
39
38
return SourceProviderError;
40
39
}
41
40
42
- #if 0
43
- if ( outputExtent.isEmpty() )
44
- {
45
- outputExtent = sourceProvider->extent();
46
- }
47
- #endif // 0
48
-
49
41
mProgressDialog = p;
50
42
51
43
if ( iface->dataType ( 1 ) == QgsRasterInterface::ARGB32 )
52
44
{
53
- WriterError e = writeARGBRaster ( iter, nCols, outputExtent, crs );
45
+ WriterError e = writeImageRaster ( iter, nCols, outputExtent, crs );
54
46
mProgressDialog = 0 ;
55
47
return e;
56
48
}
57
49
else
58
50
{
59
- //
60
51
mProgressDialog = 0 ;
61
- return NoError;
52
+ WriterError e = writeDataRaster ( iter, nCols, outputExtent, crs );
53
+ return e;
62
54
}
63
55
}
64
56
65
- QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeRasterSingleTile ( QgsRasterIterator* iter, int nCols )
57
+ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster ( QgsRasterIterator* iter, int nCols, const QgsRectangle& outputExtent,
58
+ const QgsCoordinateReferenceSystem& crs )
66
59
{
67
- #if 0
68
- if ( !sourceProvider || ! sourceProvider->isValid() )
60
+ if ( !iter )
69
61
{
70
62
return SourceProviderError;
71
63
}
72
64
73
- QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider( mOutputProviderKey, mOutputUrl );
74
- if ( !destProvider )
65
+ const QgsRasterInterface* iface = iter-> input ( );
66
+ if ( !iface )
75
67
{
76
- return DestProviderError ;
68
+ return SourceProviderError ;
77
69
}
78
70
79
- QgsRectangle sourceProviderRect = sourceProvider->extent();
80
- double pixelSize = sourceProviderRect.width() / nCols;
81
- int nRows = ( double )nCols / sourceProviderRect.width() * sourceProviderRect.height() + 0.5;
71
+ // create directory for output files
72
+ QDir destDir ( mOutputUrl );
73
+ if ( mTiledMode )
74
+ {
75
+ destDir.mkdir ( mOutputUrl );
76
+ }
77
+
78
+ // Get output map units per pixel
79
+ double outputMapUnitsPerPixel = outputExtent.width () / nCols;
80
+ int iterLeft, iterTop, iterCols, iterRows;
81
+
82
+ iter->setMaximumTileWidth ( mMaxTileWidth );
83
+ iter->setMaximumTileHeight ( mMaxTileHeight );
84
+
85
+ int nBands = iface->bandCount ();
86
+ if ( nBands < 1 )
87
+ {
88
+ return SourceProviderError;
89
+ }
90
+
91
+ // create destProvider for whole dataset here
92
+ QgsRasterDataProvider* destProvider = 0 ;
93
+ double pixelSize = outputExtent.width () / nCols;
94
+ int nRows = ( double )nCols / outputExtent.width () * outputExtent.height () + 0.5 ;
82
95
double geoTransform[6 ];
83
- geoTransform[0] = sourceProviderRect .xMinimum();
96
+ geoTransform[0 ] = outputExtent .xMinimum ();
84
97
geoTransform[1 ] = pixelSize;
85
98
geoTransform[2 ] = 0.0 ;
86
- geoTransform[3] = sourceProviderRect .yMaximum();
99
+ geoTransform[3 ] = outputExtent .yMaximum ();
87
100
geoTransform[4 ] = 0.0 ;
88
101
geoTransform[5 ] = -pixelSize;
89
102
90
- //debug
91
- bool hasARGBType = false;
92
- QgsRasterInterface::DataType outputDataType = ( QgsRasterInterface::DataType )sourceProvider->dataType( 1 );
93
- int nOutputBands = sourceProvider->bandCount();
94
- int nInputBands = sourceProvider->bandCount();
95
- if ( outputDataType == QgsRasterInterface::::ARGBDataType )
103
+ // check if all the bands have the same data type size, otherwise we cannot write it to the provider
104
+ // (at least not with the current interface)
105
+ int dataTypeSize = iface->typeSize ( iface->dataType ( 1 ) );
106
+ for ( int i = 2 ; i <= nBands; ++i )
96
107
{
97
- hasARGBType = true; //needs to be converted to four band 8bit
98
- outputDataType = QgsRasterInterface::Byte;
99
- nOutputBands = 4;
108
+ if ( iface->typeSize ( iface->dataType ( 1 ) ) != dataTypeSize )
109
+ {
110
+ return DestProviderError;
111
+ }
100
112
}
101
113
102
- if ( !destProvider->create( mOutputFormat, nOutputBands, outputDataType, nCols, nRows, geoTransform,
103
- sourceProvider->crs() ) )
114
+ QList< void *> dataList;
115
+ for ( int i = 1 ; i <= nBands; ++i )
104
116
{
105
- delete destProvider ;
106
- return CreateDatasourceError ;
117
+ iter-> startRasterRead ( i, nCols, nRows, outputExtent ) ;
118
+ dataList. push_back ( VSIMalloc ( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) ) ;
107
119
}
108
120
109
- if ( hasARGBType && nInputBands == 1 )
121
+ if ( mTiledMode )
110
122
{
111
- //For ARGB data, always use 1 input band and four int8 output bands
112
- int nPixels = nCols * nRows;
113
- int dataSize = destProvider->dataTypeSize( 1 ) * nPixels;
114
- void* data = VSIMalloc( dataSize );
115
- sourceProvider->readBlock( 1, sourceProviderRect, nCols, nRows, data );
116
-
117
- //data for output bands
118
- void* redData = VSIMalloc( nPixels );
119
- void* greenData = VSIMalloc( nPixels );
120
- void* blueData = VSIMalloc( nPixels );
121
- void* alphaData = VSIMalloc( nPixels );
123
+ createVRT ( nCols, nRows, crs, geoTransform );
124
+ }
125
+ else
126
+ {
127
+ destProvider = QgsRasterLayer::loadProvider ( mOutputProviderKey , mOutputUrl );
128
+ if ( !destProvider )
129
+ {
130
+ return DestProviderError;
131
+ }
122
132
123
- int red = 0;
124
- int green = 0;
125
- int blue = 0;
126
- int alpha = 255;
127
- uint* p = ( uint* ) data;
128
- for ( int i = 0; i < nPixels; ++i )
133
+ if ( !destProvider->create ( mOutputFormat , nBands, iface->dataType ( 1 ), nCols, nRows, geoTransform,
134
+ crs ) )
129
135
{
130
- QRgb c( *p++ );
131
- red = qRed( c ); green = qGreen( c ); blue = qBlue( c ); alpha = qAlpha( c );
132
- memcpy(( char* )redData + i, &red, 1 );
133
- memcpy(( char* )greenData + i, &green, 1 );
134
- memcpy(( char* )blueData + i, &blue, 1 );
135
- memcpy(( char* )alphaData + i, &alpha, 1 );
136
+ delete destProvider;
137
+ return CreateDatasourceError;
136
138
}
137
- destProvider->write( redData, 1, nCols, nRows, 0, 0 );
138
- destProvider->write( greenData, 2, nCols, nRows, 0, 0 );
139
- destProvider->write( blueData, 3, nCols, nRows, 0, 0 );
140
- destProvider->write( alphaData, 4, nCols, nRows, 0, 0 );
141
139
}
142
- else
140
+
141
+ int fileIndex = 0 ;
142
+ while ( true )
143
143
{
144
- //read/write data for each band
145
- for ( int i = 0; i < sourceProvider->bandCount(); ++i )
144
+ for ( int i = 1 ; i <= nBands; ++i )
146
145
{
147
- void* data = VSIMalloc( destProvider->dataTypeSize( i + 1 ) * nCols * nRows );
148
- sourceProvider->readBlock( i + 1, sourceProviderRect, nCols, nRows, data );
149
- bool writeSuccess = destProvider->write( data, i + 1, nCols, nRows, 0, 0 );
150
- CPLFree( data );
151
- if ( !writeSuccess )
146
+ if ( !iter->readNextRasterPart ( i, iterCols, iterRows, &( dataList[i - 1 ] ), iterLeft, iterTop ) )
152
147
{
153
148
delete destProvider;
154
- return WriteError;
149
+ if ( mTiledMode )
150
+ {
151
+ QFileInfo outputInfo ( mOutputUrl );
152
+ QString vrtFilePath ( mOutputUrl + " /" + outputInfo.baseName () + " .vrt" );
153
+ writeVRT ( vrtFilePath );
154
+ buildPyramides ( vrtFilePath );
155
+ }
156
+
157
+ return NoError; // reached last tile, bail out
155
158
}
156
159
}
157
- }
158
160
159
- delete destProvider;
160
- #endif // 0
161
- return NoError;
161
+ if ( mTiledMode ) // write to file
162
+ {
163
+ delete destProvider;
164
+ destProvider = createPartProvider ( outputExtent, nCols, iterCols, iterRows,
165
+ iterLeft, iterTop, mOutputUrl , fileIndex, nBands, iface->dataType ( 1 ), crs );
166
+
167
+ // write data to output file. todo: loop over the data list
168
+ for ( int i = 1 ; i <= nBands; ++i )
169
+ {
170
+ destProvider->write ( dataList[i - 1 ], i, iterCols, iterRows, 0 , 0 );
171
+ addToVRT ( QString::number ( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
172
+ }
173
+ ++fileIndex;
174
+ }
175
+ else
176
+ {
177
+ // loop over data
178
+ for ( int i = 0 ; i <= nBands; ++i )
179
+ {
180
+ destProvider->write ( dataList[i - 1 ], i, iterCols, iterRows, iterLeft, iterTop );
181
+ }
182
+ }
183
+ }
162
184
}
163
185
164
- QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeARGBRaster ( QgsRasterIterator* iter, int nCols, const QgsRectangle& outputExtent,
186
+ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeImageRaster ( QgsRasterIterator* iter, int nCols, const QgsRectangle& outputExtent,
165
187
const QgsCoordinateReferenceSystem& crs )
166
188
{
167
189
if ( !iter )
@@ -235,49 +257,13 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeARGBRaster( QgsRaster
235
257
// iter->select( outputExtent, outputMapUnitsPerPixel );
236
258
iter->startRasterRead ( 1 , nCols, nRows, outputExtent );
237
259
238
- #if 0
239
- //initialize progress dialog
240
- int nTiles = iter.nTilesX() * iter.nTilesY();
241
- if ( mProgressDialog )
242
- {
243
- mProgressDialog->setWindowTitle( QObject::tr( "Save raster" ) );
244
- mProgressDialog->setMaximum( nTiles );
245
- mProgressDialog->show();
246
- }
247
- #endif // 0
248
-
249
260
while ( iter->readNextRasterPart ( 1 , iterCols, iterRows, &data, iterLeft, iterTop ) )
250
261
{
251
262
if ( iterCols <= 5 || iterRows <= 5 ) // some wms servers don't like small values
252
263
{
253
264
continue ;
254
265
}
255
266
256
- double mup = outputExtent.width () / nCols;
257
- double mapLeft = outputExtent.xMinimum () + iterLeft * mup;
258
- double mapRight = mapLeft + mup * iterCols;
259
- double mapTop = outputExtent.yMaximum () - iterTop * mup;
260
- double mapBottom = mapTop - iterTop * mup;
261
- QgsRectangle mapRect ( mapLeft, mapBottom, mapRight, mapTop );
262
-
263
- if ( mapRect.width () < 0.000000001 || mapRect.height () < 0.000000001 )
264
- {
265
- continue ;
266
- }
267
-
268
- #if 0
269
- if ( mProgressDialog )
270
- {
271
- mProgressDialog->setValue( fileIndex + 1 );
272
- mProgressDialog->setLabelText( QObject::tr( "Downloaded raster tile %1 from %2" ).arg( fileIndex + 1 ).arg( nTiles ) );
273
- qApp->processEvents( QEventLoop::AllEvents, 2000 );
274
- if ( mProgressDialog->wasCanceled() )
275
- {
276
- break;
277
- }
278
- }
279
- #endif // 0
280
-
281
267
// fill into red/green/blue/alpha channels
282
268
uint* p = ( uint* ) data;
283
269
int nPixels = iterCols * iterRows;
@@ -298,28 +284,9 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeARGBRaster( QgsRaster
298
284
// create output file
299
285
if ( mTiledMode )
300
286
{
301
- QString outputFile = mOutputUrl + " /" + QString::number ( fileIndex );
302
287
delete destProvider;
303
- destProvider = QgsRasterLayer::loadProvider ( mOutputProviderKey , outputFile );
304
- if ( !destProvider )
305
- {
306
- return DestProviderError;
307
- }
308
-
309
- // geotransform
310
- double geoTransform[6 ];
311
- geoTransform[0 ] = mapRect.xMinimum ();
312
- geoTransform[1 ] = outputMapUnitsPerPixel;
313
- geoTransform[2 ] = 0.0 ;
314
- geoTransform[3 ] = mapRect.yMaximum ();
315
- geoTransform[4 ] = 0.0 ;
316
- geoTransform[5 ] = -outputMapUnitsPerPixel;
317
- if ( !destProvider->create ( mOutputFormat , 4 , QgsRasterInterface::Byte, iterCols, iterRows, geoTransform,
318
- crs ) )
319
- {
320
- delete destProvider;
321
- return CreateDatasourceError;
322
- }
288
+ destProvider = createPartProvider ( outputExtent, nCols, iterCols, iterRows,
289
+ iterLeft, iterTop, mOutputUrl , fileIndex, 4 , QgsRasterInterface::Byte, crs );
323
290
324
291
// write data to output file
325
292
destProvider->write ( redData, 1 , iterCols, iterRows, 0 , 0 );
@@ -345,13 +312,6 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeARGBRaster( QgsRaster
345
312
delete destProvider;
346
313
CPLFree ( data ); CPLFree ( redData ); CPLFree ( greenData ); CPLFree ( blueData ); CPLFree ( alphaData );
347
314
348
- #if 0
349
- if ( mProgressDialog )
350
- {
351
- mProgressDialog->setValue( nTiles );
352
- }
353
- #endif // 0
354
-
355
315
if ( mTiledMode )
356
316
{
357
317
QFileInfo outputInfo ( mOutputUrl );
@@ -553,6 +513,41 @@ bool QgsRasterFileWriter::writeVRT( const QString& file )
553
513
return true ;
554
514
}
555
515
516
+ QgsRasterDataProvider* QgsRasterFileWriter::createPartProvider ( const QgsRectangle& extent, int nCols, int iterCols,
517
+ int iterRows, int iterLeft, int iterTop, const QString& outputUrl, int fileIndex, int nBands, QgsRasterInterface::DataType type,
518
+ const QgsCoordinateReferenceSystem& crs )
519
+ {
520
+ double mup = extent.width () / nCols;
521
+ double mapLeft = extent.xMinimum () + iterLeft * mup;
522
+ double mapRight = mapLeft + mup * iterCols;
523
+ double mapTop = extent.yMaximum () - iterTop * mup;
524
+ double mapBottom = mapTop - iterRows * mup;
525
+ QgsRectangle mapRect ( mapLeft, mapBottom, mapRight, mapTop );
526
+
527
+ QString outputFile = outputUrl + " /" + QString::number ( fileIndex );
528
+ QgsRasterDataProvider* destProvider = QgsRasterLayer::loadProvider ( mOutputProviderKey , outputFile );
529
+ if ( !destProvider )
530
+ {
531
+ return 0 ;
532
+ }
533
+
534
+ // geotransform
535
+ double geoTransform[6 ];
536
+ geoTransform[0 ] = mapRect.xMinimum ();
537
+ geoTransform[1 ] = mup;
538
+ geoTransform[2 ] = 0.0 ;
539
+ geoTransform[3 ] = mapRect.yMaximum ();
540
+ geoTransform[4 ] = 0.0 ;
541
+ geoTransform[5 ] = -mup;
542
+ if ( !destProvider->create ( mOutputFormat , nBands, type, iterCols, iterRows, geoTransform,
543
+ crs ) )
544
+ {
545
+ delete destProvider;
546
+ return 0 ;
547
+ }
548
+ return destProvider;
549
+ }
550
+
556
551
557
552
558
553
0 commit comments