Skip to content

Commit

Permalink
Add python composition checker and composermap test
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Aug 9, 2012
1 parent 6cfb060 commit f7ef19e
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 3 deletions.
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
@@ -1,3 +1,4 @@
INCLUDE(UsePythonTest)
ADD_PYTHON_TEST(PyQGisApp test_qgisapp.py)
ADD_PYTHON_TEST(PyQgsComposerMap test_qgscomposermap.py)
ADD_PYTHON_TEST(PyQgsGeometry test_qgsgeometry.py)
90 changes: 90 additions & 0 deletions tests/src/python/qgscompositionchecker.py
@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
'''
qgscompositionchecker.py - check rendering of Qgscomposition against an expected image
--------------------------------------
Date : 31 Juli 2012
Copyright : (C) 2012 by Dr. Horst Düster / Dr. Marco Hugentobler
email : horst.duester@sourcepole.ch
***************************************************************************
* *
* 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. *
* *
***************************************************************************/
'''
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *

class QgsCompositionChecker:

def testComposition(self, mTestName, mComposition, mExpectedImageFile, page=0 ):
if ( mComposition == None):
return false


#load expected image
expectedImage = QImage( mExpectedImageFile )

#get width/height, create image and render the composition to it
width = expectedImage.width();
height = expectedImage.height();
outputImage = QImage( QSize( width, height ), QImage.Format_ARGB32 )

mComposition.setPlotStyle( QgsComposition.Print )
outputImage.setDotsPerMeterX( expectedImage.dotsPerMeterX() )
outputImage.setDotsPerMeterY( expectedImage.dotsPerMeterX() )
outputImage.fill( 0 )
p = QPainter( outputImage )
mComposition.renderPage( p, page )
p.end()

renderedFilePath = QDir.tempPath() + QDir.separator() + QFileInfo( mExpectedImageFile ).baseName() + "_rendered_python.png"
outputImage.save( renderedFilePath, "PNG" )

diffFilePath = QDir.tempPath() + QDir.separator() + QFileInfo( mExpectedImageFile ).baseName() + "_diff_python.png"
testResult = self.compareImages( expectedImage, outputImage, diffFilePath )

# myDashMessage = "<DartMeasurementFile name=\"Rendered Image " + mTestName + "\"
# " type=\"image/png\">" + renderedFilePath +
# "</DartMeasurementFile>"
# "<DartMeasurementFile name=\"Expected Image " + mTestName + "\" type=\"image/png\">" +
# mExpectedImageFile + "</DartMeasurementFile>"
# "<DartMeasurementFile name=\"Difference Image " + mTestName + "\" type=\"image/png\">" +
# diffFilePath + "</DartMeasurementFile>"

return testResult

def compareImages( self, imgExpected, imgRendered, differenceImagePath ):

if ( imgExpected.width() != imgRendered.width() or imgExpected.height() != imgRendered.height() ):
return false

imageWidth = imgExpected.width()
imageHeight = imgExpected.height()
mismatchCount = 0

differenceImage = QImage( imageWidth, imageHeight, QImage.Format_ARGB32_Premultiplied )
differenceImage.fill( qRgb( 152, 219, 249 ) )

pixel1 = QColor().rgb()
pixel2 = QColor().rgb()
for i in range( imageHeight ):
for j in range( imageWidth ):
pixel1 = imgExpected.pixel( j, i )
pixel2 = imgRendered.pixel( j, i )
if ( pixel1 != pixel2 ):
mismatchCount = mismatchCount + 1
differenceImage.setPixel( j, i, qRgb( 255, 0, 0 ) )

if not differenceImagePath.isEmpty():
differenceImage.save( differenceImagePath, "PNG" )

#allow pixel deviation of 1 percent
pixelCount = imageWidth * imageHeight;
# print "MismatchCount: "+str(mismatchCount)
# print "PixelCount: "+str(pixelCount)
return (float(mismatchCount) / float(pixelCount) ) < 0.01

110 changes: 110 additions & 0 deletions tests/src/python/test_qgscomposermap.py
@@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
'''
test_qgscomposermap.py
--------------------------------------
Date : 31 Juli 2012
Copyright : (C) 2012 by Dr. Horst Düster / Dr. Marco Hugentobler
email : horst.duester@sourcepole.ch
***************************************************************************
* *
* 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. *
* *
***************************************************************************/
'''
import unittest
from utilities import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtXml import *
from qgis.core import *
from qgscompositionchecker import QgsCompositionChecker

QGISAPP, CANVAS, IFACE, PARENT = getQgisTestApp()

class TestQgsComposerMap(unittest.TestCase):

def testCase(self):
TEST_DATA_DIR = unitTestDataPath()
rasterFileInfo = QFileInfo(TEST_DATA_DIR+QDir().separator().toAscii()+"landsat.tif")
mRasterLayer = QgsRasterLayer(rasterFileInfo.filePath(), rasterFileInfo.completeBaseName())
rasterRenderer = QgsMultiBandColorRenderer( mRasterLayer.dataProvider(), 2, 3, 4 )
mRasterLayer.setRenderer( rasterRenderer )
QgsMapLayerRegistry.instance().addMapLayer( mRasterLayer )

# create composition with composer map
mMapRenderer = QgsMapRenderer()
layerStringList = QStringList()
layerStringList.append( mRasterLayer.id() )
mMapRenderer.setLayerSet( layerStringList )
mMapRenderer.setProjectionsEnabled( False )
mComposition = QgsComposition( mMapRenderer )
mComposition.setPaperSize( 297, 210 )
mComposerMap = QgsComposerMap( mComposition, 20, 20, 200, 100 )
mComposition.addComposerMap( mComposerMap )
self.grid(mComposerMap, mComposition, TEST_DATA_DIR)
self.overviewMap(mComposerMap, mComposition, TEST_DATA_DIR)

def grid(self, mComposerMap, mComposition, TEST_DATA_DIR):
mComposerMap.setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) )
mComposerMap.setGridEnabled( True )
mComposerMap.setGridIntervalX( 2000 )
mComposerMap.setGridIntervalY( 2000 )
mComposerMap.setShowGridAnnotation( True )
mComposerMap.setGridPenWidth( 0.5 )
mComposerMap.setGridAnnotationPrecision( 0 )
mComposerMap.setGridAnnotationPosition( QgsComposerMap.Disabled, QgsComposerMap.Left )
mComposerMap.setGridAnnotationPosition( QgsComposerMap.OutsideMapFrame, QgsComposerMap.Right )
mComposerMap.setGridAnnotationPosition( QgsComposerMap.Disabled, QgsComposerMap.Top )
mComposerMap.setGridAnnotationPosition( QgsComposerMap.OutsideMapFrame, QgsComposerMap.Bottom )
mComposerMap.setGridAnnotationDirection( QgsComposerMap.Horizontal, QgsComposerMap.Right )
mComposerMap.setGridAnnotationDirection( QgsComposerMap.Horizontal, QgsComposerMap.Bottom )
checker = QgsCompositionChecker()
testResult = checker.testComposition( "Composer map grid", mComposition, TEST_DATA_DIR + QDir().separator().toAscii() + "control_images" + QDir().separator().toAscii() + "expected_composermap" + QDir().separator().toAscii() + "composermap_landsat_grid.png" )
mComposerMap.setGridEnabled( False )
mComposerMap.setShowGridAnnotation( False )
mTestName = "gaga"
# myMessage = "<DartMeasurementFile name=\"Rendered Image " + mTestName + "\" type=\"image/png\">" + renderedFilePath + "</DartMeasurementFile> <DartMeasurementFile name=\"Expected Image " + mTestName + "\" type=\"image/png\">" + mExpectedImageFile + "</DartMeasurementFile> <DartMeasurementFile name=\"Difference Image " + mTestName + "\" type=\"image/png\">" + diffFilePath + "</DartMeasurementFile>"
assert testResult == True #, myMessage

def overviewMap(self, mComposerMap, mComposition, TEST_DATA_DIR):
overviewMap = QgsComposerMap( mComposition, 20, 130, 70, 70 )
mComposition.addComposerMap( overviewMap )
# zoom in
mComposerMap.setNewExtent( QgsRectangle( 785462.375, 3341423.125, 789262.375, 3343323.125 ) )
overviewMap.setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3350923.125 ) )
overviewMap.setOverviewFrameMap( mComposerMap.id() )
checker = QgsCompositionChecker()
testResult = checker.testComposition( "Composer map overview", mComposition, TEST_DATA_DIR + QDir().separator().toAscii() +"control_images" + QDir().separator().toAscii() + "expected_composermap" + QDir().separator().toAscii() + "composermap_landsat_overview.png" )
mComposition.removeComposerItem( overviewMap )
assert testResult == True


# def uniqueId(self, mComposerMap, mComposition):
# doc = QDomDocument()
# documentElement = doc.createElement( "ComposerItemClipboard" )
# mComposerMap.writeXML( documentElement, doc )
# mComposition.addItemsFromXML( documentElement, doc, 0, false )
#
# #test if both composer maps have different ids
# newMap = QgsComposerMap()
# mapList = mComposition.composerMapItems()
#
# for mapIt in mapList:
# if mapIt != mComposerMap:
# newMap = mapIt
# break
#
# oldId = mComposerMap.id()
# newId = newMap.id()
#
# mComposition.removeComposerItem( newMap );
# print "old: "+str(oldId)
# print "new "+str(newId)
# assert oldId != newId

if __name__ == '__main__':
unittest.main()

8 changes: 5 additions & 3 deletions tests/src/python/utilities.py
Expand Up @@ -106,12 +106,14 @@ def unitTestDataPath(theSubdir=None):
'hazard' or 'exposure'.
"""
myPath = __file__
tmpPath = os.path.split(os.path.dirname(myPath))
myPath = os.path.split(tmpPath[0])
if theSubdir is not None:
myPath = os.path.abspath(os.path.join(myPath,
'unit_test_data',
myPath = os.path.abspath(os.path.join(myPath[0],
'testdata',
theSubdir))
else:
myPath = os.path.abspath(os.path.join(myPath, 'unit_test_data'))
myPath = os.path.abspath(os.path.join(myPath[0], 'testdata'))
return myPath

def setCanvasCrs(theEpsgId, theOtfpFlag=False):
Expand Down

0 comments on commit f7ef19e

Please sign in to comment.