Originally published January 26, 2020 @ 2:50 pm

On occasion I find myself struggling posting code on discussion forums that don’t handle code formatting all that well. What would’ve helped is some quick and easy way to convert code to an image file with syntax highlighting. And so here it is.

The first step is to install some prerequisites. Note: as of the time of this writing (2021-01-14), Inkscape does not work on WSL Ubuntu 20, so get 18.

apt install inkscape python-pygments imagemagick python3-pygments

In the script below you can modify a few things: font face, font size, and image size. You can list the appropriate fonts available on your system like so:

fc-list | grep -i mono

The script itself needs to be executed this way:

# To convert a single file
code2png <file path and name> <output folder> <language> [<file extension>]
# To convert multiple files
code2png <input folder> <output folder> <language> <file extension>
# Examples
code2png /var/tmp/test01.sh /mnt/c/code_snippets bash
code2png /var/tmp /mnt/c/code_snippets bash sh

You can install the script from my GitHub repo like so:

d=/var/adm/bin && f=code2png && mkdir -p ${d} && curl -s0 -k https://raw.githubusercontent.com/igoros777/kw/master/${f}.sh > ${d}/${f}.sh && chmod 755 ${d}/${f}.sh && ln -s ${d}/${f}.sh /usr/bin/${f}

And the script itself is below.

  #!/bin/bash
  fmt=svg
  out=png
  lang=""
  ext=""
  wsize=1280
  source_path=""
  target_path=""
  if [ -z "${source_path}" ] || [ -z "${target_path}" ] || [ -z "${lang}" ]; then exit 1; fi
  if [ ! -f "${source_path}" ] && [ -z "${ext}" ]; then exit 3; fi
  if [ -f "${source_path}" ] && [ -z "${ext}" ]; then ext="*"; fi
  if [ ! -d "${target_path}" ]; then mkdir -p "${target_path}" || exit 2; fi
  find "${source_path}" -maxdepth 1 -mindepth 0 -type f -name "*\.${ext}" | while read f
  do
    pygmentize -O "style=monokai,fontface=DejaVu Sans Mono,fontsize=24" -f "${fmt}" \
    -l ${lang} -o "${target_path}/$(basename -- "${f%.*}").${fmt}" "${f}" 2>/dev/null
    inkscape -z -D --export-area-snap -b '#272822' -w ${wsize} \
    "${target_path}/$(basename -- "${f%.*}").${fmt}" \
    -e "${target_path}/$(basename -- "${f%.*}").${out}" 2>/dev/null
    mogrify -path "${target_path}" -bordercolor '#272822' -border 20 \
    -format png "${target_path}/$(basename -- "${f%.*}").${out}"
    /bin/rm "${target_path}/$(basename -- "${f%.*}").${fmt}" 2>/dev/null
  done

It’s a very simplistic version that begs for a rewrite. Alas, this was all the time I could spare. By all means, feel free to make improvements. Here are some output examples: