[QGIS Commit] r14511 - in branches/raster-providers/src: core core/raster providers/grass

svn_qgis at osgeo.org svn_qgis at osgeo.org
Fri Nov 5 03:28:20 EDT 2010


Author: rblazek
Date: 2010-11-05 00:28:20 -0700 (Fri, 05 Nov 2010)
New Revision: 14511

Modified:
   branches/raster-providers/src/core/qgsrasterdataprovider.cpp
   branches/raster-providers/src/core/qgsrasterdataprovider.h
   branches/raster-providers/src/core/raster/qgsrasterlayer.cpp
   branches/raster-providers/src/core/raster/qgsrasterlayer.h
   branches/raster-providers/src/core/raster/qgsrasterviewport.h
   branches/raster-providers/src/providers/grass/qgis.d.rast.c
   branches/raster-providers/src/providers/grass/qgsgrass.cpp
   branches/raster-providers/src/providers/grass/qgsgrass.h
   branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.cpp
   branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.h
Log:
raster providers initial work, basic support for passing data for rendering from providers to raster layer

Modified: branches/raster-providers/src/core/qgsrasterdataprovider.cpp
===================================================================
--- branches/raster-providers/src/core/qgsrasterdataprovider.cpp	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/core/qgsrasterdataprovider.cpp	2010-11-05 07:28:20 UTC (rev 14511)
@@ -39,10 +39,21 @@
 
   if ( abilities & QgsRasterDataProvider::Identify )
   {
-    abilitiesList += "Identify";
-    QgsDebugMsg( "Identify" );
+    abilitiesList += tr( "Identify" );
   }
 
+  if ( abilities & QgsRasterDataProvider::Draw )
+  {
+    abilitiesList += tr( "Draw" );
+  }
+
+  if ( abilities & QgsRasterDataProvider::Data )
+  {
+    abilitiesList += tr( "Data" );
+  }
+
+  QgsDebugMsg( "Capability: " + abilitiesList.join( ", " ) );
+
   return abilitiesList.join( ", " );
 }
 

Modified: branches/raster-providers/src/core/qgsrasterdataprovider.h
===================================================================
--- branches/raster-providers/src/core/qgsrasterdataprovider.h	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/core/qgsrasterdataprovider.h	2010-11-05 07:28:20 UTC (rev 14511)
@@ -21,7 +21,7 @@
 #ifndef QGSRASTERDATAPROVIDER_H
 #define QGSRASTERDATAPROVIDER_H
 
-
+#include "qgslogger.h"
 #include "qgsdataprovider.h"
 
 class QImage;
@@ -46,11 +46,55 @@
     enum Capability
     {
       NoCapabilities =              0,
-      Identify =                    1
-//      Capability2 =           1 <<  1, etc
+      Identify =                    1,
+      // Draw: the provider is capable to render data on QImage, e.g. WMS, GRASS
+      Draw =                   1 << 1,
+      // Data: the provider is capable to return data values, so that 
+      // QgsRasterLayer can render them using selected rendering mode, e.g. GDAL, GRASS
+      Data =          1 << 2
     };
 
+    // This is modified copy of GDALDataType
+    enum DataType
+    {
+      /*! Unknown or unspecified type */          UnknownDataType = 0,
+      /*! Eight bit unsigned integer */           Byte = 1,
+      /*! Sixteen bit unsigned integer */         UInt16 = 2,
+      /*! Sixteen bit signed integer */           Int16 = 3,
+      /*! Thirty two bit unsigned integer */      UInt32 = 4,
+      /*! Thirty two bit signed integer */        Int32 = 5,
+      /*! Thirty two bit floating point */        Float32 = 6,
+      /*! Sixty four bit floating point */        Float64 = 7,
+      /*! Complex Int16 */                        CInt16 = 8,
+      /*! Complex Int32 */                        CInt32 = 9,
+      /*! Complex Float32 */                      CFloat32 = 10,
+      /*! Complex Float64 */                      CFloat64 = 11,
+      TypeCount = 12          /* maximum type # + 1 */
+    }; 
 
+    // This is modified copy of GDALColorInterp
+    enum ColorInterpretation
+    {
+      UndefinedColorInterpretation=0,
+      /*! Greyscale */                                      GrayIndex=1,
+      /*! Paletted (see associated color table) */          PaletteIndex=2,
+      /*! Red band of RGBA image */                         RedBand=3,
+      /*! Green band of RGBA image */                       GreenBand=4,
+      /*! Blue band of RGBA image */                        BlueBand=5,
+      /*! Alpha (0=transparent, 255=opaque) */              AlphaBand=6,
+      /*! Hue band of HLS image */                          HueBand=7,
+      /*! Saturation band of HLS image */                   SaturationBand=8,
+      /*! Lightness band of HLS image */                    LightnessBand=9,
+      /*! Cyan band of CMYK image */                        CyanBand=10,
+      /*! Magenta band of CMYK image */                     MagentaBand=11,
+      /*! Yellow band of CMYK image */                      YellowBand=12,
+      /*! Black band of CMLY image */                       BlackBand=13,
+      /*! Y Luminance */                                    YCbCr_YBand=14,
+      /*! Cb Chroma */                                      YCbCr_CbBand=15,
+      /*! Cr Chroma */                                      YCbCr_CrBand=16,
+      /*! Max current value */                              ColorInterpretationMax=16
+    };
+
     QgsRasterDataProvider();
 
     QgsRasterDataProvider( QString const & uri );
@@ -108,7 +152,73 @@
 
     // TODO: Get the file masks supported by this provider, suitable for feeding into the file open dialog box
 
+    /** Returns data type for the band specified by number */
+    virtual int dataType ( int bandNo ) const
+    {
+      return QgsRasterDataProvider::UnknownDataType;
+    }
 
+    int dataTypeSize ( int dataType ) const
+    {
+      // modified copy from GDAL
+      switch( dataType )
+      {
+        case Byte:
+          return 8;
+
+        case UInt16:
+        case Int16:
+          return 16;
+
+        case UInt32:
+        case Int32:
+        case Float32:
+        case CInt16:
+          return 32;
+
+        case Float64:
+        case CInt32:
+        case CFloat32:
+          return 64;
+
+        case CFloat64:
+          return 128;
+
+        default:
+          return 0;
+      }
+    }
+
+    /** Get numbur of bands */
+    virtual int bandCount() const {
+      return 0;
+    }
+
+    /** Returns data type for the band specified by number */
+    virtual int colorInterpretation ( int bandNo ) const {
+      return QgsRasterDataProvider::UndefinedColorInterpretation;
+    }
+
+    /** Get block size */
+    virtual int xBlockSize() const { return 0; }
+    virtual int yBlockSize() const { return 0; }
+    
+    /** Get raster size */
+    virtual int xSize() const { return 0; }
+    virtual int ySize() const { return 0; }
+
+    /** read block of data  */
+    virtual void readBlock( int bandNo, int xBlock, int yBlock, void *data ){}
+
+    /** read block of data using give extent and size */
+    virtual void readBlock( int bandNo, QgsRectangle  const & viewExtent, int width, int height, void *data ) {};
+
+    /** value representing null data */
+    virtual double noDataValue() const { return 0; }
+
+    virtual double minimumValue(int bandNo)const { return 0; }
+    virtual double maximumValue(int bandNo)const { return 0; }
+
     /**
      * Get metadata in a format suitable for feeding directly
      * into a subset of the GUI raster properties "Metadata" tab.

Modified: branches/raster-providers/src/core/raster/qgsrasterlayer.cpp
===================================================================
--- branches/raster-providers/src/core/raster/qgsrasterlayer.cpp	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/core/raster/qgsrasterlayer.cpp	2010-11-05 07:28:20 UTC (rev 14511)
@@ -682,8 +682,11 @@
  */
 const QgsRasterBandStats QgsRasterLayer::bandStatistics( int theBandNo )
 {
+  QgsDebugMsg( "theBandNo = " + QString::number(theBandNo) );
+  QgsDebugMsg( "mRasterType = " + QString::number(mRasterType) );
   // check if we have received a valid band number
-  if (( GDALGetRasterCount( mGdalDataset ) < theBandNo ) && mRasterType != Palette )
+  //if (( GDALGetRasterCount( mGdalDataset ) < theBandNo ) && mRasterType != Palette )
+  if (( mDataProvider->bandCount() < theBandNo ) && mRasterType != Palette )
   {
     // invalid band id, return nothing
     QgsRasterBandStats myNullReturnStats;
@@ -716,11 +719,11 @@
   emit statusChanged( tr( "Retrieving stats for %1" ).arg( name() ) );
   qApp->processEvents();
   QgsDebugMsg( "stats for band " + QString::number( theBandNo ) );
-  GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
+  //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
 
+  // Not used
+  //QString myColorerpretation = GDALGetColorInterpretationName( GDALGetRasterColorInterpretation( myGdalBand ) );
 
-  QString myColorerpretation = GDALGetColorInterpretationName( GDALGetRasterColorInterpretation( myGdalBand ) );
-
   // XXX this sets the element count to a sensible value; but then you ADD to
   // XXX it later while iterating through all the pixels?
   //myRasterBandStats.elementCount = mWidth * mHeight;
@@ -734,21 +737,29 @@
   // let the user know we're going to possibly be taking a while
   //QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType ( theBandNo );
 
   int  myNXBlocks, myNYBlocks, myXBlockSize, myYBlockSize;
-  GDALGetBlockSize( myGdalBand, &myXBlockSize, &myYBlockSize );
+  //GDALGetBlockSize( myGdalBand, &myXBlockSize, &myYBlockSize );
+  myXBlockSize = mDataProvider->xBlockSize();
+  myYBlockSize = mDataProvider->yBlockSize();
 
-  myNXBlocks = ( GDALGetRasterXSize( myGdalBand ) + myXBlockSize - 1 ) / myXBlockSize;
-  myNYBlocks = ( GDALGetRasterYSize( myGdalBand ) + myYBlockSize - 1 ) / myYBlockSize;
+  //myNXBlocks = ( GDALGetRasterXSize( myGdalBand ) + myXBlockSize - 1 ) / myXBlockSize;
+  //myNYBlocks = ( GDALGetRasterYSize( myGdalBand ) + myYBlockSize - 1 ) / myYBlockSize;
 
-  void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( GDALGetDataTypeSize( myDataType ) / 8 ) );
+  myNXBlocks = ( mDataProvider->xSize() + myXBlockSize - 1 ) / myXBlockSize;
+  myNYBlocks = ( mDataProvider->ySize() + myYBlockSize - 1 ) / myYBlockSize;
 
+  //void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( GDALGetDataTypeSize( myDataType ) / 8 ) );
+  void *myData = CPLMalloc( myXBlockSize * myYBlockSize * ( mDataProvider->dataTypeSize( myDataType ) / 8 ) );
+
   // unfortunately we need to make two passes through the data to calculate stddev
   bool myFirstIterationFlag = true;
 
   //ifdefs below to remove compiler warning about unused vars
 #ifdef QGISDEBUG
+/*
   int success;
   double GDALminimum = GDALGetRasterMinimum( myGdalBand, &success );
 
@@ -787,10 +798,13 @@
   QgsLogger::debug( "exactly computed GDALmaximum:", GDALrange[1] );
 
   QgsDebugMsg( "starting manual stat computation" );
+*/
 #endif
 
-  int myGdalBandXSize = GDALGetRasterXSize( myGdalBand );
-  int myGdalBandYSize = GDALGetRasterYSize( myGdalBand );
+  //int myGdalBandXSize = GDALGetRasterXSize( myGdalBand );
+  //int myGdalBandYSize = GDALGetRasterYSize( myGdalBand );
+  int myGdalBandXSize = mDataProvider->xSize();
+  int myGdalBandYSize = mDataProvider->ySize();
   for ( int iYBlock = 0; iYBlock < myNYBlocks; iYBlock++ )
   {
     emit drawingProgress( iYBlock, myNYBlocks * 2 );
@@ -798,7 +812,8 @@
     for ( int iXBlock = 0; iXBlock < myNXBlocks; iXBlock++ )
     {
       int  nXValid, nYValid;
-      GDALReadBlock( myGdalBand, iXBlock, iYBlock, myData );
+      //GDALReadBlock( myGdalBand, iXBlock, iYBlock, myData );
+      mDataProvider->readBlock( theBandNo, iXBlock, iYBlock, myData );
 
       // Compute the portion of the block that is valid
       // for partial edge blocks.
@@ -866,7 +881,8 @@
     {
       int  nXValid, nYValid;
 
-      GDALReadBlock( myGdalBand, iXBlock, iYBlock, myData );
+      //GDALReadBlock( myGdalBand, iXBlock, iYBlock, myData );
+      mDataProvider->readBlock( theBandNo, iXBlock, iYBlock, myData );
 
       // Compute the portion of the block that is valid
       // for partial edge blocks.
@@ -886,6 +902,7 @@
         for ( int iX = 0; iX < nXValid; iX++ )
         {
           double myValue = readValue( myData, myDataType, iX + ( iY * myXBlockSize ) );
+          //QgsDebugMsg ( "myValue = " + QString::number(myValue) );
 
           if ( mValidNoDataValue && ( fabs( myValue - mNoDataValue ) <= TINY_VALUE || myValue != myValue ) )
           {
@@ -1259,7 +1276,9 @@
   if ( 0 == theMinMax ) { return; }
 
   GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBand );
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType( theBand );
+  // TODO
   void* myGdalScanData = readData( myGdalBand, &mLastViewPort );
 
   /* Check for out of memory error */
@@ -1439,6 +1458,7 @@
   //the contents of the rasterViewPort will change
   QgsRasterViewPort *myRasterViewPort = new QgsRasterViewPort();
 
+  myRasterViewPort->mDrawnExtent = myRasterExtent;
 
   // calculate raster pixel offsets from origin to clipped rect
   // we're only interested in positive offsets where the origin of the raster
@@ -1565,7 +1585,8 @@
 
   QgsDebugMsg( "Checking for provider key." );
 
-  if ( !mProviderKey.isEmpty() )
+  //if ( !mProviderKey.isEmpty() )
+  if ( mDataProvider->capabilities() & QgsRasterDataProvider::Draw )
   {
     QgsDebugMsg( "Wanting a '" + mProviderKey + "' provider to draw this." );
 
@@ -1659,10 +1680,11 @@
       }
     }
   }
-  else
+  else if  ( mDataProvider->capabilities() & QgsRasterDataProvider::Data )
   {
-    // Otherwise use the old-fashioned GDAL direct-drawing style
-    // TODO: Move into its own GDAL provider.
+    // (Otherwise use the old-fashioned GDAL direct-drawing style
+    // TODO: Move into its own GDAL provider.)
+    // the driver can pass the data values ( capability QgsRasterDataProvider::Data )
 
     // \/\/\/ - commented-out to handle zoomed-in rasters
     //    draw(theQPainter,myRasterViewPort);
@@ -1691,6 +1713,10 @@
   // procedure to use :
   //
 
+  // debug
+  QgsDebugMsg( "mDrawingStyle = " + QString::number(mDrawingStyle) );
+  //drawSingleBandGray( theQPainter, theRasterViewPort, theQgsMapToPixel, 1 );
+  //return;
   switch ( mDrawingStyle )
   {
       // a "Gray" or "Undefined" layer drawn as a range of gray colors
@@ -3159,12 +3185,17 @@
 {
   mNoDataValue = std::numeric_limits<int>::max();
   mValidNoDataValue = false;
-  if ( mGdalDataset != NULL && GDALGetRasterCount( mGdalDataset ) > 0 )
+  //if ( mGdalDataset != NULL && GDALGetRasterCount( mGdalDataset ) > 0 )
+  if ( mDataProvider != NULL && mDataProvider->bandCount() > 0 )
   {
     int myRequestValid;
-    double myValue = GDALGetRasterNoDataValue(
-                       GDALGetRasterBand( mGdalDataset, 1 ), &myRequestValid );
+    //double myValue = GDALGetRasterNoDataValue(
+    //                   GDALGetRasterBand( mGdalDataset, 1 ), &myRequestValid );
 
+    // TODO: add 'has null value' to capabilities
+    myRequestValid = 1;
+    double myValue = mDataProvider->noDataValue();
+
     if ( 0 != myRequestValid )
     {
       setNoDataValue( myValue );
@@ -3258,6 +3289,8 @@
           mDataProvider->setImageEncoding( format );
           mDataProvider->setImageCrs( crs );
 
+          setNoDataValue( mDataProvider->noDataValue() );
+
           // get the extent
           QgsRectangle mbr = mDataProvider->extent();
 
@@ -3286,6 +3319,27 @@
           {
             *mCRS = QgsCoordinateReferenceSystem( mDataProvider->crs() );
           }
+          //mBandCount = GDALGetRasterCount( mGdalDataset );
+          mBandCount = mDataProvider->bandCount( );
+          for ( int i = 1; i <= mBandCount; i++ )
+          {
+            //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, i );
+            QgsRasterBandStats myRasterBandStats;
+            myRasterBandStats.bandName = generateBandName( i );
+            myRasterBandStats.bandNumber = i;
+            myRasterBandStats.statsGathered = false;
+            myRasterBandStats.histogramVector = new QgsRasterBandStats::HistogramVector();
+            //Store the default color table
+            // TODO
+            //readColorTable( i, &myRasterBandStats.colorTable );
+
+            mRasterStatsList.push_back( myRasterBandStats );
+
+            //Build a new contrast enhancement for the band and store in list
+            //QgsContrastEnhancement myContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )GDALGetRasterDataType( myGdalBand ) );
+            QgsContrastEnhancement myContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )mDataProvider->dataType( i ) );
+            mContrastEnhancementList.append( myContrastEnhancement );
+          }
         }
       }
       else
@@ -3417,6 +3471,7 @@
  */
 void QgsRasterLayer::setDrawingStyle( QString const & theDrawingStyleQString )
 {
+  QgsDebugMsg( "DrawingStyle = " + theDrawingStyleQString );
   if ( theDrawingStyleQString == "SingleBandGray" )//no need to tr() this its not shown in ui
   {
     mDrawingStyle = SingleBandGray;
@@ -3483,6 +3538,7 @@
 
 void QgsRasterLayer::setMaximumValue( unsigned int theBand, double theValue, bool theGenerateLookupTableFlag )
 {
+  QgsDebugMsg( "setMaximumValue theValue = " + QString::number(theValue) );
   if ( 0 < theBand && theBand <= bandCount() )
   {
     mContrastEnhancementList[theBand - 1].setMaximumValue( theValue, theGenerateLookupTableFlag );
@@ -3528,6 +3584,7 @@
 
 void QgsRasterLayer::setMinimumValue( unsigned int theBand, double theValue, bool theGenerateLookupTableFlag )
 {
+  QgsDebugMsg( "setMinimumValue theValue = " + QString::number(theValue) );
   if ( 0 < theBand && theBand <= bandCount() )
   {
     mContrastEnhancementList[theBand - 1].setMinimumValue( theValue, theGenerateLookupTableFlag );
@@ -3824,7 +3881,9 @@
    */
   snode = mnl.namedItem( "mNoDataValue" );
   myElement = snode.toElement();
+  QgsDebugMsg( "ReadXml: mNoDataValue = " + myElement.text() );
   setNoDataValue( myElement.text().toDouble() );
+  QgsDebugMsg( "ReadXml: mNoDataValue = " + QString::number( mNoDataValue ) );
   if ( myElement.attribute( "mValidNoDataValue", "false" ).compare( "true" ) )
   {
     // If flag element is not true, set to false.
@@ -4495,12 +4554,15 @@
   QgsContrastEnhancement* myGreenContrastEnhancement = contrastEnhancement( myGreenBandNo );
   QgsContrastEnhancement* myBlueContrastEnhancement = contrastEnhancement( myBlueBandNo );
 
-  QgsRasterImageBuffer redImageBuffer( myGdalRedBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer redImageBuffer( myGdalRedBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer redImageBuffer( mDataProvider, myRedBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   redImageBuffer.reset();
-  QgsRasterImageBuffer greenImageBuffer( myGdalGreenBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer greenImageBuffer( myGdalGreenBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer greenImageBuffer( mDataProvider, myGreenBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   greenImageBuffer.setWritingEnabled( false ); //only draw to redImageBuffer
   greenImageBuffer.reset();
-  QgsRasterImageBuffer blueImageBuffer( myGdalBlueBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer blueImageBuffer( myGdalBlueBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer blueImageBuffer( mDataProvider, myBlueBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   blueImageBuffer.setWritingEnabled( false ); //only draw to redImageBuffer
   blueImageBuffer.reset();
 
@@ -4593,10 +4655,12 @@
     return;
   }
 
-  GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType( theBandNo );
 
-  QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer imageBuffer( mDataProvider, theBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   imageBuffer.reset();
 
   QRgb* imageScanLine = 0;
@@ -4673,10 +4737,12 @@
     return;
   }
 
-  GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType( theBandNo );
 
-  QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer imageBuffer( mDataProvider, theBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   imageBuffer.reset();
 
   QRgb* imageScanLine = 0;
@@ -4753,10 +4819,12 @@
   }
 
   QgsRasterBandStats myRasterBandStats = bandStatistics( theBandNo );
-  GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType( theBandNo );
 
-  QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer imageBuffer( mDataProvider, theBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   imageBuffer.reset();
 
   QRgb* imageScanLine = 0;
@@ -4851,9 +4919,12 @@
     return;
   }
 
-  GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
-  QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType( theBandNo );
+  QgsDebugMsg( "myDataType = " + QString::number( myDataType) ); 
+  //QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer imageBuffer( mDataProvider, theBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   imageBuffer.reset();
 
   QRgb* imageScanLine = 0;
@@ -4866,8 +4937,10 @@
   QgsContrastEnhancement* myContrastEnhancement = contrastEnhancement( theBandNo );
 
   QgsRasterBandStats myGrayBandStats;
+  //myGrayBandStats = bandStatistics( theBandNo ); // debug
   if ( QgsContrastEnhancement::NoEnhancement != contrastEnhancementAlgorithm() && !mUserDefinedGrayMinimumMaximum && mStandardDeviations > 0 )
   {
+    QgsDebugMsg( "XXX calc stats" );
     mGrayMinimumMaximumEstimated = false;
     myGrayBandStats = bandStatistics( theBandNo );
     setMaximumValue( theBandNo, myGrayBandStats.mean + ( mStandardDeviations * myGrayBandStats.stdDev ) );
@@ -4875,21 +4948,28 @@
   }
   else if ( QgsContrastEnhancement::NoEnhancement != contrastEnhancementAlgorithm() && !mUserDefinedGrayMinimumMaximum )
   {
+    QgsDebugMsg( "XXX use provider minmax" );
     //This case will be true the first time the image is loaded, so just approimate the min max to keep
     //from calling generate raster band stats
     double GDALrange[2];
-    GDALComputeRasterMinMax( myGdalBand, 1, GDALrange ); //Approximate
+    //GDALComputeRasterMinMax( myGdalBand, 1, GDALrange ); //Approximate
     mGrayMinimumMaximumEstimated = true;
-    setMaximumValue( theBandNo, GDALrange[1] );
-    setMinimumValue( theBandNo, GDALrange[0] );
+    //setMaximumValue( theBandNo, GDALrange[1] );
+    //setMinimumValue( theBandNo, GDALrange[0] );
+    setMaximumValue( theBandNo, mDataProvider->maximumValue ( theBandNo ) );
+    setMinimumValue( theBandNo, mDataProvider->minimumValue ( theBandNo ) );
 
   }
 
+  QgsDebugMsg( " -> imageBuffer.nextScanLine");
   while ( imageBuffer.nextScanLine( &imageScanLine, &rasterScanLine ) )
   {
     for ( int i = 0; i < theRasterViewPort->drawableAreaXDim; ++i )
     {
       myGrayValue = readValue( rasterScanLine, ( GDALDataType )myDataType, i );
+      if ( myGrayValue != -2147483647 ) {
+        //QgsDebugMsg( "myGrayValue = " + QString::number( myGrayValue ) );
+      }
 
       if ( mValidNoDataValue && ( fabs( myGrayValue - mNoDataValue ) <= TINY_VALUE || myGrayValue != myGrayValue ) )
       {
@@ -4918,6 +4998,7 @@
         myGrayVal = 255 - myGrayVal;
       }
 
+      //QgsDebugMsg( QString( "i = %1 myGrayValue = %2").arg(i).arg( myGrayValue ) );
       imageScanLine[ i ] = qRgba( myGrayVal, myGrayVal, myGrayVal, myAlphaValue );
     }
   }
@@ -4936,10 +5017,12 @@
   }
 
   QgsRasterBandStats myRasterBandStats = bandStatistics( theBandNo );
-  GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
-  GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, theBandNo );
+  //GDALDataType myDataType = GDALGetRasterDataType( myGdalBand );
+  int myDataType = mDataProvider->dataType( theBandNo );
 
-  QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  //QgsRasterImageBuffer imageBuffer( myGdalBand, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
+  QgsRasterImageBuffer imageBuffer( mDataProvider, theBandNo, theQPainter, theRasterViewPort, theQgsMapToPixel, &mGeoTransform[0] );
   imageBuffer.reset();
 
   QRgb* imageScanLine = 0;
@@ -5419,24 +5502,25 @@
     mRasterTransparency.initializeTransparentPixelList( mNoDataValue );
   }
 
-  mBandCount = GDALGetRasterCount( mGdalDataset );
-  for ( int i = 1; i <= mBandCount; i++ )
-  {
-    GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, i );
-    QgsRasterBandStats myRasterBandStats;
-    myRasterBandStats.bandName = generateBandName( i );
-    myRasterBandStats.bandNumber = i;
-    myRasterBandStats.statsGathered = false;
-    myRasterBandStats.histogramVector = new QgsRasterBandStats::HistogramVector();
-    //Store the default color table
-    readColorTable( i, &myRasterBandStats.colorTable );
+  // Moved to setDataProvider, later maybe to constructor
+  //mBandCount = GDALGetRasterCount( mGdalDataset );
+  //for ( int i = 1; i <= mBandCount; i++ )
+  //{
+    //GDALRasterBandH myGdalBand = GDALGetRasterBand( mGdalDataset, i );
+    //QgsRasterBandStats myRasterBandStats;
+    //myRasterBandStats.bandName = generateBandName( i );
+    //myRasterBandStats.bandNumber = i;
+    //myRasterBandStats.statsGathered = false;
+    //myRasterBandStats.histogramVector = new QgsRasterBandStats::HistogramVector();
+    ////Store the default color table
+    //readColorTable( i, &myRasterBandStats.colorTable );
 
-    mRasterStatsList.push_back( myRasterBandStats );
+    //mRasterStatsList.push_back( myRasterBandStats );
 
-    //Build a new contrast enhancement for the band and store in list
-    QgsContrastEnhancement myContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )GDALGetRasterDataType( myGdalBand ) );
-    mContrastEnhancementList.append( myContrastEnhancement );
-  }
+    ////Build a new contrast enhancement for the band and store in list
+    //QgsContrastEnhancement myContrastEnhancement(( QgsContrastEnhancement::QgsRasterDataType )GDALGetRasterDataType( myGdalBand ) );
+    //mContrastEnhancementList.append( myContrastEnhancement );
+  //}
 
   //defaults - Needs to be set after the Contrast list has been build
   //Try to read the default contrast enhancement from the config file
@@ -5537,32 +5621,32 @@
 /*
  *  @param index index in memory block
  */
-double QgsRasterLayer::readValue( void *data, GDALDataType type, int index )
+double QgsRasterLayer::readValue( void *data, int type, int index )
 {
   if ( !data )
     return mValidNoDataValue ? mNoDataValue : 0.0;
 
   switch ( type )
   {
-    case GDT_Byte:
+    case QgsRasterDataProvider::Byte:
       return ( double )(( GByte * )data )[index];
       break;
-    case GDT_UInt16:
+    case QgsRasterDataProvider::UInt16:
       return ( double )(( GUInt16 * )data )[index];
       break;
-    case GDT_Int16:
+    case QgsRasterDataProvider::Int16:
       return ( double )(( GInt16 * )data )[index];
       break;
-    case GDT_UInt32:
+    case QgsRasterDataProvider::UInt32:
       return ( double )(( GUInt32 * )data )[index];
       break;
-    case GDT_Int32:
+    case QgsRasterDataProvider::Int32:
       return ( double )(( GInt32 * )data )[index];
       break;
-    case GDT_Float32:
+    case QgsRasterDataProvider::Float32:
       return ( double )(( float * )data )[index];
       break;
-    case GDT_Float64:
+    case QgsRasterDataProvider::Float64:
       return ( double )(( double * )data )[index];
       break;
     default:
@@ -5661,8 +5745,9 @@
   return TRSTRING_NOT_SET;
 }
 
-QgsRasterImageBuffer::QgsRasterImageBuffer( GDALRasterBandH rasterBand, QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* geoTransform ):
-    mRasterBand( rasterBand ), mPainter( p ), mViewPort( viewPort ), mMapToPixel( mapToPixel ), mGeoTransform( geoTransform ), mValid( false ), mWritingEnabled( true ), mDrawPixelRect( false ), mCurrentImage( 0 ), mCurrentGDALData( 0 )
+//QgsRasterImageBuffer::QgsRasterImageBuffer( GDALRasterBandH rasterBand, QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* geoTransform ):
+QgsRasterImageBuffer::QgsRasterImageBuffer( QgsRasterDataProvider *dataProvider, int bandNo, QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* geoTransform ):
+    mDataProvider( dataProvider ), mBandNo(bandNo), mPainter( p ), mViewPort( viewPort ), mMapToPixel( mapToPixel ), mGeoTransform( geoTransform ), mValid( false ), mWritingEnabled( true ), mDrawPixelRect( false ), mCurrentImage( 0 ), mCurrentGDALData( 0 )
 {
 
 }
@@ -5675,7 +5760,9 @@
 
 void QgsRasterImageBuffer::reset( int maxPixelsInVirtualMemory )
 {
-  if ( !mRasterBand || !mPainter || !mViewPort )
+  QgsDebugMsg( "Start" );
+  //if ( !mRasterBand || !mPainter || !mViewPort )
+  if ( !mDataProvider || mBandNo <= 0 || !mPainter || !mViewPort )
   {
     mValid = false;
     return;
@@ -5705,6 +5792,7 @@
 
 bool QgsRasterImageBuffer::nextScanLine( QRgb** imageScanLine, void** rasterScanLine )
 {
+  //QgsDebugMsg( "Entered" );
   if ( !mValid )
     return false;
 
@@ -5729,8 +5817,9 @@
   {
     *imageScanLine = 0;
   }
-  GDALDataType type = GDALGetRasterDataType( mRasterBand );
-  int size = GDALGetDataTypeSize( type ) / 8;
+  //GDALDataType type = GDALGetRasterDataType( mRasterBand );
+  //int size = GDALGetDataTypeSize( type ) / 8;
+  int size = mDataProvider->dataTypeSize(mDataProvider->dataType(mBandNo))/8;
   *rasterScanLine = ( unsigned char * )mCurrentGDALData + mCurrentPartImageRow * mViewPort->drawableAreaXDim * size;
 
   ++mCurrentPartImageRow;
@@ -5740,6 +5829,7 @@
 
 bool QgsRasterImageBuffer::createNextPartImage()
 {
+  QgsDebugMsg( "Entered" );
   //draw the last image if mCurrentImage exists
   if ( mCurrentImage )
   {
@@ -5803,11 +5893,13 @@
   mCurrentPartImageRow = 0;
 
   //read GDAL image data
-  GDALDataType type = GDALGetRasterDataType( mRasterBand );
-  int size = GDALGetDataTypeSize( type ) / 8;
+  //GDALDataType type = GDALGetRasterDataType( mRasterBand );
+  //int size = GDALGetDataTypeSize( type ) / 8;
+  int size = mDataProvider->dataTypeSize ( mDataProvider->dataType(mBandNo) ) / 8 ;
   int xSize = mViewPort->drawableAreaXDim;
   int ySize = mViewPort->drawableAreaYDim;
 
+  //TODO: clean up - most should be thrown out
   //make the raster tiles overlap at least 2 pixels to avoid white stripes
   int overlapRows = 0;
   if ( mMapToPixel )
@@ -5838,16 +5930,25 @@
   }
   mNumCurrentImageRows = ySize;
   mCurrentGDALData = VSIMalloc( size * xSize * ySize );
-  CPLErr myErr = GDALRasterIO( mRasterBand, GF_Read, mViewPort->rectXOffset,
-                               mViewPort->rectYOffset + mCurrentRow, mViewPort->clippedWidth, rasterYSize,
-                               mCurrentGDALData, xSize, ySize, type, 0, 0 );
+  //CPLErr myErr = GDALRasterIO( mRasterBand, GF_Read, mViewPort->rectXOffset,
+  //                             mViewPort->rectYOffset + mCurrentRow, mViewPort->clippedWidth, rasterYSize,
+  //                             mCurrentGDALData, xSize, ySize, type, 0, 0 );
 
-  if ( myErr != CPLE_None )
-  {
-    CPLFree( mCurrentGDALData );
-    mCurrentGDALData = 0;
-    return false;
-  }
+  // TODO: check this, it is probably not precise
+  double yMax = mViewPort->mDrawnExtent.yMaximum() - mCurrentRow * mMapToPixel->mapUnitsPerPixel(); 
+  double yMin = yMax - ySize * mMapToPixel->mapUnitsPerPixel();
+  
+  QgsRectangle partExtent ( mViewPort->mDrawnExtent.xMinimum(), yMin,
+                            mViewPort->mDrawnExtent.xMaximum(), yMax );
+  mDataProvider->readBlock ( mBandNo, partExtent, xSize, ySize, mCurrentGDALData );
+  
+  // TODO - error check - throw exception
+  //if ( myErr != CPLE_None )
+  //{
+  //  CPLFree( mCurrentGDALData );
+  //  mCurrentGDALData = 0;
+  //  return false;
+  //}
 
   //create the QImage
   if ( mWritingEnabled )

Modified: branches/raster-providers/src/core/raster/qgsrasterlayer.h
===================================================================
--- branches/raster-providers/src/core/raster/qgsrasterlayer.h	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/core/raster/qgsrasterlayer.h	2010-11-05 07:28:20 UTC (rev 14511)
@@ -778,7 +778,8 @@
     bool readFile( const QString & fileName );
 
     /** \brief Read a raster value given position from memory block created by readData() */
-    inline double readValue( void *data, GDALDataType type, int index );
+    //inline double readValue( void *data, GDALDataType type, int index );
+    inline double readValue( void *data, int type, int index );
 
     /** \brief Update the layer if it is outdated */
     bool update();
@@ -922,8 +923,9 @@
 class CORE_EXPORT QgsRasterImageBuffer
 {
   public:
-    QgsRasterImageBuffer( GDALRasterBandH rasterBand, QPainter* p,
-                          QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* mGeoTransform );
+    //QgsRasterImageBuffer( GDALRasterBandH rasterBand, QPainter* p,
+    QgsRasterImageBuffer( QgsRasterDataProvider *dataProvider, int bandNo, QPainter* p,
+                          QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel, double* mGeoTransform  );
     ~QgsRasterImageBuffer();
     void reset( int maxPixelsInVirtualMemory = 5000000 );
     /**Returns a pointer to the next scan line (or 0 if end)*/
@@ -939,7 +941,9 @@
     /**Peter's fix for zoomed in rasters*/
     void drawPixelRectangle();
 
-    GDALRasterBandH mRasterBand; //raster band
+    //GDALRasterBandH mRasterBand; //raster band
+    QgsRasterDataProvider* mDataProvider;
+    int mBandNo;
     QPainter* mPainter;
     QgsRasterViewPort* mViewPort;
     const QgsMapToPixel* mMapToPixel;
@@ -957,6 +961,7 @@
     int mCurrentPartRasterMax; //maximum (raster source) row of current image
     int mCurrentPartImageRow; //current image row
     int mNumCurrentImageRows; //number of image rows for the current part
+    //QgsRectangle mCurrentPartExtent; // extent of current part in map units
 
     //current memory image and gdal scan data
     QImage* mCurrentImage;

Modified: branches/raster-providers/src/core/raster/qgsrasterviewport.h
===================================================================
--- branches/raster-providers/src/core/raster/qgsrasterviewport.h	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/core/raster/qgsrasterviewport.h	2010-11-05 07:28:20 UTC (rev 14511)
@@ -74,6 +74,9 @@
   /** \brief Distance in map units from bottom edge to top edge for the part of the raster that
    * is to be rendered.*/
   int drawableAreaYDim;
+
+  // intersection of current map extent and layer extent
+  QgsRectangle mDrawnExtent;
 };
 
 #endif //QGSRASTERVIEWPORT_H

Modified: branches/raster-providers/src/providers/grass/qgis.d.rast.c
===================================================================
--- branches/raster-providers/src/providers/grass/qgis.d.rast.c	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/providers/grass/qgis.d.rast.c	2010-11-05 07:28:20 UTC (rev 14511)
@@ -21,7 +21,7 @@
 #include <grass/raster.h>
 #include <grass/display.h>
 
-int display( char *name, char *mapset, RASTER_MAP_TYPE data_type );
+int display( char *name, char *mapset, RASTER_MAP_TYPE data_type, char *format );
 
 int main( int argc, char **argv )
 {
@@ -31,6 +31,7 @@
   struct GModule *module;
   struct Option *map;
   struct Option *win;
+  struct Option *format;
   struct Cell_head window;
 
   /* Initialize the GIS calls */
@@ -43,6 +44,12 @@
   map = G_define_standard_option( G_OPT_R_MAP );
   map->description = ( "Raster map to be displayed" );
 
+  format = G_define_option();
+  format->key = "format";
+  format->type = TYPE_STRING;
+  format->description = "format";
+  format->options = "color,value";
+
   win = G_define_option();
   win->key = "window";
   win->type = TYPE_DOUBLE;
@@ -76,18 +83,19 @@
 
   /* use DCELL even if the map is FCELL */
   if ( fp )
-    display( name, mapset, DCELL_TYPE );
+    display( name, mapset, DCELL_TYPE, format->answer );
   else
-    display( name, mapset, CELL_TYPE );
+    display( name, mapset, CELL_TYPE, format->answer );
 
   exit( EXIT_SUCCESS );
 }
 
-static int cell_draw( char *, char *, struct Colors *, RASTER_MAP_TYPE );
+static int cell_draw( char *, char *, struct Colors *, RASTER_MAP_TYPE, char *format );
 
 int display( char *name,
              char *mapset,
-             RASTER_MAP_TYPE data_type )
+             RASTER_MAP_TYPE data_type,
+             char *format )
 {
   struct Colors colors;
 
@@ -97,7 +105,7 @@
   //G_set_null_value_color(r, g, b, &colors);
 
   /* Go draw the raster map */
-  cell_draw( name, mapset, &colors, data_type );
+  cell_draw( name, mapset, &colors, data_type, format );
 
   /* release the colors now */
   G_free_colors( &colors );
@@ -108,7 +116,8 @@
 static int cell_draw( char *name,
                       char *mapset,
                       struct Colors *colors,
-                      RASTER_MAP_TYPE data_type )
+                      RASTER_MAP_TYPE data_type,
+                      char *format )
 {
   int cellfile;
   void *xarray;
@@ -120,6 +129,7 @@
   int big_endian;
   long one = 1;
   FILE *fo;
+  int raster_size;
 
   big_endian = !( *(( char * )( &one ) ) );
 
@@ -145,6 +155,7 @@
   // Unfortunately this is not sufficient on Windows to switch stdout to binary mode
   fo = fdopen( fileno( stdout ), "wb" );
 
+  raster_size = G_raster_size( data_type );
   /* loop for array rows */
   for ( row = 0; row < nrows; row++ )
   {
@@ -157,25 +168,53 @@
     for ( i = 0; i < ncols; i++ )
     {
       unsigned char alpha = 255;
+      //G_debug ( 0, "row = %d col = %d", row, i );
       if ( G_is_null_value( ptr, data_type ) )
       {
         alpha = 0;
       }
-      ptr = G_incr_void_ptr( ptr, G_raster_size( data_type ) );
+      ptr = G_incr_void_ptr( ptr, raster_size );
 
-
-      // We need data suitable for QImage 32-bpp
-      // the data are stored in QImage as QRgb which is unsigned int.
-      // Because it depends on byte order of the platform we have to
-      // consider byte order (well, middle endian ignored)
-      if ( big_endian )
+      if ( strcmp(format,"color") == 0 ) 
       {
-        // I have never tested this
-        fprintf( fo, "%c%c%c%c", alpha, red[i], grn[i], blu[i] );
+        // We need data suitable for QImage 32-bpp
+        // the data are stored in QImage as QRgb which is unsigned int.
+        // Because it depends on byte order of the platform we have to
+        // consider byte order (well, middle endian ignored)
+        if ( big_endian )
+        {
+          // I have never tested this
+          fprintf( fo, "%c%c%c%c", alpha, red[i], grn[i], blu[i] );
+        }
+        else
+        {
+          fprintf( fo, "%c%c%c%c", blu[i], grn[i], red[i], alpha );
+        }
       }
       else
       {
-        fprintf( fo, "%c%c%c%c", blu[i], grn[i], red[i], alpha );
+          int *val;
+          val = (int*) (ptr);
+          //G_debug ( 0, "val = %d", *val );
+          if ( data_type == CELL_TYPE) {
+            G_debug ( 0, "valx = %d", *((CELL *) ptr));
+          }
+          if ( G_is_null_value(ptr, data_type) ) {
+            if ( data_type == CELL_TYPE) {
+              int nul = -2147483647;
+              fwrite( &nul , 4, 1, fo );
+            } else if ( data_type == DCELL_TYPE) {
+              double nul = 2.2250738585072014e-308;
+              fwrite( &nul , 8, 1, fo );
+            } else if ( data_type == FCELL_TYPE) {
+              double nul = 1.17549435e-38F;
+              fwrite( &nul , 4, 1, fo );
+            }
+          }
+          else
+          {
+            fwrite( ptr, raster_size, 1, fo );
+          }
       }
     }
   }

Modified: branches/raster-providers/src/providers/grass/qgsgrass.cpp
===================================================================
--- branches/raster-providers/src/providers/grass/qgsgrass.cpp	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/providers/grass/qgsgrass.cpp	2010-11-05 07:28:20 UTC (rev 14511)
@@ -29,6 +29,7 @@
 #include <QSettings>
 #include <QTextStream>
 #include <QTemporaryFile>
+#include <QHash>
 
 #include <QTextCodec>
 
@@ -1171,6 +1172,60 @@
   return QgsRectangle( 0, 0, 0, 0 );
 }
 
+void GRASS_EXPORT QgsGrass::size( QString gisdbase, QString location, QString mapset, QString map, int *cols, int *rows )
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+
+  *cols = 0;
+  *rows = 0;
+  try
+  {
+    QString str = QgsGrass::getInfo( "size", gisdbase, location, mapset, map, QgsGrass::Raster );
+    QStringList list = str.split( "," );
+    if ( list.size() != 2 )
+    {
+      throw QgsGrass::Exception( "Cannot parse GRASS map size: " + str );
+    }
+    *cols = list[0].toInt();
+    *rows = list[1].toInt();
+  }
+  catch ( QgsGrass::Exception &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ),
+                          QObject::tr( "Cannot get raster extent" ) + "\n" + e.what() );
+  }
+  
+  QgsDebugMsg( QString( "raster size = %1 %2" ).arg( *cols ).arg( *rows ) );
+}
+
+QHash<QString, QString> GRASS_EXPORT QgsGrass::info( QString gisdbase, QString location, QString mapset, QString map, MapType type )
+{
+  QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );
+  QHash<QString, QString> inf;
+
+  try
+  {
+    QString str = QgsGrass::getInfo( "info", gisdbase, location, mapset, map, type );
+    QgsDebugMsg( str );
+    QStringList list = str.split( "\n" );
+    for ( int i = 0; i < list.size(); i++ ) {
+      QStringList keyVal = list[i].split(':');
+      if ( list[i].isEmpty() ) { continue; }
+      if ( keyVal.size() != 2 )
+      {
+        throw QgsGrass::Exception( "Cannot parse GRASS map info key value : " + list[i] + " (" + str + " ) " );
+      }
+      inf[keyVal[0]] = keyVal[1];
+    }
+  }
+  catch ( QgsGrass::Exception &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ),
+                          QObject::tr( "Cannot get map info" ) + "\n" + e.what() );
+  }
+  return inf; 
+}
+
 QMap<QString, QString> GRASS_EXPORT QgsGrass::query( QString gisdbase, QString location, QString mapset, QString map, MapType type, double x, double y )
 {
   QgsDebugMsg( QString( "gisdbase = %1 location = %2" ).arg( gisdbase ).arg( location ) );

Modified: branches/raster-providers/src/providers/grass/qgsgrass.h
===================================================================
--- branches/raster-providers/src/providers/grass/qgsgrass.h	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/providers/grass/qgsgrass.h	2010-11-05 07:28:20 UTC (rev 14511)
@@ -27,6 +27,7 @@
 #include "qgsexception.h"
 #include <QString>
 #include <QMap>
+#include <QHash>
 class QgsCoordinateReferenceSystem;
 class QgsRectangle;
 
@@ -188,6 +189,14 @@
     static GRASS_EXPORT QgsRectangle extent( QString gisdbase, QString location,
         QString mapset, QString map, MapType type = None );
 
+    // ! Get raster map size
+    static GRASS_EXPORT void size( QString gisdbase, QString location,
+        QString mapset, QString map, int *cols, int *rows );
+
+    // ! Get raster info
+    static GRASS_EXPORT QHash<QString, QString> info( QString gisdbase, QString location,
+        QString mapset, QString map, MapType type );
+
     // ! Get map value / feautre info
     static GRASS_EXPORT QMap<QString, QString> query( QString gisdbase, QString location,
         QString mapset, QString map, MapType type, double x, double y );

Modified: branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.cpp
===================================================================
--- branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.cpp	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.cpp	2010-11-05 07:28:20 UTC (rev 14511)
@@ -38,6 +38,7 @@
 #include <QDir>
 #include <QFileInfo>
 #include <QFile>
+#include <QHash>
 
 static QString PROVIDER_KEY = "grassraster";
 static QString PROVIDER_DESCRIPTION = "GRASS raster provider";
@@ -75,6 +76,15 @@
   QgsDebugMsg( QString( "mapName: %1" ).arg( mMapName ) );
 
   mCrs = QgsGrass::crs( mGisdbase, mLocation );
+
+  // the block size can change of course when the raster is overridden
+  // ibut it is only called once when statistics are calculated
+  QgsGrass::size( mGisdbase, mLocation, mMapset, mMapName, &mCols, &mRows );
+
+  mInfo = QgsGrass::info( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
+
+  mGrassDataType = mInfo["TYPE"].toInt();
+  QgsDebugMsg( "mGrassDataType = " + QString::number( mGrassDataType ) );
 }
 
 QgsGrassRasterProvider::~QgsGrassRasterProvider()
@@ -123,6 +133,114 @@
   return image;
 }
 
+
+void QgsGrassRasterProvider::readBlock( int bandNo, int xBlock, int yBlock, void *block )
+{
+  QgsDebugMsg( "Entered" );
+  // TODO: optimize, see extent()
+  
+  QgsDebugMsg( "yBlock = "  + QString::number( yBlock ) );
+
+  QStringList arguments;
+  arguments.append( "map=" +  mMapName + "@" + mMapset );
+
+  QgsRectangle ext = extent();
+
+  double cellHeight = ext.height() / mRows;
+  double yMaximum = ext.yMaximum() - cellHeight * yBlock;
+  double yMinimum = yMaximum - cellHeight;
+
+  arguments.append(( QString( "window=%1,%2,%3,%4,%5,%6" )
+                     .arg( ext.xMinimum() ).arg( yMinimum )
+                     .arg( ext.xMaximum() ).arg( yMaximum )
+                     .arg( mCols  ).arg( 1 ) ) );
+
+  arguments.append( "format=value");
+  QProcess process( this );
+  QString cmd = QgsApplication::prefixPath() + "/" QGIS_LIBEXEC_SUBDIR "/grass/modules/qgis.d.rast";
+  QByteArray data;
+  try
+  {
+    data = QgsGrass::runModule( mGisdbase, mLocation, cmd, arguments );
+  }
+  catch ( QgsGrass::Exception &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot draw raster" ) + "\n"
+                          + e.what() );
+
+    // We don't set mValid to false, because the raster can be recreated and work next time
+  }
+  QgsDebugMsg( QString( "%1 bytes read from modules stdout" ).arg( data.size() ) );
+  // byteCount() in Qt >= 4.6
+  //int size = image->byteCount() < data.size() ? image->byteCount() : data.size();
+  // TODO : data type size
+  int typeSize = 4;
+  int size = mCols * typeSize < data.size() ? mCols * typeSize : data.size();
+  memcpy( block, data.data(), size );
+}
+
+void QgsGrassRasterProvider::readBlock( int bandNo, QgsRectangle  const & viewExtent, int pixelWidth, int pixelHeight, void *block )
+{
+  QgsDebugMsg( "Entered" );
+  QgsDebugMsg( "pixelWidth = "  + QString::number( pixelWidth ) );
+  QgsDebugMsg( "pixelHeight = "  + QString::number( pixelHeight ) );
+  QgsDebugMsg( "viewExtent: " + viewExtent.toString() );
+
+  QImage *image = new QImage( pixelWidth, pixelHeight, QImage::Format_ARGB32 );
+  image->fill( QColor( Qt::gray ).rgb() );
+
+  QStringList arguments;
+  arguments.append( "map=" +  mMapName + "@" + mMapset );
+
+  arguments.append(( QString( "window=%1,%2,%3,%4,%5,%6" )
+                     .arg( viewExtent.xMinimum() ).arg( viewExtent.yMinimum() )
+                     .arg( viewExtent.xMaximum() ).arg( viewExtent.yMaximum() )
+                     .arg( pixelWidth ).arg( pixelHeight ) ) );
+  arguments.append( "format=value");
+  QProcess process( this );
+  QString cmd = QgsApplication::prefixPath() + "/" QGIS_LIBEXEC_SUBDIR "/grass/modules/qgis.d.rast";
+  QByteArray data;
+  try
+  {
+    data = QgsGrass::runModule( mGisdbase, mLocation, cmd, arguments );
+  }
+  catch ( QgsGrass::Exception &e )
+  {
+    QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot draw raster" ) + "\n"
+                          + e.what() );
+
+    // We don't set mValid to false, because the raster can be recreated and work next time
+    return;
+  }
+  QgsDebugMsg( QString( "%1 bytes read from modules stdout" ).arg( data.size() ) );
+  // byteCount() in Qt >= 4.6
+  //int size = image->byteCount() < data.size() ? image->byteCount() : data.size();
+  // TODO : data type size
+  int typeSize = 4;
+  int size = pixelWidth * pixelHeight * typeSize < data.size() ? pixelWidth * pixelHeight * typeSize : data.size();
+  memcpy( block, data.data(), size );
+}
+
+double  QgsGrassRasterProvider::noDataValue() const {
+  double nul;
+  if ( mGrassDataType == CELL_TYPE ) {
+    nul = -2147483647;
+  } else if ( mGrassDataType == DCELL_TYPE ) {
+    nul = 2.2250738585072014e-308;
+  } else if ( mGrassDataType == FCELL_TYPE ) {
+    nul = 1.17549435e-38F;
+  }
+  QgsDebugMsg( QString( "noDataValue = %1" ).arg( nul ) );
+  return nul;
+}
+
+double  QgsGrassRasterProvider::minimumValue( int bandNo ) const {
+  return mInfo["MIN_VALUE"].toDouble();
+}
+double  QgsGrassRasterProvider::maximumValue( int bandNo ) const {
+  return mInfo["MAX_VALUE"].toDouble();
+}
+
 QgsCoordinateReferenceSystem QgsGrassRasterProvider::crs()
 {
   QgsDebugMsg( "Entered" );
@@ -134,11 +252,19 @@
   // The extend can change of course so we get always fresh, to avoid running always the module
   // we should save mExtent and mLastModified and check if the map was modified
 
-  QgsRectangle rect;
-  rect = QgsGrass::extent( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
-  return rect;
+  mExtent = QgsGrass::extent( mGisdbase, mLocation, mMapset, mMapName, QgsGrass::Raster );
+  return mExtent;
 }
 
+// this is only called once when statistics are calculated
+int QgsGrassRasterProvider::xBlockSize() const { return mCols; } 
+int QgsGrassRasterProvider::yBlockSize() const { return 1; }
+
+// TODO this should be always refreshed if raster has changed ?
+// maybe also only for stats
+int QgsGrassRasterProvider::xSize() const { return mCols; } 
+int QgsGrassRasterProvider::ySize() const { return mRows; }
+
 bool QgsGrassRasterProvider::identify( const QgsPoint& thePoint, QMap<QString, QString>& theResults )
 {
   QgsDebugMsg( "Entered" );
@@ -149,10 +275,28 @@
 
 int QgsGrassRasterProvider::capabilities() const
 {
-  int capability = QgsRasterDataProvider::Identify;
+  int capability = QgsRasterDataProvider::Identify 
+                 | QgsRasterDataProvider::Data;
   return capability;
 }
 
+int QgsGrassRasterProvider::dataType( int bandNo ) const
+{
+  // TODO
+  return QgsRasterDataProvider::Int32;
+}
+
+int QgsGrassRasterProvider::bandCount() const
+{
+  // TODO
+  return 1;
+}
+
+int QgsGrassRasterProvider::colorInterpretation ( int bandNo ) const {
+  // TODO
+  return QgsRasterDataProvider::GrayIndex;
+}
+
 bool QgsGrassRasterProvider::isValid()
 {
   return mValid;

Modified: branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.h
===================================================================
--- branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.h	2010-11-05 07:26:04 UTC (rev 14510)
+++ branches/raster-providers/src/providers/grass/qgsgrassrasterprovider.h	2010-11-05 07:28:20 UTC (rev 14511)
@@ -21,6 +21,11 @@
 #ifndef QGSWMSPROVIDER_H
 #define QGSWMSPROVIDER_H
 
+extern "C"
+{
+#include <grass/gis.h>
+}
+
 #include "qgscoordinatereferencesystem.h"
 #include "qgsrasterdataprovider.h"
 #include "qgsrectangle.h"
@@ -171,6 +176,26 @@
       */
     int capabilities() const;
 
+    int dataType ( int bandNo ) const;
+
+    int bandCount() const;
+
+    int colorInterpretation ( int bandNo ) const;
+
+    int xBlockSize() const;
+    int yBlockSize() const;
+
+    int xSize() const;
+    int ySize() const;
+
+
+    void readBlock( int bandNo, int xBlock, int yBlock, void *data );
+    void readBlock( int bandNo, QgsRectangle  const & viewExtent, int width, int height,  void *data );
+
+    double noDataValue() const;
+    double minimumValue(int bandNo)const;
+    double maximumValue(int bandNo)const;
+
     /**
      * Get metadata in a format suitable for feeding directly
      * into a subset of the GUI raster properties "Metadata" tab.
@@ -196,7 +221,16 @@
     QString mMapset;        // map mapset
     QString mMapName;       // map name
 
+    RASTER_MAP_TYPE mGrassDataType; // CELL_TYPE, DCELL_TYPE, FCELL_TYPE
+
+    QgsRectangle mExtent;
+    int mCols;
+    int mRows;
+
+    QHash<QString, QString> mInfo;
+
     QgsCoordinateReferenceSystem mCrs;
+
 };
 
 #endif



More information about the QGIS-commit mailing list