Skip to main content

Haskell Diagrams GIF Animation

I am about ready to release LiterateX, and I have finally pushed the develop branch to GitHub!

GIF Animation

In the README, I include an animation that explains the project name much more elegantly than prose can. It replaces the “X” with a selection of supported languages, showing that the “X” is a variable name. LiterateX allows you to write literate source code for many languages.

LiterateX: LiterateBash, LiterateC, LiterateClojure, LiterateErlang, LiterateHaskell, LiterateIdris, LiterateJavaScript, LiteratePython, LiterateRacket, LiterateSQL, Literate…

Since LiterateX is a Haskell project, it makes sense to implement the animation in Haskell. I used the diagrams framework, using the diagrams-cairo backend to generate the GIF animation. The source code, available in the project/animation directory, is pretty concise.

animation :: [(Diagram B, Int)]
animation = (mkFrame "X", 300) : [(mkFrame lang, 50) | lang <- langs]
  where
    mkFrame :: String -> Diagram B
    mkFrame lang
      = baselineText ("Literate" ++ lang)
          # font "Noto Sans"
          # fontSizeL 0.5
          # fc black
          # translateX (-3)
          # translateY (-0.25)
      <> rect 6.5 1 # lw none # fc white # bg white

The mkFrame function creates a single frame in the animation, given the String to append to “Literate”. The background rectangle, white to match GitHub, has a height of 1 unit and a width of 6.5 units, which provides sufficient space for the text in all of the frames. The text is rendered in black with a font size of 0.5 units, making it easy to align left and center vertically using translation.

The animation function returns a list of frame and duration pairs. The animation displays “LiterateX” for 3 seconds followed by the text for each selected language for 0.5 seconds each.

Resolved Issues

Unfortunately, the diagrams-cairo backend does not have many options for the generated files. The default background is black, and I am unable to find a way to set a different background color. The white rectangle background in the diagram of each frame is aliased, resulting in gray lines at the top and bottom of the rendered GIF animation.

Unable to fix the issue on the Haskell side, I resorted to using an external program (Gifsicle) to crop the rendered GIF image. Since I am using an external program anyway, I was also able to reduce the number of colors in the image as well, greatly reducing the size of the image. (There are no color options, and the default use of the RGB color space is inappropriate for most diagrams the software is used to create!)

Nix

Currently, diagrams only works with old versions of GHC. I tried using it with Stack, but compilation failed on my system (with a C header file parsing error). Thankfully, I was able to avoid that problem by using Nix instead. All of the program dependencies are met thanks to pinning an appropriate nixpkgs revision and using cabal2nix.

It works fine on my system, but my current Nix derivation is not sufficient to make it work on other systems because it does not include dependencies that are not required by the program itself. The program makes use of the Noto Sans font (noto-fonts), Gifsicle (gifsicle) is used processing the rendered GIF image, and GNU Make is (optionally) used as well.

While I know how to specify such dependencies in other types of Nix derivations, I am not sure how it should be done in the style of Nix derivation that I am using. I do not have time to get sidetracked by this issue now… I will research it later, or perhaps a friend will point me in the right direction!

Author

Travis Cardwell

Published

Tags