QMap<QString, QString> QgsRasterDataProvider::identify( const QgsPoint & thePoint, const QgsRectangle &theExtent, int theWidth, int theHeight ) { QMap<QString, QString> results; QgsRasterDataProvider::IdentifyFormat identifyFormat; if ( capabilities() & QgsRasterDataProvider::IdentifyValue ) { identifyFormat = QgsRasterDataProvider::IdentifyFormatValue; } else if ( capabilities() & QgsRasterDataProvider::IdentifyHtml ) { identifyFormat = QgsRasterDataProvider::IdentifyFormatHtml; } else if ( capabilities() & QgsRasterDataProvider::IdentifyText ) { identifyFormat = QgsRasterDataProvider::IdentifyFormatText; } else { return results; } QMap<int, QVariant> myResults = identify( thePoint, identifyFormat, theExtent, theWidth, theHeight ); if ( identifyFormat == QgsRasterDataProvider::IdentifyFormatValue ) { foreach ( int bandNo, myResults.keys() ) { double value = myResults.value( bandNo ).toDouble(); QString valueString; if ( isNoDataValue( bandNo, value ) ) { valueString = tr( "no data" ); } else { valueString = QgsRasterBlock::printValue( value ); } results.insert( generateBandName( bandNo ), valueString ); } }
QgsRasterBandStats QgsRasterDataProvider::bandStatistics( int theBandNo ) { double myNoDataValue = noDataValue(); QgsRasterBandStats myRasterBandStats; myRasterBandStats.elementCount = 0; // because we'll be counting only VALID pixels later myRasterBandStats.bandName = generateBandName( theBandNo ); myRasterBandStats.bandNumber = theBandNo; int myDataType = dataType( theBandNo ); int myNXBlocks, myNYBlocks, myXBlockSize, myYBlockSize; myXBlockSize = xBlockSize(); myYBlockSize = yBlockSize(); myNXBlocks = ( xSize() + myXBlockSize - 1 ) / myXBlockSize; myNYBlocks = ( ySize() + myYBlockSize - 1 ) / myYBlockSize; void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( dataTypeSize( theBandNo ) / 8 ) ); // unfortunately we need to make two passes through the data to calculate stddev bool myFirstIterationFlag = true; int myBandXSize = xSize(); int myBandYSize = ySize(); for ( int iYBlock = 0; iYBlock < myNYBlocks; iYBlock++ ) { for ( int iXBlock = 0; iXBlock < myNXBlocks; iXBlock++ ) { int nXValid, nYValid; readBlock( theBandNo, iXBlock, iYBlock, myData ); // Compute the portion of the block that is valid // for partial edge blocks. if (( iXBlock + 1 ) * myXBlockSize > myBandXSize ) nXValid = myBandXSize - iXBlock * myXBlockSize; else nXValid = myXBlockSize; if (( iYBlock + 1 ) * myYBlockSize > myBandYSize ) nYValid = myBandYSize - iYBlock * myYBlockSize; else nYValid = myYBlockSize; // Collect the histogram counts. for ( int iY = 0; iY < nYValid; iY++ ) { for ( int iX = 0; iX < nXValid; iX++ ) { double myValue = readValue( myData, myDataType, iX + ( iY * myXBlockSize ) ); //QgsDebugMsg ( QString ( "%1 %2 value %3" ).arg (iX).arg(iY).arg( myValue ) ); if ( mValidNoDataValue && ( qAbs( myValue - myNoDataValue ) <= TINY_VALUE ) ) { continue; // NULL } myRasterBandStats.sum += myValue; ++myRasterBandStats.elementCount; //only use this element if we have a non null element if ( myFirstIterationFlag ) { //this is the first iteration so initialise vars myFirstIterationFlag = false; myRasterBandStats.minimumValue = myValue; myRasterBandStats.maximumValue = myValue; } //end of true part for first iteration check else { //this is done for all subsequent iterations if ( myValue < myRasterBandStats.minimumValue ) { myRasterBandStats.minimumValue = myValue; } if ( myValue > myRasterBandStats.maximumValue ) { myRasterBandStats.maximumValue = myValue; } } //end of false part for first iteration check } } } //end of column wise loop } //end of row wise loop //end of first pass through data now calculate the range myRasterBandStats.range = myRasterBandStats.maximumValue - myRasterBandStats.minimumValue; //calculate the mean myRasterBandStats.mean = myRasterBandStats.sum / myRasterBandStats.elementCount; //for the second pass we will get the sum of the squares / mean for ( int iYBlock = 0; iYBlock < myNYBlocks; iYBlock++ ) { for ( int iXBlock = 0; iXBlock < myNXBlocks; iXBlock++ ) { int nXValid, nYValid; readBlock( theBandNo, iXBlock, iYBlock, myData ); // Compute the portion of the block that is valid // for partial edge blocks. if (( iXBlock + 1 ) * myXBlockSize > myBandXSize ) nXValid = myBandXSize - iXBlock * myXBlockSize; else nXValid = myXBlockSize; if (( iYBlock + 1 ) * myYBlockSize > myBandYSize ) nYValid = myBandYSize - iYBlock * myYBlockSize; else nYValid = myYBlockSize; // Collect the histogram counts. for ( int iY = 0; iY < nYValid; iY++ ) { for ( int iX = 0; iX < nXValid; iX++ ) { double myValue = readValue( myData, myDataType, iX + ( iY * myXBlockSize ) ); //QgsDebugMsg ( "myValue = " + QString::number(myValue) ); if ( mValidNoDataValue && ( qAbs( myValue - myNoDataValue ) <= TINY_VALUE ) ) { continue; // NULL } myRasterBandStats.sumOfSquares += static_cast < double > ( pow( myValue - myRasterBandStats.mean, 2 ) ); } } } //end of column wise loop } //end of row wise loop //divide result by sample size - 1 and get square root to get stdev myRasterBandStats.stdDev = static_cast < double >( sqrt( myRasterBandStats.sumOfSquares / ( myRasterBandStats.elementCount - 1 ) ) ); #ifdef QGISDEBUG QgsLogger::debug( "************ STATS **************", 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "VALID NODATA", mValidNoDataValue, 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "NULL", noDataValue() , 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "MIN", myRasterBandStats.minimumValue, 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "MAX", myRasterBandStats.maximumValue, 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "RANGE", myRasterBandStats.range, 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "MEAN", myRasterBandStats.mean, 1, __FILE__, __FUNCTION__, __LINE__ ); QgsLogger::debug( "STDDEV", myRasterBandStats.stdDev, 1, __FILE__, __FUNCTION__, __LINE__ ); #endif CPLFree( myData ); myRasterBandStats.statsGathered = true; return myRasterBandStats; }