Home / Alt manpages / ppmforge(1)

  • ppmforge(1)
  • User command
  • linux

Generate Repeatable Fractal Planets and Skies with ppmforge

ppmforge renders fractal planets, cloud textures and star fields as PPM files, all from the same random-terrain engine. This guide makes a repeatable render with an explicit seed, checks the actual dimensions rather than trusting the request, and shows how to scale a scene up without changing it. Allow about fifteen minutes for a first run, including time to inspect the output.

You need a shell, the Netpbm package and a directory where you can write temporary images. These commands need no elevated privileges: do not run the generator as root merely to write an image, choose a directory you own instead.

1. Check the installed command

Confirm which binary will run and record the package version. This is a read-only checkpoint, and it also protects you from comparing results produced by a different Netpbm build:

$ command -v ppmforge
/usr/bin/ppmforge
$ ppmforge -version 2>&1 | sed -n '1,2p'
ppmforge: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
ppmforge: Built from source dated 2024-03-31 09:09:47
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1

The manual says options may be abbreviated to the shortest unique prefix. Use full option names in scripts: they make the intended settings easier to review, and they survive additions to the command's option list later.

2. Make a small cloud image first

Start small, with an explicit seed. -clouds selects the cloud renderer, -seed makes the result repeatable, and a small size and mesh keep this first test quick:

$ ppmforge -clouds -seed 123 -width 256 -height 192 -mesh 64 \
    > /tmp/ppmforge-clouds.ppm
ppmforge: clouds: -seed 123 -dimension 2.15 -power 0.75 -mesh 64
$ file /tmp/ppmforge-clouds.ppm
/tmp/ppmforge-clouds.ppm: Netpbm image data, size 256 x 192, rawbits, pixmap

The height here is lower than the width, which is a valid rectangular image; the installed command preserves those dimensions, and the manual requires an even width. Verify the actual result rather than trusting a graphical preview: on this build, treat a direct header check as the authoritative test.

$ od -An -c -N 20 /tmp/ppmforge-clouds.ppm
   P   6  \n   2   5   6       1   9   2  \n   2   5   5  \n

PPM pixel data is binary, so do not open the whole file in a text editor. The first three lines are the header: P6 means raw colour data, followed by width, height and maximum channel value.

Checkpoint

You have a non-empty PPM and have checked its actual header. Keep this file until the larger render has been inspected too.

3. Choose the image type deliberately

Without a type option, ppmforge generates a planet. Use -clouds for a cloud texture or -night for a frame full of stars. The same seed and dimensions do not make those modes equivalent: the selected renderer changes the image entirely.

$ ppmforge -night -seed 123 -width 256 -height 256 -mesh 64 \
    > /tmp/ppmforge-night.ppm
ppmforge: night: -seed 123 -stars 100 -saturation 125.
$ od -An -c -N 20 /tmp/ppmforge-night.ppm
   P   6  \n   2   5   6       2   5   6  \n   2   5   5  \n

Night images use -saturation to control the colour variation of stars, defaulting to 125.

  • Set -saturation 0 for uncoloured stars and no more than 256 colours, which can make later indexed-image conversion simpler.
  • Higher values create more coloured stars and can produce many distinct colours.

Planet images can also contain tens of thousands of colours. If your display or export format needs a colour limit, run the completed PPM through a separate Netpbm tool such as ppmdither, pnmquant or pamdepth. That is a conversion step, not an option to ppmforge itself.

4. Tune a planet with a fixed seed

Keep the seed fixed while you compare settings. The default planet uses fractal dimension 2.4 and power 1.2. This command makes a larger, well-lit planet with a 23.5 degree inclination and explicit ice settings:

$ ppmforge -seed 123 -width 800 -height 600 -mesh 256 \
    -hour 12 -inclination 23.5 -dimension 2.4 -power 1.2 \
    -ice 0.4 -glaciers 0.75 \
    > /tmp/ppmforge-planet.ppm
$ file /tmp/ppmforge-planet.ppm
/tmp/ppmforge-planet.ppm: Netpbm image data, size 800 x 600, rawbits, pixmap
  • -hour 12 puts the central meridian at full illumination. The default hour is random, so two otherwise identical commands can show different lighting unless you set it.
  • -inclination controls the latitude at which the star sits overhead, with positive values meaning northern summer.
  • -ice controls polar caps.
  • -glaciers lets high terrain carry ice towards lower latitudes.

Quality has a cost: the FFT mesh is square, and both memory use and computation grow roughly with the square of its size. Doubling -mesh 256 to -mesh 512 needs about four times the memory and takes about four times as long. Do not raise mesh and output dimensions together until the smaller test looks right.

The generated image must be at least as wide as it is high, and the width must be even. If you need a tall or narrow final image, generate a valid wider image first and crop it afterwards with pamcut. Do not assume the requested dimensions are the final ones: inspect the header or use file.

5. Re-render a result instead of guessing

The seed is printed unless you use -quiet. Save a seed you like, then reuse it with the same image settings. That lets you change viewing parameters or render at a higher resolution without changing the underlying random scene:

$ ppmforge -seed 123 -width 800 -height 600 -mesh 256 \
    -hour 12 -inclination 23.5 > /tmp/planet-v1.ppm
$ ppmforge -seed 123 -width 1600 -height 1200 -mesh 512 \
    -hour 12 -inclination 23.5 > /tmp/planet-v2.ppm
$ cmp -s /tmp/planet-v1.ppm /tmp/planet-v2.ppm; printf 'same bytes: %s\n' "$?"
same bytes: 1

A non-zero status from cmp is expected here, since the dimensions and mesh differ between the two. To check actual determinism, render the exact same command twice and compare:

$ ppmforge -seed 123 -width 256 -height 256 -mesh 64 > /tmp/a.ppm
$ ppmforge -seed 123 -width 256 -height 256 -mesh 64 > /tmp/b.ppm
$ cmp /tmp/a.ppm /tmp/b.ppm
$ echo $?
0

If you omit -seed, the program picks one from the date and time. Fine for variation, wrong default for a build or a reproducible asset pipeline.

6. Recover from failed or unwanted renders

Warning

Shell redirection truncates its destination before the program starts. Do not redirect a valuable image straight over its only copy. Render to a new temporary name, inspect it, then move it into place:

$ ppmforge -seed 123 -width 800 -height 600 -mesh 256 \
    > /tmp/planet.ppm.new
$ file /tmp/planet.ppm.new
$ mv /tmp/planet.ppm.new /path/to/checked/planet.ppm

Recovery

If the render fails, the old destination is untouched; remove the incomplete .new file only after confirming it is the failed temporary. If you already overwrote an output, there is no ppmforge undo: regenerate it from the recorded seed and options, or restore your own backup.

  • Memory or time problem: reduce -mesh first, then reduce output dimensions.
  • Unexpectedly dark planet: set an explicit -hour between 4 and 20, with 12 as the simplest test.
  • Missing converter: keep the verified PPM and install or invoke the conversion tool through your normal package-management process. None of this needs sudo.

Done means

  • Version confirmed. You checked the installed Netpbm version and the ppmforge path.
  • Mode chosen on purpose. You generated a PPM in the intended mode: planet, clouds or night sky.
  • Seed recorded. You used an explicit seed when the image needs to be reproducible.
  • Dimensions verified. You checked the actual PPM header rather than trusting the request.
  • Mesh sized sensibly. You kept mesh size proportionate to available memory and render time.
  • Output protected. You rendered replacements to a separate file, so a failed command could not destroy the previous image.