Skip to content

Commit

Permalink
Add unit test for composer map
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Jul 6, 2012
1 parent b0034b1 commit f6f4474
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 1 deletion.
4 changes: 3 additions & 1 deletion tests/src/core/CMakeLists.txt
@@ -1,5 +1,5 @@
# Standard includes and utils to compile into all tests.
SET (util_SRCS qgsrenderchecker.cpp)
SET (util_SRCS qgsrenderchecker.cpp qgscompositionchecker.cpp)


#####################################################
Expand All @@ -8,6 +8,7 @@ SET (util_SRCS qgsrenderchecker.cpp)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/src/core
${CMAKE_SOURCE_DIR}/src/core/composer
${CMAKE_SOURCE_DIR}/src/core/raster
${CMAKE_SOURCE_DIR}/src/core/renderer
${CMAKE_SOURCE_DIR}/src/core/symbology
Expand Down Expand Up @@ -96,3 +97,4 @@ ADD_QGIS_TEST(vectorlayertest testqgsvectorlayer.cpp)
ADD_QGIS_TEST(rulebasedrenderertest testqgsrulebasedrenderer.cpp)
ADD_QGIS_TEST(ziplayertest testziplayer.cpp)
ADD_QGIS_TEST(dataitemtest testqgsdataitem.cpp)
ADD_QGIS_TEST(composermaptest testqgscomposermap.cpp)
104 changes: 104 additions & 0 deletions tests/src/core/qgscompositionchecker.cpp
@@ -0,0 +1,104 @@
/***************************************************************************
qgscompositionchecker.cpp - check rendering of Qgscomposition against an expected image
--------------------------------------
Date : 5 Juli 2012
Copyright : (C) 2012 by Marco Hugentobler
email : marco@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. *
* *
***************************************************************************/

#include "qgscompositionchecker.h"
#include "qgscomposition.h"
#include <QImage>
#include <QPainter>

QgsCompositionChecker::QgsCompositionChecker( QgsComposition* composition, const QString& expectedImageFile ): mComposition( composition ), mExpectedImageFile( expectedImageFile )
{
}

QgsCompositionChecker::QgsCompositionChecker()
{
}

QgsCompositionChecker::~QgsCompositionChecker()
{
}

bool QgsCompositionChecker::testComposition()
{
if ( !mComposition )
{
return false;
}

#if 0 //fake mode to generate expected image
//assume 300 dpi and size of the control image 3507 * 2480
QImage outputImage( QSize( 3507, 2480 ), QImage::Format_ARGB32 );
mComposition->setPlotStyle( QgsComposition::Print );
outputImage.setDotsPerMeterX( 300 / 25.4 * 1000 );
outputImage.setDotsPerMeterY( 300 / 25.4 * 1000 );
outputImage.fill( 0 );
QPainter p( &outputImage );
QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
QRectF targetArea( 0, 0, 3507, 2480 );
mComposition->render( &p, targetArea, sourceArea );
p.end();
outputImage.save( "/tmp/composermap_control.png", "PNG" );
return false;
#endif //0

#if 1
//load expected image
QImage expectedImage( mExpectedImageFile );

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

mComposition->setPlotStyle( QgsComposition::Print );
outputImage.setDotsPerMeterX( expectedImage.dotsPerMeterX() /*mComposition->printResolution() / 25.4 * 1000*/ );
outputImage.setDotsPerMeterY( expectedImage.dotsPerMeterX() /*mComposition->printResolution() / 25.4 * 1000*/ );
outputImage.fill( 0 );
QPainter p( &outputImage );
QRectF sourceArea( 0, 0, mComposition->paperWidth(), mComposition->paperHeight() );
QRectF targetArea( 0, 0, width, height );
mComposition->render( &p, targetArea, sourceArea );
p.end();

return compareImages( expectedImage, outputImage );
#endif //0
}

bool QgsCompositionChecker::compareImages( const QImage& img1, const QImage& img2 ) const
{
if ( img1.width() != img2.width() || img1.height() != img2.height() )
{
return false;
}

int imageWidth = img1.width();
int imageHeight = img1.height();
int mismatchCount = 0;

QRgb pixel1, pixel2;
for ( int i = 0; i < imageHeight; ++i )
{
for ( int j = 0; j < imageWidth; ++j )
{
pixel1 = img1.pixel( j, i );
pixel2 = img2.pixel( j, i );
if ( pixel1 != pixel2 )
{
++mismatchCount;
}
}
}
return mismatchCount < 1;
}
40 changes: 40 additions & 0 deletions tests/src/core/qgscompositionchecker.h
@@ -0,0 +1,40 @@
/***************************************************************************
qgscompositionchecker.h - check rendering of Qgscomposition against an expected image
--------------------------------------
Date : 5 Juli 2012
Copyright : (C) 2012 by Marco Hugentobler
email : marco@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. *
* *
***************************************************************************/

#ifndef QGSCOMPOSITIONCHECKER_H
#define QGSCOMPOSITIONCHECKER_H

#include <QString>
class QgsComposition;
class QImage;

/**Renders a composition to an image and compares with an expected output*/
class QgsCompositionChecker
{
public:
QgsCompositionChecker( QgsComposition* composition, const QString& expectedImageFile );
~QgsCompositionChecker();

bool testComposition();

private:
QgsCompositionChecker(); //forbidden
bool compareImages( const QImage& img1, const QImage& img2 ) const;

QgsComposition* mComposition;
QString mExpectedImageFile;
};

#endif // QGSCOMPOSITIONCHECKER_H
91 changes: 91 additions & 0 deletions tests/src/core/testqgscomposermap.cpp
@@ -0,0 +1,91 @@
/***************************************************************************
testqgscomposermap.cpp
----------------------
begin : Juli 2012
copyright : (C) 2012 by Marco Hugentobler
email : marco at sourcepole dot 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. *
* *
***************************************************************************/

#include "qgsapplication.h"
#include "qgscomposition.h"
#include "qgscompositionchecker.h"
#include "qgscomposermap.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaprenderer.h"
#include "qgsrasterlayer.h"
#include <QObject>
#include <QtTest>

class TestQgsComposerMap: public QObject
{
Q_OBJECT;
private slots:
void initTestCase();// will be called before the first testfunction is executed.
void cleanupTestCase();// will be called after the last testfunction was executed.
void init();// will be called before each testfunction is executed.
void cleanup();// will be called after every testfunction.
void render(); //test if rendering of the composition with composr map is correct

private:
QgsComposition* mComposition;
QgsComposerMap* mComposerMap;
QgsMapRenderer* mMapRenderer;
QgsRasterLayer* mRasterLayer;
};

void TestQgsComposerMap::initTestCase()
{
QgsApplication::init( QString() );
QgsApplication::initQgis();

//create maplayers from testdata and add to layer registry
QFileInfo rasterFileInfo( QString( TEST_DATA_DIR ) + QDir::separator() + "landsat.tif" );
mRasterLayer = new QgsRasterLayer( rasterFileInfo.filePath(),
rasterFileInfo.completeBaseName() );
QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer*>() << mRasterLayer );

//create composition with composer map
mMapRenderer = new QgsMapRenderer();
mMapRenderer->setLayerSet( QStringList() << mRasterLayer->id() );
mMapRenderer->setProjectionsEnabled( false );
mComposition = new QgsComposition( mMapRenderer );
mComposition->setPaperSize( 297, 210 ); //A4 landscape
mComposerMap = new QgsComposerMap( mComposition, 20, 20, 200, 100 );
mComposition->addComposerMap( mComposerMap );
}

void TestQgsComposerMap::cleanupTestCase()
{
delete mComposition;
delete mMapRenderer;
}

void TestQgsComposerMap::init()
{

}

void TestQgsComposerMap::cleanup()
{

}

void TestQgsComposerMap::render()
{
mComposerMap->setNewExtent( QgsRectangle( 781662.375, 3339523.125, 793062.375, 3345223.125 ) );
QgsCompositionChecker checker( mComposition, QString( QString( TEST_DATA_DIR ) + QDir::separator() +
"control_images" + QDir::separator() + "composermap_landsat1.png" ) );
QVERIFY( checker.testComposition() );
}

QTEST_MAIN( TestQgsComposerMap )
#include "moc_testqgscomposermap.cxx"
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f6f4474

Please sign in to comment.