Home / Alt manpages / pamseq(1)

  • pamseq(1)
  • User command
  • linux

Build Reproducible PAM Sequence Images with pamseq

You will finish with a repeatable way to generate a one-row PAM image containing a numerical sequence, a multi-plane tuple grid, or a small colour map. The examples use pamseq from Netpbm 11.5.2, supplied here by package netpbm 2:11.05.02-1.1build1.

Allow about fifteen minutes. You need a shell, pamseq, and optionally pamrestack or pamfile from Netpbm. The commands write ordinary files in your working directory and do not need elevated privileges. Do not use sudo unless your chosen destination is deliberately protected and you have checked the ownership first.

1. Check the installed command

Confirm which executable will run and record the Netpbm version. These are read-only checks:

$ command -v pamseq
/usr/bin/pamseq
$ pamseq --version
pamseq: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pamseq: 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 version matters because the -min, -max and -step options were added in Netpbm 10.99. If another machine has an older Netpbm, check its local manual before copying these examples into a script.

Checkpoint: if command -v finds nothing, stop here. Install Netpbm through your normal package-management process, then repeat the check. There is no reason to run the generator as root.

2. Generate a simple sequence

The required arguments are depth and maxval. Depth is the number of samples in each tuple. With depth 1 and maxval 4, pamseq creates one row containing the five values from 0 through 4:

$ pamseq 1 4 > sequence.pam
$ pamfile sequence.pam
sequence.pam: PAM, 5 by 1 by 1 maxval 4
$ od -An -t u1 -j 44 sequence.pam
   0   1   2   3   4

The output is a binary PAM file, so do not use cat as a visual check. The header is text, but the sample data may contain control bytes. pamfile checks the image structure and od makes the small sample values visible. Header length can vary when attributes are present, so the offset in this deliberately simple example is not a general parsing rule.

Checkpoint: the width is maxval minus the starting value plus one when the default range is used. For pamseq 1 4, that is five pixels. The height is always one until another Netpbm program reshapes the stream.

3. Set a range and step explicitly

Use -min, -max and -step when the default 0-to-maxval ramp is not the sequence you need. For depth 1, each option takes one whole-number value:

$ pamseq 1 255 -min=4 -max=8 -step=2 > even-range.pam
$ pamfile even-range.pam
even-range.pam: PAM, 3 by 1 by 1 maxval 255
$ pamtopnm -assume even-range.pam | od -An -t u1
  80  53  10  51  32  49  10  50  53  53  10   4   6   8

The endpoint is included when the step lands on it. A step that does not land exactly on the maximum produces values only up to the last value in the sequence; do not assume that -max will be emitted in every case. Each step must be positive and no greater than maxval. Every maximum must be at least its matching minimum.

The option spelling is shown in its clearest form. pamseq accepts either one or two leading hyphens, accepts whitespace or an equals sign before a value, and permits unique abbreviations. Full option names are easier to audit, so keep them in scripts.

4. Generate tuples across several planes

For depth greater than one, provide one comma-separated number per plane. pamseq varies the highest-numbered plane first, then moves towards the lower-numbered planes. With depth 2, the second sample changes fastest:

$ pamseq 2 255 -min=0,4 -max=2,8 -step=1,2 > tuples.pam
$ pamfile tuples.pam
tuples.pam: PAM, 9 by 1 by 2 maxval 255
$ pamseq 2 255 -min=0,4 -max=2,8 -step=1,2 \
    | pamrestack -width=3 > tuple-grid.pam
$ pamfile tuple-grid.pam
tuple-grid.pam: PAM, 3 by 3 by 2 maxval 255

The first stream has nine tuples in one row: (0,4), (0,6), (0,8), then the same second-plane values with first-plane value 1, then 2. pamrestack -width=3 turns that one row into three rows. The reshape is separate from pamseq; it does not change the values.

A common mistake is supplying the wrong number of comma-separated values. This fails safely before a useful image is produced:

$ pamseq 2 10 -min=0
pamseq: Wrong number of values for -min: 1.  Need 2

Match the count to depth for all three range options. Do not silently reuse a depth-1 option list for a multi-plane image.

5. Add a tuple type for colour data

-tupletype sets the PAM TUPLTYPE attribute. It does not change the number of planes or scale the samples. A depth-3 image with maxval 5 contains every combination of three values from 0 through 5, so it is 216 pixels wide:

$ pamseq 3 5 -tupletype=RGB > web-safe-map.pam
$ pamfile web-safe-map.pam
web-safe-map.pam: PAM, 216 by 1 by 3 maxval 5, RGB
$ pamtopnm web-safe-map.pam > web-safe-map.ppm
$ file web-safe-map.ppm
web-safe-map.ppm: Netpbm image data, size 216 x 1, rawbits, pixmap

This is a compact colour map, not a normal photograph. The RGB label describes the tuple type for readers that understand it. Modern Netpbm programs can consume the PAM RGB image directly; pamtopnm is shown as an explicit conversion when a later tool expects a PNM stream.

Keep the PAM file if you need its tuple metadata. If you only need a PPM, verify the generated PAM first and convert it afterwards.

6. Write output without losing an existing file

Shell redirection truncates its destination before pamseq starts. If sequence.pam already contains a good result, do not redirect straight over it. Generate a temporary sibling, verify it, then replace the old file deliberately:

$ pamseq 1 255 -min=0 -max=255 -step=16 > sequence.pam.new
$ pamfile sequence.pam.new
sequence.pam.new: PAM, 16 by 1 by 1 maxval 255
$ mv sequence.pam.new sequence.pam

If generation or verification fails, leave the original untouched and remove only the known temporary file after checking its path. Removing a file is irreversible in the normal shell workflow, so do not use a broad wildcard. If the final mv replaced the wrong destination, restore it from your backup or version control; pamseq has no undo operation.

For automation, check the exit status before accepting the result and keep the output in a directory where the invoking user can write. A successful command says that pamseq completed; pamfile still needs to confirm the dimensions, depth and maxval expected by the next stage.

7. Diagnose the likely errors

A complaint about a range list usually means the list length does not match depth. An invalid maximum or step means the requested sequence violates the numeric limits. Reduce the command to a small range, check it with pamfile, then add the real values.

If a downstream program rejects the image, inspect the PAM header and check whether it expects one row or a reshaped image. pamseq always creates height 1. Use pamrestack only when you have a deliberate width and know how many tuples the input contains.

If the output appears empty or unreadable in a terminal, that is expected for binary image data. Use pamfile, file, a Netpbm converter, or an image viewer instead. Do not infer correctness from terminal characters.

Done means

  • You confirmed the installed pamseq and Netpbm version.
  • You generated and inspected a PAM image with the expected width, height, depth and maxval.
  • Every range list has one value per plane, with positive steps.
  • You used pamrestack only as a separate, intentional reshape step.
  • You labelled RGB tuples explicitly when a downstream reader needs that metadata.
  • You protected an existing output from shell redirection and verified replacements before moving them into place.