| 1 | Screenshots for the README were generated by dumping X pixmaps in XPM format, |
| 2 | followed by conversion to GIF and integration into animated GIF using |
| 3 | ImageMagick. |
| 4 | |
| 5 | First, to generate an XPM screenshot on each frame, make the following code |
| 6 | modifications to `WolframAutomata.c`. |
| 7 | |
| 8 | Add to top of file: |
| 9 | |
| 10 | #include <X11/xpm.h> |
| 11 | |
| 12 | Add to `struct state`: |
| 13 | |
| 14 | int framenumber; |
| 15 | |
| 16 | In `WolframAutomata_init()`: |
| 17 | |
| 18 | state->framenumber = 0; |
| 19 | |
| 20 | In `WolframAutomata_draw()`, toward the end, right before returning: |
| 21 | |
| 22 | XWindowAttributes xgwa; |
| 23 | XGetWindowAttributes(state->dpy, state->win, &xgwa); |
| 24 | Pixmap temp = XCreatePixmap(state->dpy, state->win, state->dpy_width, state->dpy_height, xgwa.depth); |
| 25 | XCopyArea(state->dpy, state->evolution_history, temp, state->gc, 0, window_y_offset, state->dpy_width, state->dpy_height, 0, 0); |
| 26 | char * buffer = malloc(29); |
| 27 | snprintf(buffer, 29, "/tmp/wolfram-frame-%05d.xpm", state->framenumber); |
| 28 | XpmWriteFileFromPixmap(state->dpy, buffer, temp, 0, NULL); |
| 29 | state->framenumber++; |
| 30 | XFreePixmap(state->dpy, temp); |
| 31 | |
| 32 | Now recompile after adding `-lXpm` to the linker flags in the `Makefile`. |
| 33 | |
| 34 | Deleting every other frame had negligible visual impact, so all odd number |
| 35 | frames were deleted to shrink file size of the resulting animation. |
| 36 | |
| 37 | To convert all XPM files in a directory using ImageMagick's `convert`, use the |
| 38 | following bash snippet: |
| 39 | |
| 40 | for f in *.xpm ; do convert "$f" "${f%.xpm}.gif" ; done |
| 41 | |
| 42 | To combine GIFs into a single animated GIF, use the following command: |
| 43 | |
| 44 | convert -layers OptimizePlus -delay 10x600 wolfram-frame-*.gif -loop 0 wolfram.gif |
| 45 | |
| 46 | Check the ImageMagick manual for other `-layers` options. Some had significant |
| 47 | impact on filesize and the manual contains good descriptions of the algorithm |
| 48 | behind each. |
| 49 | |
| 50 | For setting the replay speed of the animated GIF, note that `-delay` is of the |
| 51 | form `ticks-per-frame x ticks-per-second`. For example, `10x600` is ten ticks |
| 52 | per frame and 600 ticks per second. |
| 53 | |
| 54 | Unlike what one might expact, `-loop 0` causes the animated GIF to loop and |
| 55 | `-loop 1` causes it to halt. |