diff --git a/CMakeLists.txt b/CMakeLists.txt index 257bb280bae..7de2c60eeaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -559,6 +559,12 @@ ADD_CUSTOM_TARGET(version ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/qgsversion.h) ############################################################# # process subdirs +#create a variable to specify where our test data is +#so that unit tests can use TEST_DATA_DIR to locate +#the test data. See CMakeLists in test dirs for more info +#TEST_DATA_DIR is also used by QgsRenderChecker currently in core +SET (TEST_DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/testdata") + ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(doc) ADD_SUBDIRECTORY(images) @@ -570,10 +576,6 @@ IF (WITH_BINDINGS) ENDIF (WITH_BINDINGS) IF (ENABLE_TESTS) - #create a variable to specify where our test data is - #so that unit tests can use TEST_DATA_DIR to locate - #the test data. See CMakeLists in test dirs for more info - SET (TEST_DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/testdata") ADD_SUBDIRECTORY(tests) SET (CTEST_BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/output/bin" ) MESSAGE (STATUS "Ctest Binary Directory set to: ${CTEST_BINARY_DIRECTORY}") diff --git a/python/core/core.sip b/python/core/core.sip index 3a4eb6e6e0d..ef254911ee3 100644 --- a/python/core/core.sip +++ b/python/core/core.sip @@ -75,6 +75,7 @@ %Include qgsrectangle.sip %Include qgsrendercontext.sip %Include qgsrenderer.sip +%Include qgsrenderchecker.sip %Include qgsrunprocess.sip %Include qgsscalecalculator.sip %Include qgssinglesymbolrenderer.sip diff --git a/python/core/qgsrasterlayer.sip b/python/core/qgsrasterlayer.sip index 57ebe0b7360..97d446394b8 100644 --- a/python/core/qgsrasterlayer.sip +++ b/python/core/qgsrasterlayer.sip @@ -81,6 +81,15 @@ public: Multiband } ; + /** \brief Contrast enhancement limits */ + enum ContrastEnhancementLimits + { + ContrastEnhancementNone, + ContrastEnhancementMinMax, + ContrastEnhancementStdDev, + ContrastEnhancementCumulativeCut + }; + /** \brief A list containing on ContrastEnhancement object per raster band in this raster layer */ typedef QList ContrastEnhancementList; diff --git a/python/core/qgsrenderchecker.sip b/python/core/qgsrenderchecker.sip new file mode 100644 index 00000000000..cdc4826d0ff --- /dev/null +++ b/python/core/qgsrenderchecker.sip @@ -0,0 +1,43 @@ + +/** Render checker for tests in python */ + +class QgsRenderChecker +{ +%TypeHeaderCode +#include +%End + public: + + QgsRenderChecker(); + + ~QgsRenderChecker(); + + QString controlImagePath() const; + + QString report(); + + float matchPercent(); + + unsigned int mismatchCount(); + + unsigned int matchTarget(); + + int elapsedTime(); + + void setControlName( const QString theName ); + + void setControlPathPrefix( const QString theName ); + + QString imageToHash( QString theImageFile ); + + void setRenderedImage( QString theImageFileName ); + + void setMapRenderer( QgsMapRenderer * thepMapRenderer ); + + bool runTest( QString theTestName, unsigned int theMismatchCount = 0 ); + + bool compareImages( QString theTestName, unsigned int theMismatchCount = 0, QString theRenderedImageFile = "" ); + + bool isKnownAnomaly( QString theDiffImageFile ); +}; + diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c5ed76bd64a..7e2c4b31b24 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -96,6 +96,7 @@ SET(QGIS_CORE_SRCS qgsrasterprojector.cpp qgsrasterdataprovider.cpp qgsrendercontext.cpp + qgsrenderchecker.cpp qgsrectangle.cpp qgsrunprocess.cpp qgsscalecalculator.cpp @@ -376,6 +377,7 @@ SET(QGIS_CORE_HDRS qgsrasterdataprovider.h qgsrectangle.h qgsrendercontext.h + qgsrenderchecker.h qgsrunprocess.h qgsscalecalculator.h qgssnapper.h @@ -492,6 +494,9 @@ ELSE (WIN32) ADD_DEFINITIONS("-D_HAVE_PTHREAD_") ENDIF (WIN32) +# Test data dir for QgsRenderChecker +ADD_DEFINITIONS(-DTEST_DATA_DIR="\\"${TEST_DATA_DIR}\\"") + ############################################################# # qgis_core library @@ -581,3 +586,4 @@ IF (APPLE AND QGIS_MACAPP_INSTALL_DEV) INSTALL(TARGETS qgis_core FRAMEWORK DESTINATION ${QGIS_MACAPP_DEV_PREFIX}) INSTALL(CODE "EXECUTE_PROCESS(COMMAND install_name_tool -id \"${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/Versions/${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}/qgis_core\" \"$ENV{DESTDIR}${QGIS_MACAPP_DEV_PREFIX}/qgis_core.framework/qgis_core\")") ENDIF (APPLE AND QGIS_MACAPP_INSTALL_DEV) + diff --git a/tests/src/core/qgsrenderchecker.cpp b/src/core/qgsrenderchecker.cpp similarity index 100% rename from tests/src/core/qgsrenderchecker.cpp rename to src/core/qgsrenderchecker.cpp diff --git a/tests/src/core/qgsrenderchecker.h b/src/core/qgsrenderchecker.h similarity index 100% rename from tests/src/core/qgsrenderchecker.h rename to src/core/qgsrenderchecker.h diff --git a/tests/src/analysis/CMakeLists.txt b/tests/src/analysis/CMakeLists.txt index 5e6d4548ef3..98c9018b20e 100644 --- a/tests/src/analysis/CMakeLists.txt +++ b/tests/src/analysis/CMakeLists.txt @@ -1,5 +1,5 @@ # Standard includes and utils to compile into all tests. -SET (util_SRCS ../core/qgsrenderchecker.cpp) +SET (util_SRCS) ##################################################### diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt index 69173d9f2ff..4d42bde4737 100644 --- a/tests/src/core/CMakeLists.txt +++ b/tests/src/core/CMakeLists.txt @@ -1,5 +1,5 @@ # Standard includes and utils to compile into all tests. -SET (util_SRCS qgsrenderchecker.cpp qgscompositionchecker.cpp) +SET (util_SRCS qgscompositionchecker.cpp) ##################################################### diff --git a/tests/src/core/testqgsrasterlayer.cpp b/tests/src/core/testqgsrasterlayer.cpp index b5b73934ef2..4ce0ab7cbc0 100644 --- a/tests/src/core/testqgsrasterlayer.cpp +++ b/tests/src/core/testqgsrasterlayer.cpp @@ -114,7 +114,7 @@ void TestQgsRasterLayer::initTestCase() QFileInfo myFloat32RasterFileInfo( myFloat32FileName ); mpFloat32RasterLayer = new QgsRasterLayer( myFloat32RasterFileInfo.filePath(), - myFloat32RasterFileInfo.completeBaseName() ); + myFloat32RasterFileInfo.completeBaseName() ); qDebug() << "float32raster metadata: " << mpFloat32RasterLayer->dataProvider()->metadata(); // Register the layer with the registry @@ -443,10 +443,13 @@ bool TestQgsRasterLayer::setQml( QString theType ) void TestQgsRasterLayer::transparency() { QVERIFY( mpFloat32RasterLayer->isValid() ); - QgsSingleBandGrayRenderer* r = new QgsSingleBandGrayRenderer( mpRasterLayer->dataProvider(), 1 ); - mpFloat32RasterLayer->setRenderer( r ); + QgsSingleBandGrayRenderer* renderer = new QgsSingleBandGrayRenderer( mpRasterLayer->dataProvider(), 1 ); + mpFloat32RasterLayer->setRenderer( renderer ); mpFloat32RasterLayer->setContrastEnhancementAlgorithm( QgsContrastEnhancement::StretchToMinimumMaximum, QgsRasterLayer::ContrastEnhancementMinMax ); + qDebug( "contrastEnhancement.minimumValue = %.17g", renderer->contrastEnhancement()->minimumValue() ); + qDebug( "contrastEnhancement.maximumValue = %.17g", renderer->contrastEnhancement()->maximumValue() ); + QList myTransparentSingleValuePixelList; QgsRasterTransparency* rasterTransparency = new QgsRasterTransparency(); QgsRasterTransparency::TransparentSingleValuePixel myTransparentPixel; @@ -470,7 +473,7 @@ void TestQgsRasterLayer::transparency() QStringList myLayers; myLayers << mpFloat32RasterLayer->id(); mpMapRenderer->setLayerSet( myLayers ); - + mpMapRenderer->setExtent( mpFloat32RasterLayer->extent() ); QVERIFY( render( "raster_transparency" ) ); } diff --git a/tests/src/gui/CMakeLists.txt b/tests/src/gui/CMakeLists.txt index 8b641a167d8..118d9c3a170 100644 --- a/tests/src/gui/CMakeLists.txt +++ b/tests/src/gui/CMakeLists.txt @@ -1,5 +1,5 @@ # Standard includes and utils to compile into all tests. -SET (util_SRCS ../core/qgsrenderchecker.cpp) +SET (util_SRCS) ##################################################### diff --git a/tests/src/python/test_qgsrasterlayer.py b/tests/src/python/test_qgsrasterlayer.py index b274d941b44..055498cde19 100644 --- a/tests/src/python/test_qgsrasterlayer.py +++ b/tests/src/python/test_qgsrasterlayer.py @@ -1,8 +1,8 @@ import os import unittest -from qgis.core import QgsRasterLayer, QgsPoint -from PyQt4.QtCore import QFileInfo, QString +from qgis.core import QgsRasterLayer, QgsPoint, QgsMapLayerRegistry, QgsMapRenderer, QgsSingleBandGrayRenderer, QgsContrastEnhancement, QgsRasterTransparency, QgsRenderChecker +from PyQt4.QtCore import QFileInfo, QString, QStringList # Convenience instances in case you may need them # not used in this test @@ -40,6 +40,69 @@ class TestQgsRasterLayer(unittest.TestCase): myMessage = 'Expected: %s\nGot: %s' % (myValues, myExpectedValues) self.assertEquals(myValues, myExpectedValues, myMessage) + def testTransparency(self): + myPath = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'testdata', 'raster', 'band1_float32_noct_epsg4326.tif')) + myFileInfo = QFileInfo(myPath) + myBaseName = myFileInfo.baseName() + myRasterLayer = QgsRasterLayer(myPath, myBaseName) + myMessage = 'Raster not loaded: %s' % myPath + assert myRasterLayer.isValid(), myMessage + + renderer = QgsSingleBandGrayRenderer( myRasterLayer.dataProvider(), 1 ); + myRasterLayer.setRenderer( renderer ); + myRasterLayer.setContrastEnhancementAlgorithm( QgsContrastEnhancement.StretchToMinimumMaximum, QgsRasterLayer.ContrastEnhancementMinMax ); + + myContrastEnhancement = myRasterLayer.renderer().contrastEnhancement() + #print "myContrastEnhancement.minimumValue = %.17g" % myContrastEnhancement.minimumValue() + #print "myContrastEnhancement.maximumValue = %.17g" % myContrastEnhancement.maximumValue() + + # Unfortunately the minimum/maximum values calculated in C++ and Python + # are slightely different (e.g. 3.3999999521443642e+38 x 3.3999999521444001e+38) + # It is not clear where the precision is lost. We set the same values as C++. + myContrastEnhancement.setMinimumValue( -3.3319999287625854e+38 ) + myContrastEnhancement.setMaximumValue( 3.3999999521443642e+38 ) + #myType = myRasterLayer.dataProvider().dataType( 1 ); + #myEnhancement = QgsContrastEnhancement( myType ); + + + + myTransparentSingleValuePixelList = [] + rasterTransparency = QgsRasterTransparency() + + myTransparentPixel1 = QgsRasterTransparency.TransparentSingleValuePixel() + myTransparentPixel1.min = -2.5840000772112106e+38 + myTransparentPixel1.max = -1.0879999684602689e+38 + myTransparentPixel1.percentTransparent = 50 + myTransparentSingleValuePixelList.append( myTransparentPixel1 ) + + myTransparentPixel2 = QgsRasterTransparency.TransparentSingleValuePixel() + myTransparentPixel2.min = 1.359999960575336e+37 + myTransparentPixel2.max = 9.520000231087593e+37 + myTransparentPixel2.percentTransparent = 70 + myTransparentSingleValuePixelList.append( myTransparentPixel2 ) + + rasterTransparency.setTransparentSingleValuePixelList( myTransparentSingleValuePixelList ) + + rasterRenderer = myRasterLayer.renderer() + assert rasterRenderer + + rasterRenderer.setRasterTransparency( rasterTransparency ) + + QgsMapLayerRegistry.instance().addMapLayers( [ myRasterLayer, ] ) + + myMapRenderer = QgsMapRenderer() + + myLayers = QStringList() + myLayers.append( myRasterLayer.id() ) + myMapRenderer.setLayerSet( myLayers ) + myMapRenderer.setExtent( myRasterLayer.extent() ) + + myChecker = QgsRenderChecker() + myChecker.setControlName( "expected_raster_transparency" ) + myChecker.setMapRenderer( myMapRenderer ) + + myResultFlag = myChecker.runTest( "raster_transparency_python" ); + assert myResultFlag, "Raster transparency rendering test failed" if __name__ == '__main__': unittest.main() diff --git a/tests/testdata/raster/band1_float32_noct_epsg4326.tif.aux.xml b/tests/testdata/raster/band1_float32_noct_epsg4326.tif.aux.xml index 009f2c59fde..59865f4aa44 100644 --- a/tests/testdata/raster/band1_float32_noct_epsg4326.tif.aux.xml +++ b/tests/testdata/raster/band1_float32_noct_epsg4326.tif.aux.xml @@ -1,5 +1,15 @@ + + + -3.365659928167135e+38 + 3.433659951548935e+38 + 100 + 0 + 0 + 1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1|0|0|0|0|0|0|0|0|0|0|1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1|1|1|0|1|1|1|1|1|1|1 + + 0.000000e+00 0.000000e+00 255 127 0 255 127 0 1