Images in Mokvino Web


Mokvino Web is a collection of scripts for GNU Awk, GNU Make and Mokvino which can be used to build and maintain websites.

Mokvino Web has several rules for converting between various image formats, including bitmaps and vector graphics. All you have to do is provide the source files in src/www/, and list what files you want of each type in Makefile. For example:

# In Makefile
JPEGS += animals/dog
JPEGS += animals/pig

PNGS += tools/bucket
PNGS += tools/spade
SVGS += logo

This indicates that you want the following files to be created:

  • pub/www/animals/dog.jpg
  • pub/www/animals/pig.jpg
  • pub/www/tools/bucket.png
  • pub/www/tools/spade.png
  • pub/www/logo.svg

Suppose you then provide the following:

  • src/www/animals/dog.jpg
  • src/www/animals/pig.png
  • src/www/tools/bucket.png
  • src/www/tools/spade.png
  • src/www/logo.svg

Then animals/dog.jpg, tools/bucket.png, tools/spade.png and logo.svg are created simply by copying from src/www/ to pub/www/. animals/pig.jpg will be converted from animals/pig.png.

Compressed SVG

If you have src/www/icons/foo.svg, and you want to create a compressed version of it in pub/www/icons/foo.svgz, you just have to list it as one to be compressed:

# In Makefile
SVGZS += icons/foo

If you're testing on a local filesystem, and your browser can't understand that foo.svgz is an SVG that needs to be decompressed first, you could disable compression for all SVGs using:

# In mysite-env.mk

SVG2SVGZ=cat
SVGZ_SUFFIX=.svg

Rasterizing SVGs

If you provide these files:

  • src/www/logo.dim
  • src/www/logo.svg

…and declare that you want a PNG image with the same basename:

# In Makefile
PNGS += logo

…then Mokvino Web will generate pub/www/logo.png from logo.svg as an image with dimensions specified in logo.dim. For example:

width=40
height=32

It's possible to leave out one of the dimensions to let it be computed by the rasterizer.

The conversion is performed by rasterizer, which is part of Batik, or by Inkscape, which is the default. You can change this by setting SVG2PNG=rasterizer.

There's an easily fixed bug in the Ubuntu package libbatik-java, if it reports java.lang.NoClassDefFoundError. Make sure that xmlgraphics-commons is included in the classpath unconditionally:

find_jars commons-logging commons-io xmlgraphics-commons

If you want to create large and small PNGs of a single SVG, define labels for each size using SCALES:

SCALES += big
SCALES += small

PNGS += $$(SCALES:%=icons/foo-%)

Then define dimensions for the labelled PNGs:

# In src/www/icons/foo-big.dim
width=32
height=32
# In src/www/icons/foo-small.dim
width=16
height=16

This works by copying the source SVG unchanged to var/www/icons/foo-small.svg and var/www/icons/foo-big.svg, from which the standard rules can convert to PNG.

If you want several images of the same scale to have the same dimensions, you can create the dimensions dynamically:

var/www/%-small.dim: src/small.dim
        cp --reflink=auto '$$<' '$$@'

Favicons

To create an image of type image/x-icon (as originally used for rel="shortcut icon") from SVG, simply list the unsuffixed name in ICOS, e.g.:

ICOS += icons/favicon

This uses predefined sizes ico16, ico32, and ico48, and creates dimensions for them automatically. By default, it uses Batik's rasterizer to convert SVG to PNG, as it preserves aspect ratio. Specify the following if you want to use Inkscape instead:

ICO_SVG2PNG=inkscape

Export of LibreOffice figures

Mokvino Web can convert ODG files into cropped PDFs using unoconv and pdfcrop. It also converts ODGs to SVGs (without backgrounds) using inkscape and xsltproc. If you specify any of these:

PDFS += figure1
SVGS += figure1
SVGZS += figure1

…and you provide src/www/figure1.odg, that will be enough to generate:

  • src/www/figure1.svg
  • src/www/figure1.svgz
  • src/www/figure1.pdf

Note that the output from unoconv can be disappointing for some features, like gradient fills. It also always fails for me the first time if LibreOffice is currently running, with the error Unable to connect or start own listener. On the second go, it converts the file that is open, rather than the file you specify. So I have to quit LibreOffice first.

Content negotiation of WebP images

Select which images should be available as WebPs. For example, if you want all PNGs and JPEGs to be available as WebPs:

WEBPS += $$(sort $$(PNGS) $$(JPEGS))

Instigate content negotiation on links to PNGs and JPEGs by unsetting their link suffixes:

JPEG_LNK_SUFFIX=
PNG_LNK_SUFFIX=

These are probably settings you only want to use in mysite-env.mk for your public installation.

You should also configure your web server to slightly prefer PNGs over WebPs, so that browsers that stupidly accept any image format won't get WebP by mistake:

AddType image/webp;qs=0.9 .webp