Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Icons: SVG and PNG, minimizing blur. #632

Closed
pnorman opened this issue Jun 15, 2014 · 12 comments
Closed

Icons: SVG and PNG, minimizing blur. #632

pnorman opened this issue Jun 15, 2014 · 12 comments

Comments

@pnorman
Copy link
Collaborator

pnorman commented Jun 15, 2014

I have a branch with a SVG icon for Parking, and it's showing what was a theoretical concern is one in practice

image
(Current master left, branch right, 1600%)

A properly done bitmap is clearer than a vector graphic, when at the resolution of the bitmap. This can seen here with the lower horizontal bar of the P having 3 pixels on the non-transparent version.

Are there techniques that we can use to minimize this? How did @samanpwbb handle PNG conversions in Maki?

The relevant SVG is

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100">
<path fill="none" stroke-width="14" stroke="#0092da" d="M 7,100 L 7,7 50,7 A 23,23 0 0,1 50,53 L 7,53" />
</svg>

and MSS is

    marker-file: url('symbols/parking.svg');
    marker-placement: interior;
    marker-height: 12;
@matthijsmelissen
Copy link
Collaborator

SVG versions of (most of) our icons can be found here: http://www.sjjb.co.uk/mapicons/contactsheet

@samanpwbb
Copy link

How did @samanpwbb handle PNG conversions in Maki?

We export PNGs from SVGs with Inkscape. Script to automate this is here: https://github.com/mapbox/maki/blob/mb-pages/render.sh

The only way to get crisp bitmaps from vector graphics is to design the source vectors with awareness of the pixel grid from the start, and then export them at exactly 100% size. Open up a few maki icons in Inkscape and enable the grid to see how this works (each square on the grid = 1 pixel:
screen shot 2014-06-15 at 2 45 24 pm

From https://github.com/mapbox/maki/tree/mb-pages/src.

@matthijsmelissen
Copy link
Collaborator

This is the automatic SVG-PNG conversion for 'our' images:
https://github.com/twain47/Open-SVG-Map-Icons/tree/master/tools

@hlaw
Copy link

hlaw commented Jun 16, 2014

If fonts are used in place of svg for the vector icons, hinting tools can be of help to attempt to align the glyph to whatever grid size it is rendered while keeping the shape, resulting in a sharper image.
Below is the svg imported into fontforge. Black outline is the original shape and the green one is automatically generated after autohinting (seems there are some bugs in displaying the green outline but they do not affect the result). Mapnik which includes opentype should support the rendering through the text symboliser.

screenshot from 2014-06-16 13 37 45

Another example (left one with hinting set up). The more complex shape requires some cleanup and tweaking within fontforge.
screenshot from 2014-06-16 13 50 07

@pnorman
Copy link
Collaborator Author

pnorman commented Jun 16, 2014

If fonts are used in place of svg for the vector icons

I thought about this long and hard. While probably superior in many ways, making the stylesheet depend on a custom font scares me, because we need to start worrying about non-system font directories.

@pnorman
Copy link
Collaborator Author

pnorman commented Jun 16, 2014

Tweaking the SVG to use pixel boundaries improves results, but still not quite as good as a PNG

image
PNG left, SVG right.

That the PNG is better is probably unavoidable. It was done by a more computationally intensive rescaling than is normal.

The real advantage to SVGs comes when using scale (e.g. in print). If it weren't for that, I wouldn't be bothering with this, although it is also nice to be able to do the SVG in black and set the colour in the MSS: pnorman@6491e9a#diff-5d9237083037cf1d6d91c329a0ff61adR175

png-scalesvg-scale

@hlaw
Copy link

hlaw commented Jun 16, 2014

The SVG version may perhaps be improved further by shifting the right stem of 'P' a little bit left, to fit within 2 pixels?

SVG has an attribute "shape-rendering:crispEdges" (https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering) which instructs the renderer to deal with exactly the same issue, but I think no browser or library support this fully (besides just turning off anti-aliasing).

making the stylesheet depend on a custom font scares me, because we need to start worrying about non-system font directories.

It may perhaps be useful to hack Mapnik to support something like marker-file: url('symbol/symbol.ttf#P');, and manage these font files separately without "polluting" the proper system / library fonts, given that it already has the rendering libraries needed.

@pnorman
Copy link
Collaborator Author

pnorman commented Jun 16, 2014

The SVG version may perhaps be improved further by shifting the right stem of 'P' a little bit left, to fit within 2 pixels?

I thought I was, but turned out to be slightly off. Adding a grid within SVG helped. This worked for a grid:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 9 12">
<path fill-rule="evenodd" d="M 0,0 L 0,12 1.75,12 1.75,7 6,7 A 3,3 0 0,0 6,0 Z M 1.75,1.75 L 1.75,5.25 6,5.25 A 1,1 0 0,0 6,1.75 Z"/>
<g>
<line id="hl" fill="none" stroke="red" stroke-width="0.05" x1="0" y1="0" x2="10" y2="0" />
<use xlink:href="#hl" transform="translate(0,1)"/>
<use xlink:href="#hl" transform="translate(0,2)"/>
<use xlink:href="#hl" transform="translate(0,3)"/>
<use xlink:href="#hl" transform="translate(0,4)"/>
<use xlink:href="#hl" transform="translate(0,5)"/>
<use xlink:href="#hl" transform="translate(0,6)"/>
<use xlink:href="#hl" transform="translate(0,7)"/>
<use xlink:href="#hl" transform="translate(0,8)"/>
<use xlink:href="#hl" transform="translate(0,9)"/>
<use xlink:href="#hl" transform="translate(0,10)"/>
<use xlink:href="#hl" transform="translate(0,11)"/>
<use xlink:href="#hl" transform="translate(0,12)"/>
</g>
<g>
<line id="vl" fill="none" stroke="red" stroke-width="0.05" x1="0" y1="0" x2="0" y2="12" />
<use xlink:href="#vl" transform="translate(1,0)"/>
<use xlink:href="#vl" transform="translate(2,0)"/>
<use xlink:href="#vl" transform="translate(3,0)"/>
<use xlink:href="#vl" transform="translate(4,0)"/>
<use xlink:href="#vl" transform="translate(5,0)"/>
<use xlink:href="#vl" transform="translate(6,0)"/>
<use xlink:href="#vl" transform="translate(7,0)"/>
<use xlink:href="#vl" transform="translate(8,0)"/>
<use xlink:href="#vl" transform="translate(9,0)"/>
<use xlink:href="#vl" transform="translate(10,0)"/>
</g>
</svg>

@pnorman
Copy link
Collaborator Author

pnorman commented Jun 16, 2014

With alignment fixes.

image

Still better as a PNG, but pretty damn close.

@hlaw
Copy link

hlaw commented Jun 16, 2014

I have tried shifting a bit to avoid anti-aliased pixels according to the grid. (The floating point can be rounded off if this is better).

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="0 0 9 12">
<path fill-rule="evenodd" d="m 0.07627119,0 0,12 1.74563801,0 0,-5 4.4323281,0 C 8.086833,7 8.9247252,5.4045048 8.9247252,3.5719092 8.9247252,1.7393135 8.086833,0 6.2542373,0 z m 1.74563801,1.75 0,3.5 4.4577518,0 C 7.1959589,5.25 7.4035395,4.488207 7.4035395,3.5719092 7.4035395,2.6556113 7.1959589,1.75 6.279661,1.75 z"/>
<g>
<line id="hl" fill="none" stroke="red" stroke-width="0.05" x1="0" y1="0" x2="10" y2="0" />
<use xlink:href="#hl" transform="translate(0,1)"/>
<use xlink:href="#hl" transform="translate(0,2)"/>
<use xlink:href="#hl" transform="translate(0,3)"/>
<use xlink:href="#hl" transform="translate(0,4)"/>
<use xlink:href="#hl" transform="translate(0,5)"/>
<use xlink:href="#hl" transform="translate(0,6)"/>
<use xlink:href="#hl" transform="translate(0,7)"/>
<use xlink:href="#hl" transform="translate(0,8)"/>
<use xlink:href="#hl" transform="translate(0,9)"/>
<use xlink:href="#hl" transform="translate(0,10)"/>
<use xlink:href="#hl" transform="translate(0,11)"/>
<use xlink:href="#hl" transform="translate(0,12)"/>
</g>
<g>
<line id="vl" fill="none" stroke="red" stroke-width="0.05" x1="0" y1="0" x2="0" y2="12" />
<use xlink:href="#vl" transform="translate(1,0)"/>
<use xlink:href="#vl" transform="translate(2,0)"/>
<use xlink:href="#vl" transform="translate(3,0)"/>
<use xlink:href="#vl" transform="translate(4,0)"/>
<use xlink:href="#vl" transform="translate(5,0)"/>
<use xlink:href="#vl" transform="translate(6,0)"/>
<use xlink:href="#vl" transform="translate(7,0)"/>
<use xlink:href="#vl" transform="translate(8,0)"/>
<use xlink:href="#vl" transform="translate(9,0)"/>
<use xlink:href="#vl" transform="translate(10,0)"/>
</g>
</svg>

@springmeyer
Copy link
Contributor

This issue may be of interest: mapnik/mapnik#1316

because we need to start worrying about non-system font directories.

You can use <Map font-directory="./local_fonts" /> which will be looked up relative to your XML location. (https://github.com/mapnik/mapnik/wiki/XMLConfigReference#map)

@matthijsmelissen
Copy link
Collaborator

This is implemented by #1165. Closing the current issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants