| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,220 @@ | ||
| /*************************************************************************** | ||
| qgsrasterdrawer.cpp | ||
| --------------------- | ||
| begin : June 2012 | ||
| copyright : (C) 2012 by Radim Blazek | ||
| email : radim dot blazek at gmail.com | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgslogger.h" | ||
| #include "qgsrasterdrawer.h" | ||
| //#include "qgsrasterresampler.h" | ||
| #include "qgsrasterprojector.h" | ||
| #include "qgsrastertransparency.h" | ||
| #include "qgsrasterviewport.h" | ||
| #include "qgsmaptopixel.h" | ||
|
|
||
| //resamplers | ||
| //#include "qgsbilinearrasterresampler.h" | ||
| //#include "qgscubicrasterresampler.h" | ||
|
|
||
| #include <QDomDocument> | ||
| #include <QDomElement> | ||
| #include <QImage> | ||
| #include <QPainter> | ||
|
|
||
| QgsRasterDrawer::QgsRasterDrawer( QgsRasterFace* input ): mInput( input ) | ||
| { | ||
| } | ||
|
|
||
| QgsRasterDrawer::~QgsRasterDrawer() | ||
| { | ||
| //remove remaining memory in partinfos | ||
| /* | ||
| QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.begin(); | ||
| for ( ; partIt != mRasterPartInfos.end(); ++partIt ) | ||
| { | ||
| CPLFree( partIt.value().data ); | ||
| } | ||
| */ | ||
| } | ||
|
|
||
| void QgsRasterDrawer::draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel ) | ||
| { | ||
| QgsDebugMsg( "Entered" ); | ||
| if ( !p || !mInput || !viewPort || !theQgsMapToPixel ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| // last pipe filter has only 1 band | ||
| int bandNumber = 0; | ||
| startRasterRead( bandNumber, viewPort, theQgsMapToPixel ); | ||
|
|
||
| //number of cols/rows in output pixels | ||
| int nCols = 0; | ||
| int nRows = 0; | ||
| //number of raster cols/rows with oversampling | ||
| //int nRasterCols = 0; | ||
| //int nRasterRows = 0; | ||
| //shift to top left point for the raster part | ||
| int topLeftCol = 0; | ||
| int topLeftRow = 0; | ||
|
|
||
| // We know that the output data type of last pipe filter is QImage data | ||
| //QgsRasterDataProvider::DataType rasterType = ( QgsRasterDataProvider::DataType )mProvider->dataType( mGrayBand ); | ||
|
|
||
| void* rasterData; | ||
|
|
||
| // readNextRasterPart calcs and resets nCols, nRows, topLeftCol, topLeftRow | ||
| while ( readNextRasterPart( bandNumber, viewPort, nCols, nRows, | ||
| &rasterData, topLeftCol, topLeftRow ) ) | ||
| { | ||
| //create image | ||
| //QImage img( nRasterCols, nRasterRows, QImage::Format_ARGB32_Premultiplied ); | ||
|
|
||
| // TODO: the exact format should be read from input | ||
| QImage img(( uchar * ) rasterData, nCols, nRows, QImage::Format_ARGB32_Premultiplied ); | ||
| drawImage( p, viewPort, img, topLeftCol, topLeftRow ); | ||
|
|
||
| // QImage does not delete data block passed to constructor | ||
| free( rasterData ); | ||
| } | ||
| } | ||
|
|
||
| void QgsRasterDrawer::startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel ) | ||
| { | ||
| if ( !viewPort || !mapToPixel || !mInput ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| //remove any previous part on that band | ||
| removePartInfo( bandNumber ); | ||
|
|
||
| //split raster into small portions if necessary | ||
| RasterPartInfo pInfo; | ||
| pInfo.nCols = viewPort->drawableAreaXDim; | ||
| pInfo.nRows = viewPort->drawableAreaYDim; | ||
|
|
||
| //effective oversampling factors are different to global one because of rounding | ||
| //oversamplingX = (( double )pInfo.nCols * oversampling ) / viewPort->drawableAreaXDim; | ||
| //oversamplingY = (( double )pInfo.nRows * oversampling ) / viewPort->drawableAreaYDim; | ||
|
|
||
| // TODO : we dont know oversampling (grid size) here - how to get totalMemoryUsage ? | ||
| //int totalMemoryUsage = pInfo.nCols * oversamplingX * pInfo.nRows * oversamplingY * mInput->dataTypeSize( bandNumber ); | ||
| int totalMemoryUsage = pInfo.nCols * pInfo.nRows * mInput->dataTypeSize( bandNumber ); | ||
| int parts = totalMemoryUsage / 100000000 + 1; | ||
| int nPartsPerDimension = sqrt( parts ); | ||
| pInfo.nColsPerPart = pInfo.nCols / nPartsPerDimension; | ||
| pInfo.nRowsPerPart = pInfo.nRows / nPartsPerDimension; | ||
| pInfo.currentCol = 0; | ||
| pInfo.currentRow = 0; | ||
| pInfo.data = 0; | ||
| pInfo.prj = 0; | ||
| mRasterPartInfos.insert( bandNumber, pInfo ); | ||
| } | ||
|
|
||
| bool QgsRasterDrawer::readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort, | ||
| int& nCols, int& nRows, void** rasterData, int& topLeftCol, int& topLeftRow ) | ||
| { | ||
| if ( !viewPort ) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| //get partinfo | ||
| QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber ); | ||
| if ( partIt == mRasterPartInfos.end() ) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| RasterPartInfo& pInfo = partIt.value(); | ||
|
|
||
| //remove last data block | ||
| // TODO: data are released somewhere else (check) | ||
| //free( pInfo.data ); | ||
| pInfo.data = 0; | ||
| delete pInfo.prj; | ||
| pInfo.prj = 0; | ||
|
|
||
| //already at end | ||
| if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow == pInfo.nRows ) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| //read data block | ||
| nCols = qMin( pInfo.nColsPerPart, pInfo.nCols - pInfo.currentCol ); | ||
| nRows = qMin( pInfo.nRowsPerPart, pInfo.nRows - pInfo.currentRow ); | ||
| int typeSize = mInput->dataTypeSize( bandNumber ) / 8; | ||
|
|
||
| //get subrectangle | ||
| QgsRectangle viewPortExtent = viewPort->mDrawnExtent; | ||
| double xmin = viewPortExtent.xMinimum() + pInfo.currentCol / ( double )pInfo.nCols * viewPortExtent.width(); | ||
| double xmax = viewPortExtent.xMinimum() + ( pInfo.currentCol + nCols ) / ( double )pInfo.nCols * viewPortExtent.width(); | ||
| double ymin = viewPortExtent.yMaximum() - ( pInfo.currentRow + nRows ) / ( double )pInfo.nRows * viewPortExtent.height(); | ||
| double ymax = viewPortExtent.yMaximum() - pInfo.currentRow / ( double )pInfo.nRows * viewPortExtent.height(); | ||
| QgsRectangle blockRect( xmin, ymin, xmax, ymax ); | ||
|
|
||
| pInfo.data = mInput->readBlock( bandNumber, blockRect, nCols, nRows ); | ||
|
|
||
| *rasterData = pInfo.data; | ||
| topLeftCol = pInfo.currentCol; | ||
| topLeftRow = pInfo.currentRow; | ||
|
|
||
| pInfo.currentCol += nCols; | ||
| if ( pInfo.currentCol == pInfo.nCols && pInfo.currentRow + nRows == pInfo.nRows ) //end of raster | ||
| { | ||
| pInfo.currentRow = pInfo.nRows; | ||
| } | ||
| else if ( pInfo.currentCol == pInfo.nCols ) //start new row | ||
| { | ||
| pInfo.currentCol = 0; | ||
| pInfo.currentRow += pInfo.nRowsPerPart; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| void QgsRasterDrawer::stopRasterRead( int bandNumber ) | ||
| { | ||
| removePartInfo( bandNumber ); | ||
| } | ||
|
|
||
| void QgsRasterDrawer::removePartInfo( int bandNumber ) | ||
| { | ||
| QMap<int, RasterPartInfo>::iterator partIt = mRasterPartInfos.find( bandNumber ); | ||
| if ( partIt != mRasterPartInfos.end() ) | ||
| { | ||
| RasterPartInfo& pInfo = partIt.value(); | ||
| //CPLFree( pInfo.data ); | ||
| free( pInfo.data ); | ||
| delete pInfo.prj; | ||
| mRasterPartInfos.remove( bandNumber ); | ||
| } | ||
| } | ||
|
|
||
| void QgsRasterDrawer::drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow ) const | ||
| { | ||
| if ( !p || !viewPort ) | ||
| { | ||
| return; | ||
| } | ||
|
|
||
| //top left position in device coords | ||
| QPoint tlPoint = QPoint( viewPort->topLeftPoint.x() + topLeftCol, viewPort->topLeftPoint.y() + topLeftRow ); | ||
|
|
||
| p->drawImage( tlPoint, img ); | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| /*************************************************************************** | ||
| qgsrasterdrawer.h | ||
| ------------------- | ||
| begin : June 2012 | ||
| copyright : (C) 2012 by Radim Blazek | ||
| email : radim dot blazek at gmail.com | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRASTERDRAWER_H | ||
| #define QGSRASTERDRAWER_H | ||
|
|
||
| //#include "qgsrasterdataprovider.h" | ||
| #include "qgsrasterface.h" | ||
|
|
||
| #include <QMap> | ||
|
|
||
| class QPainter; | ||
| class QImage; | ||
| class QgsMapToPixel; | ||
| class QgsRasterResampler; | ||
| class QgsRasterProjector; | ||
| class QgsRasterTransparency; | ||
| class QgsRasterViewPort; | ||
|
|
||
| class QDomElement; | ||
|
|
||
| class QgsRasterDrawer | ||
| { | ||
| public: | ||
| //Stores information about reading of a raster band. Columns and rows are in unsampled coordinates | ||
| struct RasterPartInfo | ||
| { | ||
| int currentCol; | ||
| int currentRow; | ||
| int nCols; | ||
| int nRows; | ||
| int nColsPerPart; | ||
| int nRowsPerPart; | ||
| void* data; //data (can be in oversampled/undersampled resolution) | ||
| QgsRasterProjector* prj; //raster projector (or 0 if no reprojection is done) | ||
| }; | ||
|
|
||
| QgsRasterDrawer( QgsRasterFace* input ); | ||
| ~QgsRasterDrawer(); | ||
|
|
||
| void draw( QPainter* p, QgsRasterViewPort* viewPort, const QgsMapToPixel* theQgsMapToPixel ); | ||
|
|
||
| protected: | ||
| //inline double readValue( void *data, QgsRasterFace::DataType type, int index ); | ||
|
|
||
| /**Start reading of raster band. Raster data can then be retrieved by calling readNextRasterPart until it returns false. | ||
| @param bandNumer number of raster band to read | ||
| @param viewPort describes raster position on screen | ||
| */ | ||
| void startRasterRead( int bandNumber, QgsRasterViewPort* viewPort, const QgsMapToPixel* mapToPixel ); | ||
| /**Fetches next part of raster data | ||
| @param nCols number of columns on output device | ||
| @param nRows number of rows on output device | ||
| @param nColsRaster number of raster columns (different to nCols if oversamplingX != 1.0) | ||
| @param nRowsRaster number of raster rows (different to nRows if oversamplingY != 0)*/ | ||
| //bool readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort, | ||
| // int& nCols, int& nRows, | ||
| // int& nColsRaster, int& nRowsRaster, | ||
| // void** rasterData, int& topLeftCol, int& topLeftRow ); | ||
| bool readNextRasterPart( int bandNumber, QgsRasterViewPort* viewPort, | ||
| int& nCols, int& nRows, | ||
| void** rasterData, | ||
| int& topLeftCol, int& topLeftRow ); | ||
| /**Draws raster part | ||
| @param topLeftCol Left position relative to left border of viewport | ||
| @param topLeftRow Top position relative to top border of viewport*/ | ||
| void drawImage( QPainter* p, QgsRasterViewPort* viewPort, const QImage& img, int topLeftCol, int topLeftRow ) const; | ||
| void stopRasterRead( int bandNumber ); | ||
|
|
||
| QgsRasterFace* mInput; | ||
| QMap<int, RasterPartInfo> mRasterPartInfos; | ||
|
|
||
| private: | ||
| /**Remove part into and release memory*/ | ||
| void removePartInfo( int bandNumer ); | ||
| }; | ||
| /* | ||
| inline double QgsRasterDrawer::readValue( void *data, QgsRasterFace::DataType type, int index ) | ||
| { | ||
| if ( !mProvider ) | ||
| { | ||
| return 0; | ||
| } | ||
| if ( !data ) | ||
| { | ||
| return mProvider->noDataValue(); | ||
| } | ||
| switch ( type ) | ||
| { | ||
| case QgsRasterFace::Byte: | ||
| return ( double )(( GByte * )data )[index]; | ||
| break; | ||
| case QgsRasterFace::UInt16: | ||
| return ( double )(( GUInt16 * )data )[index]; | ||
| break; | ||
| case QgsRasterFace::Int16: | ||
| return ( double )(( GInt16 * )data )[index]; | ||
| break; | ||
| case QgsRasterFace::UInt32: | ||
| return ( double )(( GUInt32 * )data )[index]; | ||
| break; | ||
| case QgsRasterFace::Int32: | ||
| return ( double )(( GInt32 * )data )[index]; | ||
| break; | ||
| case QgsRasterFace::Float32: | ||
| return ( double )(( float * )data )[index]; | ||
| break; | ||
| case QgsRasterFace::Float64: | ||
| return ( double )(( double * )data )[index]; | ||
| break; | ||
| default: | ||
| //QgsMessageLog::logMessage( tr( "GDAL data type %1 is not supported" ).arg( type ), tr( "Raster" ) ); | ||
| break; | ||
| } | ||
| return mProvider->noDataValue(); | ||
| } | ||
| */ | ||
|
|
||
| #endif // QGSRASTERDRAWER_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /*************************************************************************** | ||
| qgsrasterface.cpp - Internal raster processing modules interface | ||
| -------------------------------------- | ||
| Date : Jun 21, 2012 | ||
| Copyright : (C) 2012 by Radim Blazek | ||
| email : radim dot blazek at gmail dot com | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "qgsrasterface.h" | ||
| #include "qgslogger.h" | ||
|
|
||
| #include <QByteArray> | ||
|
|
||
| QgsRasterFace::QgsRasterFace( QgsRasterFace * input ): mInput( input ) | ||
| { | ||
| } | ||
|
|
||
| QgsRasterFace::~QgsRasterFace() | ||
| { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| /*************************************************************************** | ||
| qgsrasterface.h - Internal raster processing modules interface | ||
| -------------------------------------- | ||
| Date : Jun 21, 2012 | ||
| Copyright : (C) 2012 by Radim Blazek | ||
| email : radim dot blazek at gmail dot com | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef QGSRASTERFACE_H | ||
| #define QGSRASTERFACE_H | ||
|
|
||
| #include <QObject> | ||
|
|
||
| #include "qgsrectangle.h" | ||
|
|
||
| /** \ingroup core | ||
| * Base class for processing modules. | ||
| */ | ||
| // TODO: inherit from QObject? QgsRasterDataProvider inherits already from QObject | ||
| class CORE_EXPORT QgsRasterFace //: public QObject | ||
| { | ||
|
|
||
| //Q_OBJECT | ||
|
|
||
| public: | ||
|
|
||
| // TODO: This is copy of QgsRasterDataProvider::DataType, the QgsRasterDataProvider | ||
| // should use this DataType | ||
| // 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, | ||
| /*! Color, alpha, red, green, blue, 4 bytes */ ARGBDataType = 12, | ||
| TypeCount = 13 /* maximum type # + 1 */ | ||
| }; | ||
|
|
||
| int typeSize( 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; | ||
|
|
||
| case ARGBDataType: | ||
| return 32; | ||
|
|
||
| default: | ||
| return 0; | ||
| } | ||
| } | ||
| int dataTypeSize( int bandNo ) const | ||
| { | ||
| return typeSize( dataType( bandNo ) ); | ||
| } | ||
|
|
||
|
|
||
| QgsRasterFace( QgsRasterFace * input = 0 ); | ||
|
|
||
| virtual ~QgsRasterFace(); | ||
|
|
||
| /** Returns data type for the band specified by number */ | ||
| virtual int dataType( int bandNo ) const | ||
| { | ||
| return UnknownDataType; | ||
| } | ||
|
|
||
| // TODO | ||
| virtual double noDataValue() const { return 0; } | ||
|
|
||
| /** Read block of data using given extent and size. | ||
| * Returns pointer to data. | ||
| * Caller is responsible to free the memory returned. | ||
| */ | ||
| virtual void * readBlock( int bandNo, QgsRectangle const & extent, int width, int height ) | ||
| { | ||
| Q_UNUSED( bandNo ); Q_UNUSED( extent ); Q_UNUSED( width ); Q_UNUSED( height ); | ||
| return 0; | ||
| } | ||
|
|
||
| void setInput( QgsRasterFace* input ) { mInput = input; } | ||
|
|
||
| //protected: | ||
| // QgsRasterFace from used as input, data are read from it | ||
| QgsRasterFace* mInput; | ||
|
|
||
|
|
||
| }; | ||
|
|
||
| #endif | ||
|
|
||
|
|