Merge pull request #1539 from mapycz/compositing

Image filters and compositing tests on New Zealand
This commit is contained in:
Dane Springmeyer 2012-10-16 11:27:30 -07:00
commit 3252233a42
58 changed files with 243 additions and 5 deletions

View file

@ -0,0 +1,49 @@
<Map srs="+proj=lonlat +ellps=WGS84 +datum=WGS84 +no_defs +over"
background-color="lightsteelblue">
<Style name="land">
<Rule>
<PolygonSymbolizer fill="darkslategrey" geometry-transform="translate(+1,+1)" />
<PolygonSymbolizer fill="lightcyan" geometry-transform="translate(-1,-1)" />
<PolygonSymbolizer fill="forestgreen" />
</Rule>
</Style>
<Style name="markers" comp-op="src-over">
<Rule>
<MarkersSymbolizer fill="saddlebrown"
fill-opacity="0.5"
stroke-width="0"
width="45 - 5 * [SCALERANK]"
height="45 - 5 * [SCALERANK]"
allow-overlap="true"
ignore-placement="true"
/>
<MarkersSymbolizer fill="white"
fill-opacity="0.7"
stroke-width="0"
width="5"
height="5"
allow-overlap="true"
ignore-placement="true"
/>
</Rule>
</Style>
<Layer name="land">
<StyleName>land</StyleName>
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">../shp/new_zealand/ne_50m_land.shp</Parameter>
</Datasource>
</Layer>
<Layer name="cities">
<StyleName>markers</StyleName>
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">../shp/new_zealand/ne_50m_populated_places_simple.shp</Parameter>
</Datasource>
</Layer>
</Map>

View file

@ -0,0 +1,68 @@
<Map srs="+proj=lonlat +ellps=WGS84 +datum=WGS84 +no_defs +over"
background-color="lightsteelblue">
<Style name="land">
<Rule>
<PolygonSymbolizer fill="darkslategrey" geometry-transform="translate(+1,+1)" />
<PolygonSymbolizer fill="lightcyan" geometry-transform="translate(-1,-1)" />
<PolygonSymbolizer fill="forestgreen" />
</Rule>
</Style>
<Style name="markers" comp-op="hard-light">
<Rule>
<MarkersSymbolizer fill="saddlebrown"
fill-opacity="0.5"
stroke-width="0"
width="45 - 5 * [SCALERANK]"
height="45 - 5 * [SCALERANK]"
allow-overlap="true"
ignore-placement="true"
/>
<MarkersSymbolizer fill="white"
fill-opacity="0.7"
stroke-width="0"
width="5"
height="5"
allow-overlap="true"
ignore-placement="true"
/>
</Rule>
</Style>
<Style name="labels" comp-op="overlay">
<Rule>
<TextSymbolizer face-name="DejaVu Sans Book"
size="12"
fill="black"
halo-fill="white"
halo-radius="2"
dx="7"
dy="1"
avoid-edges="true"
vertical-alignment="middle"
placement-type="simple"
placements="NE,NW"
allow-overlap="false"
>[NAME]</TextSymbolizer>
</Rule>
</Style>
<Layer name="land">
<StyleName>land</StyleName>
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">../shp/new_zealand/ne_50m_land.shp</Parameter>
</Datasource>
</Layer>
<Layer name="cities">
<StyleName>markers</StyleName>
<StyleName>labels</StyleName>
<Datasource>
<Parameter name="type">shape</Parameter>
<Parameter name="file">../shp/new_zealand/ne_50m_populated_places_simple.shp</Parameter>
</Datasource>
</Layer>
</Map>

Binary file not shown.

View file

@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.017453292519943295]]

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.017453292519943295]]

View file

@ -2,7 +2,8 @@
from nose.tools import *
import os,sys
from utilities import execution_path, Todo, get_unique_colors, pixel2channels
from utilities import execution_path, run_tests, Todo
from utilities import get_unique_colors, pixel2channels, side_by_side_image
import mapnik
def setup():
@ -20,6 +21,10 @@ def debug_image(image,step=2):
red,green,blue,alpha = pixel2channels(pixel)
print "rgba(%s,%s,%s,%s) at %s,%s" % (red,green,blue,alpha,x,y)
def replace_style(m, name, style):
m.remove_style(name)
m.append_style(name, style)
# note: it is impossible to know for all pixel colors
# we can only detect likely cases of non premultiplied colors
def validate_pixels_are_not_premultiplied(image):
@ -97,6 +102,8 @@ def test_compare_images():
successes.append(name)
else:
fails.append('failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected))
fail_im = side_by_side_image(expected_im, a)
fail_im.save('/tmp/mapnik-comp-op-test-' + name + '.fail.png')
eq_(len(successes),num_ops,'\n'+'\n'.join(fails))
b.demultiply()
# b will be slightly modified by pre and then de multiplication rounding errors
@ -142,6 +149,36 @@ def test_pre_multiply_status_of_map2():
mapnik.render(m,im)
eq_(validate_pixels_are_not_premultiplied(im),True)
def test_style_level_comp_op():
m = mapnik.Map(256, 256)
mapnik.load_map(m, '../data/good_maps/style_level_comp_op.xml')
m.zoom_all()
successes = []
fails = []
for name in mapnik.CompositeOp.names:
# find_style returns a copy of the style object
style_markers = m.find_style("markers")
style_markers.comp_op = getattr(mapnik.CompositeOp, name)
# replace the original style with the modified one
replace_style(m, "markers", style_markers)
im = mapnik.Image(m.width, m.height)
mapnik.render(m, im)
actual = '/tmp/mapnik-style-comp-op-' + name + '.png'
expected = 'images/style-comp-op/' + name + '.png'
im.save(actual)
if not os.path.exists(expected):
print 'generating expected test image: %s' % expected
im.save(expected)
expected_im = mapnik.Image.open(expected)
# compare them
if im.tostring() == expected_im.tostring():
successes.append(name)
else:
fails.append('failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected))
fail_im = side_by_side_image(expected_im, im)
fail_im.save('/tmp/mapnik-style-comp-op-' + name + '.fail.png')
eq_(len(fails), 0, '\n'+'\n'.join(fails))
def test_style_level_opacity():
m = mapnik.Map(512,512)
mapnik.load_map(m,'../data/good_maps/style_level_opacity_and_blur.xml')
@ -221,4 +258,4 @@ def test_background_image_with_alpha_and_background_color_against_composited_con
if __name__ == "__main__":
setup()
[eval(run)() for run in dir() if 'test_' in run]
run_tests(eval(x) for x in dir() if x.startswith("test_"))

View file

@ -1,7 +1,19 @@
#!/usr/bin/env python
from nose.tools import *
from utilities import execution_path, run_tests
from utilities import side_by_side_image
import os, mapnik
import re
def setup():
# All of the paths used are relative, if we run the tests
# from another directory we need to chdir()
os.chdir(execution_path('.'))
def replace_style(m, name, style):
m.remove_style(name)
m.append_style(name, style)
def test_append():
s = mapnik.Style()
@ -11,5 +23,45 @@ def test_append():
s.image_filters = 'sharpen'
eq_(s.image_filters,'sharpen')
def test_style_level_image_filter():
m = mapnik.Map(256, 256)
mapnik.load_map(m, '../data/good_maps/style_level_image_filter.xml')
m.zoom_all()
successes = []
fails = []
for name in ("", "agg-stack-blur(2,2)", "blur",
"edge-detect", "emboss", "gray", "invert",
"sharpen", "sobel", "x-gradient", "y-gradient"):
if name == "":
filename = "none"
else:
filename = re.sub(r"[^-_a-z.0-9]", "", name)
# find_style returns a copy of the style object
style_markers = m.find_style("markers")
style_markers.image_filters = name
style_labels = m.find_style("labels")
style_labels.image_filters = name
# replace the original style with the modified one
replace_style(m, "markers", style_markers)
replace_style(m, "labels", style_labels)
im = mapnik.Image(m.width, m.height)
mapnik.render(m, im)
actual = '/tmp/mapnik-style-image-filter-' + filename + '.png'
expected = 'images/style-image-filter/' + filename + '.png'
im.save(actual)
if not os.path.exists(expected):
print 'generating expected test image: %s' % expected
im.save(expected)
expected_im = mapnik.Image.open(expected)
# compare them
if im.tostring() == expected_im.tostring():
successes.append(name)
else:
fails.append('failed comparing actual (%s) and expected(%s)' % (actual,'tests/python_tests/'+ expected))
fail_im = side_by_side_image(expected_im, im)
fail_im.save('/tmp/mapnik-style-image-filter-' + filename + '.fail.png')
eq_(len(fails), 0, '\n'+'\n'.join(fails))
if __name__ == "__main__":
[eval(run)() for run in dir() if 'test_' in run]
setup()
run_tests(eval(x) for x in dir() if x.startswith("test_"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -140,7 +140,7 @@ def test_render_points():
p = mapnik.Projection(projs[projdescr])
m.zoom_to_box(p.forward(mapnik.Box2d(ul_lonlat,lr_lonlat)))
# Render to SVG so that it can be checked how many points are there with string comparison
svg_file = os.path.join(tempfile.gettempdir(),'%s.svg')
svg_file = os.path.join(tempfile.gettempdir(), 'mapnik-render-points-%s.svg' % projdescr)
mapnik.render_to_file(m, svg_file)
num_points_present = len(ds.all_features())
svg = open(svg_file,'r').read()

View file

@ -1,8 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
import os, sys, inspect
import os, sys, inspect, traceback
import mapnik
def execution_path(filename):
return os.path.join(os.path.dirname(sys._getframe(1).f_code.co_filename), filename)
@ -55,3 +57,31 @@ def get_unique_colors(im):
pixels.append(pixel)
pixels = sorted(pixels)
return map(pixel2rgba,pixels)
def run_tests(iterable):
failed = 0
for test in iterable:
try:
test()
sys.stderr.write("\x1b[32m✓ \x1b[m" + test.__name__ + "\x1b[m\n")
except:
exc_type, exc_value, exc_tb = sys.exc_info()
failed += 1
sys.stderr.write("\x1b[31m✘ \x1b[m" + test.__name__ + "\x1b[m\n")
for mline in traceback.format_exception_only(exc_type, exc_value):
for line in mline.rstrip().split("\n"):
sys.stderr.write(" \x1b[31m" + line + "\x1b[m\n")
sys.stderr.write(" Traceback:\n")
for mline in traceback.format_tb(exc_tb):
for line in mline.rstrip().split("\n"):
sys.stderr.write(" " + line + "\n")
sys.stderr.flush()
return failed
def side_by_side_image(left_im, right_im):
width = left_im.width() + 1 + right_im.width()
height = max(left_im.height(), right_im.height())
im = mapnik.Image(width, height)
im.blend(0, 0, left_im, 1.0)
im.blend(left_im.width() + 1, 0, right_im, 1.0)
return im