Skip to content

Commit c4fa82e

Browse files
committedSep 12, 2012
rasters saveas data type conversion fix
1 parent aa063f6 commit c4fa82e

9 files changed

+89
-17
lines changed
 

‎src/app/qgisapp.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4023,6 +4023,9 @@ void QgisApp::saveAsRasterFile()
40234023
}
40244024

40254025
QProgressDialog pd( 0, tr( "Abort..." ), 0, 0 );
4026+
// Show the dialo immediately because cloning pipe can take some time (WCS)
4027+
pd.setLabelText( QObject::tr( "Reading raster" ) );
4028+
pd.show();
40264029
pd.setWindowModality( Qt::WindowModal );
40274030

40284031
// TODO: show error dialogs

‎src/core/qgsrasterdataprovider.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
528528
virtual QDateTime dataTimestamp() const { return QDateTime(); }
529529

530530
/**Writes into the provider datasource*/
531+
// TODO: add data type (may be defferent from band type)
531532
virtual bool write( void* data, int band, int width, int height, int xOffset, int yOffset )
532533
{
533534
Q_UNUSED( data );

‎src/core/raster/qgsrasterfilewriter.cpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,13 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
157157
QList<QgsRasterInterface::DataType> destDataTypeList;
158158
for ( int bandNo = 1; bandNo <= nBands; bandNo++ )
159159
{
160+
QgsRasterNuller *nuller = pipe->nuller();
160161

161162
bool srcHasNoDataValue = srcProvider->srcHasNoDataValue( bandNo );
162163
bool destHasNoDataValue = false;
163164
double destNoDataValue;
164-
QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
165+
//QgsRasterInterface::DataType destDataType = srcProvider->srcDataType( bandNo );
166+
QgsRasterInterface::DataType destDataType = srcProvider->dataType( bandNo );
165167
if ( srcHasNoDataValue )
166168
{
167169
// If source has no data value, it is used by provider
@@ -170,13 +172,12 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
170172
destNoDataValue = srcProvider->noDataValue();
171173
destHasNoDataValue = true;
172174
}
173-
#if 0
174-
else if ( )
175+
else if ( nuller && nuller->noData().size() > 0 )
175176
{
176-
// TODO: see if nuller has user defined aditional values, in that case use one as no data value
177-
177+
// Use one user defined no data value
178+
destNoDataValue = nuller->noData().value( 0 ).min;
179+
destHasNoDataValue = true;
178180
}
179-
#endif
180181
else
181182
{
182183
// Verify if we realy need no data value, i.e.
@@ -212,6 +213,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster( const Qgs
212213
destHasNoDataValue = true;
213214
}
214215
}
216+
if ( nuller ) nuller->setOutputNoData( destNoDataValue );
217+
215218
QgsDebugMsg( QString( "bandNo = %1 destDataType = %2 destHasNoDataValue = %3 destNoDataValue = %4" ).arg( bandNo ).arg( destDataType ).arg( destHasNoDataValue ).arg( destNoDataValue ) );
216219
destDataTypeList.append( destDataType );
217220
destHasNoDataValueList.append( destHasNoDataValue );
@@ -282,11 +285,12 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
282285
int iterCols = 0;
283286
int iterRows = 0;
284287

285-
int dataTypeSize = srcProvider->typeSize( srcProvider->srcDataType( 1 ) );
288+
int dataTypeSize = srcProvider->typeSize( srcProvider->dataType( 1 ) ) / 8;
286289
QList<void*> dataList;
287290
for ( int i = 1; i <= nBands; ++i )
288291
{
289292
iter->startRasterRead( i, nCols, nRows, outputExtent );
293+
// TODO: no need to alloc memory, change to readBlock() returning the allocated block
290294
dataList.push_back( VSIMalloc( dataTypeSize * mMaxTileWidth * mMaxTileHeight ) );
291295
// TODO - fix segfault here when using tiles+vrt (reported by Etienne)
292296
destProvider->setNoDataValue( i, destNoDataValueList.value( i - 1 ) );
@@ -347,6 +351,24 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
347351
}
348352
}
349353

354+
// It may happen that internal data type (dataType) is wider than destDataType
355+
QList<void*> destDataList;
356+
for ( int i = 1; i <= nBands; ++i )
357+
{
358+
if ( srcProvider->dataType( i ) == destDataType )
359+
{
360+
destDataList.push_back( dataList[i-1] );
361+
}
362+
else
363+
{
364+
// TODO: this conversion should go to QgsRasterDataProvider::write with additional input data type param
365+
void *destData = QgsRasterInterface::convert( dataList[i-1], srcProvider->srcDataType( i ), destDataType, iterCols * iterRows );
366+
destDataList.push_back( destData );
367+
CPLFree( dataList[i-1] );
368+
}
369+
dataList[i-1] = 0;
370+
}
371+
350372
if ( mTiledMode ) //write to file
351373
{
352374
delete destProvider;
@@ -356,8 +378,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
356378
//write data to output file. todo: loop over the data list
357379
for ( int i = 1; i <= nBands; ++i )
358380
{
359-
destProvider->write( dataList[i - 1], i, iterCols, iterRows, 0, 0 );
360-
CPLFree( dataList[i - 1] );
381+
destProvider->write( destDataList[i - 1], i, iterCols, iterRows, 0, 0 );
382+
CPLFree( destDataList[i - 1] );
361383
addToVRT( QString::number( fileIndex ), i, iterCols, iterRows, iterLeft, iterTop );
362384
}
363385
}
@@ -366,8 +388,8 @@ QgsRasterFileWriter::WriterError QgsRasterFileWriter::writeDataRaster(
366388
//loop over data
367389
for ( int i = 1; i <= nBands; ++i )
368390
{
369-
destProvider->write( dataList[i - 1], i, iterCols, iterRows, iterLeft, iterTop );
370-
CPLFree( dataList[i - 1] );
391+
destProvider->write( destDataList[i - 1], i, iterCols, iterRows, iterLeft, iterTop );
392+
CPLFree( destDataList[i - 1] );
371393
}
372394
}
373395
++fileIndex;

‎src/core/raster/qgsrasterinterface.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include "qgslogger.h"
2525
#include "qgsrasterinterface.h"
2626

27+
#include "cpl_conv.h"
28+
2729
QgsRasterInterface::QgsRasterInterface( QgsRasterInterface * input )
2830
: mInput( input )
2931
, mOn( true )
@@ -248,3 +250,15 @@ QString QgsRasterInterface::printValue( double value )
248250
QgsDebugMsg( "Cannot correctly parse printed value" );
249251
return s;
250252
}
253+
254+
void * QgsRasterInterface::convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size )
255+
{
256+
int destDataTypeSize = typeSize( destDataType ) / 8;
257+
void *destData = VSIMalloc( destDataTypeSize * size );
258+
for ( int i = 0; i < size; i++ )
259+
{
260+
double value = readValue( srcData, srcDataType, i );
261+
writeValue( destData, destDataType, i, value );
262+
}
263+
return destData;
264+
}

‎src/core/raster/qgsrasterinterface.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#ifndef QGSRASTERINTERFACE_H
1919
#define QGSRASTERINTERFACE_H
2020

21+
#include <limits>
22+
2123
#include <QImage>
2224

2325
#include "qgsrectangle.h"
@@ -61,7 +63,7 @@ class CORE_EXPORT QgsRasterInterface
6163

6264
virtual ~QgsRasterInterface();
6365

64-
int typeSize( int dataType ) const
66+
static int typeSize( int dataType )
6567
{
6668
// Modified and extended copy from GDAL
6769
switch ( dataType )
@@ -197,15 +199,24 @@ class CORE_EXPORT QgsRasterInterface
197199
* @return string representing the value*/
198200
static QString printValue( double value );
199201

202+
/** \brief Convert block of data from one type to another. Original block memory
203+
* is not release.
204+
* @param srcData source data
205+
* @param srcDataType source data type
206+
* @param destDataType dest data type
207+
* @param size block size (width * height)
208+
* @return block of data in destDataType */
209+
static void * convert( void *srcData, QgsRasterInterface::DataType srcDataType, QgsRasterInterface::DataType destDataType, int size );
210+
200211
protected:
201212
// QgsRasterInterface used as input
202213
QgsRasterInterface* mInput;
203214

204215
// On/off state, if off, it does not do anything, replicates input
205216
bool mOn;
206217

207-
inline double readValue( void *data, QgsRasterInterface::DataType type, int index );
208-
inline void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );
218+
inline static double readValue( void *data, QgsRasterInterface::DataType type, int index );
219+
inline static void writeValue( void *data, QgsRasterInterface::DataType type, int index, double value );
209220

210221
private:
211222
// Last rendering cumulative (this and all preceding interfaces) times, from index 1
@@ -217,6 +228,7 @@ class CORE_EXPORT QgsRasterInterface
217228

218229
inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::DataType type, int index )
219230
{
231+
#if 0
220232
if ( !mInput )
221233
{
222234
return 0;
@@ -226,6 +238,7 @@ inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::Dat
226238
{
227239
return mInput->noDataValue();
228240
}
241+
#endif
229242

230243
switch ( type )
231244
{
@@ -256,7 +269,8 @@ inline double QgsRasterInterface::readValue( void *data, QgsRasterInterface::Dat
256269
}
257270

258271
// TODO: noDataValue is per band
259-
return mInput->noDataValue();
272+
//return mInput->noDataValue();
273+
return std::numeric_limits<double>::quiet_NaN();
260274
}
261275

262276
inline void QgsRasterInterface::writeValue( void *data, QgsRasterInterface::DataType type, int index, double value )

‎src/core/raster/qgsrasternuller.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ void * QgsRasterNuller::readBlock( int bandNo, QgsRectangle const & extent, int
5858

5959
QgsRasterInterface::DataType dataType = mInput->dataType( bandNo );
6060

61-
double noDataValue = mInput->noDataValue( bandNo );
61+
// Input may be without no data value
62+
//double noDataValue = mInput->noDataValue( bandNo );
63+
double noDataValue = mOutputNoData;
6264

6365
for ( int i = 0; i < height; i++ )
6466
{

‎src/core/raster/qgsrasternuller.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,15 @@ class CORE_EXPORT QgsRasterNuller : public QgsRasterInterface
4545

4646
void setNoData( QList<QgsRasterNuller::NoData> noData ) { mNoData = noData; }
4747

48+
QList<QgsRasterNuller::NoData> noData() const { return mNoData; }
49+
50+
/** \brief Set output no data value. */
51+
void setOutputNoData( double noData ) { mOutputNoData = noData; }
52+
4853
private:
4954
QList<QgsRasterNuller::NoData> mNoData;
55+
// no data to be set in output
56+
double mOutputNoData;
5057
};
5158

5259
#endif // QGSRASTERNULLER_H

‎src/core/raster/qgsrasterpipe.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ QgsRasterPipe::Role QgsRasterPipe::interfaceRole( QgsRasterInterface * interface
127127
if ( dynamic_cast<QgsRasterRenderer *>( interface ) ) return RendererRole;
128128
if ( dynamic_cast<QgsRasterResampleFilter *>( interface ) ) return ResamplerRole;
129129
if ( dynamic_cast<QgsRasterProjector *>( interface ) ) return ProjectorRole;
130+
if ( dynamic_cast<QgsRasterNuller *>( interface ) ) return NullerRole;
130131
return UnknownRole;
131132
}
132133

@@ -225,6 +226,11 @@ QgsRasterProjector * QgsRasterPipe::projector() const
225226
return dynamic_cast<QgsRasterProjector*>( interface( ProjectorRole ) );
226227
}
227228

229+
QgsRasterNuller * QgsRasterPipe::nuller() const
230+
{
231+
return dynamic_cast<QgsRasterNuller*>( interface( NullerRole ) );
232+
}
233+
228234
bool QgsRasterPipe::remove( int idx )
229235
{
230236
QgsDebugMsg( QString( "remove at %1" ).arg( idx ) );

‎src/core/raster/qgsrasterpipe.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "qgsrasterinterface.h"
2626
#include "qgsrasterresamplefilter.h"
2727
#include "qgsrasterdataprovider.h"
28+
#include "qgsrasternuller.h"
2829
#include "qgsrasterrenderer.h"
2930
#include "qgsrasterprojector.h"
3031

@@ -45,7 +46,8 @@ class CORE_EXPORT QgsRasterPipe
4546
ProviderRole = 1,
4647
RendererRole = 2,
4748
ResamplerRole = 3,
48-
ProjectorRole = 4
49+
ProjectorRole = 4,
50+
NullerRole = 5,
4951
};
5052

5153
QgsRasterPipe( );
@@ -91,6 +93,7 @@ class CORE_EXPORT QgsRasterPipe
9193
QgsRasterRenderer * renderer() const;
9294
QgsRasterResampleFilter * resampleFilter() const;
9395
QgsRasterProjector * projector() const;
96+
QgsRasterNuller * nuller() const;
9497

9598
/** Set on/off collection of statistics */
9699
void setStatsOn( bool on ) { if ( last() ) last()->setStatsOn( on ); }

0 commit comments

Comments
 (0)
Please sign in to comment.