Search code examples
syntax-highlightingimagemagickghostscriptopenoffice-writerenscript

Convert source code to syntax highlighted image


Background

OpenOffice Writer lacks the ability to link to an ASCII text source file, apply syntax highlighting, wrap it in a frame, and update the frame contents whenever the source file changes. However, OpenOffice Writer can link to images, and will update the images automatically when they change.

Problem

The images need to be high-resolution (300 dpi or greater) with syntax colouring appropriate for a white background (i.e., a printed page).

Question

How can high-quality images be created automatically from source code files, such as:

  • SQL;
  • PostgreSQL functions;
  • Java;
  • bash scripts; and
  • R and PL/R?

Attempts

Most attempts have been a variation on the following theme:

$ enscript --color -f Courier12 -B -1 --highlight=sql -h -o - source.sql |\
  convert - -trim -border 10 source.png

There are a few problems with this approach:

  1. The resolution is lacking (using -resample and -density offer no improvement).
  2. The syntax highlighting is unsuitable for a white page (can probably change enscript's colour theme).
  3. Using Courier100 produces several .png files, which would need to be stitched together.
  4. The -border 10 unexpectedly changes the background colour from white to lightgray.

Manual Solution

Converting the source files to PostScript -- avoiding ImageMagick altogether -- and then importing them into The GIMP will produce the desired results. Unfortunately, that solution involves a bit of manual work, and my GIMP batch programming experience is next to nil.


Solution

  • Software Requirements

    The following software packages are available for both Windows and Linux systems, and are required for a complete, working solution:

    • gvim - Used to export syntax highlighted source code to HTML.
    • moria - Colour scheme for syntax highlighting.
    • wkhtmltopdf - Converts HTML documents to PDF or PostScript (PS) documents.
    • Ghostscript - Used to convert PS to PNG.
    • ImageMagick - Used to trim the PNG and add a border.

    General Steps

    Here is how the solution works:

    1. Load the source code into an editor that can add splashes of colour.
    2. Export the source code as an HTML document (with embedded FONT tags).
    3. Convert the HTML document to a PS file.
    4. Convert the PS file to a PNG file.
    5. Trim the white border of the PNG and the overzealous source code border.
    6. Add a border around the image, using the same background colour as the HTML document.
    7. Delete temporary files.

    Installation

    Install the components into the following locations:

    • gvim - C:\Program Files\Vim
    • moria - C:\Program Files\Vim\vim73\colors
    • wkhtmltopdf - C:\Program Files\wkhtml
    • Ghostscript - C:\Program Files\gs
    • ImageMagick - C:\Program Files\ImageMagick

    Note: ImageMagick has a program called convert.exe, which cannot supersede the Windows convert command. Because of this, the full path to convert.exe must be hard-coded in the batch file (as opposed to adding ImageMagick to the PATH).

    Environment Variables

    Add or update the following environment variables:

    • GS_LIB = C:\Program Files\gs\gs9.00\lib
    • GS_PROG = C:\Program Files\gs\gs9.00\bin\gswin32.exe
    • PATH = "C:\Program Files\Vim\vim73";"C:\Program Files\wkhtml";"C:\Program Files\gs\gs9.00\bin"

    Batch File

    Here is the batch source text:

    @ECHO OFF
    
    ECHO Converting %1 to %1.html ...
    
    gvim -e %1 -c "set nobackup" -c ":colorscheme moria" -c :TOhtml -c wq -c :q
    
    ECHO Converting %1.html to %1.ps ...
    
    wkhtmltopdf --quiet --dpi 1200 %1.html %1.ps
    
    ECHO Converting %1.pdf to %1.png ...
    IF EXIST %1.png DEL /q %1.png
    
    gswin32 -q -dBATCH -dNOPAUSE -dSAFER -dNOPROMPT ^
     -sDEVICE=png16m -dDEVICEXRESOLUTION=600 -dDEVICEYRESOLUTION=600 ^
     -dDEVICEWIDTH=4958 -dDEVICEHEIGHT=7017 -dNOPLATFONTS ^
     -dTextAlphaBits=4 -sOutputFile=%1.png %1.ps
    
    ECHO Trimming %1.png ...
    
    move %1.png %1.orig.png
    
    "C:\Program Files\ImageMagick\convert.exe" -trim +repage -trim +repage ^
      -bordercolor "#f0f0f0" -border 25x25 %1.orig.png %1.png
    
    ECHO Removing old files ...
    IF EXIST %1.orig.png DEL /q %1.orig.png
    IF EXIST %1.html DEL /q %1.html
    IF EXIST %1.ps DEL /q %1.ps