3 minute read

Most graphics that we use in publications or reports are vector graphics, such as SVGs, PDFs, sometimes also WMFs, EMFs, EPSs, or PS files. It is often necessary to convert between them, most often between PDF and SVG. This can be done via Inkscape. Here I provide the little script vec2vec.sh, which does this in the terminal. It basically just executes Inkscape with the correct parameters.

All you have to do is to provide the path to the source vector graphics document and either the path to a destination document or the extension to convert. If you call vec2vec.sh mydoc.pdf svg, then it will create a file mydoc.svg. If you call vec2vec.sh mydoc.svg svg ../result.wmf, then it creates the document result.wmf in the parent folder of the current folder. As output format, the script additionall supports PNG, which is a raster graphic. For the input format PDF, you can additionally specify the optional argument flatten, in which case all text is rendered as vector graphics, which may help in some cases where font issues mess up the output.

The script will check if Inkscape is installed and abort if not. In that case, an appropriate error message is printed. You can install GhostScript via sudo apt-get install inkscape. The script will also fail with an error if either the input file does not exist or if the expected output file is not produced for some reason.

Here you can download this script and the complete collection of my personal scripts is available here. In that collection, there also is a script convertTo.sh, which bundles different conversion scripts between different formats. It decides based on the file extensions which scripts to use (or fails if no fitting script is available). Another related script is office2pdf.sh.

#!/bin/bash -

# Convert one vector graphic format to another.
# Supported input formats include svg, pdf, wmf, emf, eps, and ps.
# Supported output formats include svg, pdf, wmf, emf, eps, ps, and png.
#
# The script expects the following parameters:
# 1. The path to a source document.
# 2. Either a file extension or a path to a destination document.
#    The file extension will then be taken from that path.
# 3. Optional: For PDF input documents, you may specify "flatten", which
#              converts text to vector drawings. This may help in some
#              cases of corrupted output.
#
# This script is basically a wrapper around inkscape.
#
# strict error handling
set -o pipefail  # trace ERR through pipes
set -o errtrace  # trace ERR through 'time command' and other functions
set -o nounset   # set -u : exit the script if you try to use an uninitialized variable
set -o errexit   # set -e : exit the script if any statement returns a non-true return value

if [ $# -lt 2 ]; then
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Convert one vector graphics format to another."
    echo "Parameters:"
    echo " 1. path to the source file (svg, pdf, wmf, emf, eps, ps)"
    echo " 2. destination file extension OR path to destination document"
    echo " 3. OPTIONAL: 'flatten' for PDF sources to convert text to curves"
    exit 1
fi

if ! ( command -v inkscape &> /dev/null ); then
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Inkscape is not installed but needed."
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): You can install it via 'sudo apt-get install inkscape'."
    exit 1
fi

srcDocument="$(realpath "$1")"
srcExtension="${srcDocument##*.}"
if [ -f "$srcDocument" ]; then
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Got source document '$srcDocument' with file extension '$srcExtension'."
else
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Source document $srcDocument' does not exist."
    exit 1
fi

outSpec="$2"
dstExtension="${outSpec##*.}"
if [[ "$dstExtension" != "$outSpec" ]]; then
    dstDocument="$(realpath "$outSpec")"
else
    dstExtension="$outSpec"
    dstDocument="$(realpath "${srcDocument%.*}.$dstExtension")"
fi
echo "$(date +'%0Y-%0m-%0d %0R:%0S'): We will convert document '$srcDocument' to '$dstDocument'."

moreArgs="--export-type=$dstExtension --export-background-opacity=0.0 --export-area-page --vacuum-defs"
if [ "$srcExtension" == "pdf" ]; then
    if [ "$dstExtension" != "ps" ]; then
        moreArgs="$moreArgs --pdf-page=1"
    fi
fi
if [ "$dstExtension" == "pdf" ]; then
    moreArgs="$moreArgs --export-pdf-version=1.5"
elif [ "$dstExtension" == "svg" ]; then
    moreArgs="$moreArgs --export-plain-svg"
elif [ "$dstExtension" == "ps" ]; then
    moreArgs="$moreArgs --export-ps-level=3"
elif [ "$dstExtension" == "eps" ]; then
    moreArgs="$moreArgs --export-ps-level=3"
fi

if [ $# -gt 2 ]; then
    if [ "$3" == "flatten" ]; then
        if [ "$srcExtension" == "pdf" ]; then
            echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Try to flatten input PDF."
            moreArgs="${moreArgs} --pdf-poppler"
        else
            echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Flattening is only supported for PDF input."
        fi
    fi
fi

echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Now using Inkscape to convert '$srcDocument' to '$dstDocument' with arguments '$moreArgs'."
inkscape --export-filename="$dstDocument" $moreArgs "$srcDocument"

if [ -f "$dstDocument" ]; then
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Finished converting '$srcDocument' to '$dstDocument'."
else
    echo "$(date +'%0Y-%0m-%0d %0R:%0S'): Destination document '$dstDocument' was not created."
    exit 1
fi