Convert a FITS Image to PNM with fitstopnm
fitstopnm turns a FITS astronomy image into a plain PGM or PPM file you can actually view, without touching your original data. It ships in Netpbm 11.5.2, installed here as Debian package netpbm 2:11.05.02-1.1build1, and the whole job takes about fifteen minutes once the file and tools are ready.
The route
Jump straight to the step you need, or tick off Done means at the end.
You need a readable FITS file, a shell, and room for the output. This will not edit FITS headers or touch your source data. Conversion is an ordinary unprivileged job: skip sudo unless your chosen directory genuinely needs it.
1. Confirm the installed command
Check the executable and package version before trusting the examples below. These commands only read local metadata:
$ command -v fitstopnm
/usr/bin/fitstopnm
$ fitstopnm --version
fitstopnm: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
...
The build details in that version string vary by distribution; the Netpbm version is what matters. The installed manual notes that the shortest unique abbreviation of an option is accepted. Use full option names in scripts anyway, so a later option addition cannot quietly change what an abbreviation means.
Checkpoint
If command -v finds nothing, install Netpbm through your normal package manager. Do not download a random replacement binary into the working directory.
2. Check the FITS input without changing it
Set a shell variable to the real path. Quoting it protects spaces and shell metacharacters in the filename:
$ FITS_FILE='/path/to/observation.fits'
$ test -r "$FITS_FILE" && echo 'input is readable'
input is readable
$ file "$FITS_FILE"
/path/to/observation.fits: FITS image data
The wording from file depends on its version and on the FITS contents. A readable file is not necessarily a valid image with the dimensions you expect, so keep the original in place until the PNM has been checked.
Warning
Never redirect output onto the input path. Shell redirection opens the destination before fitstopnm starts, so fitstopnm "$FITS_FILE" > "$FITS_FILE" can wipe the source before conversion even begins. Always pick a separate destination.
3. Inspect the sample range first
Use -printmax to see the minimum and maximum sample values without generating an image yet:
$ fitstopnm -printmax "$FITS_FILE"
-12.5 843.75
Those two numbers are just an example of the output shape, not a prediction about your data. The option prints the range and quits, which is handy before you choose explicit scaling limits or an output maximum.
By default, fitstopnm trusts DATAMIN and DATAMAX from the FITS header when they exist. Force an actual scan of the pixel data with -scanmax when header metadata might be stale:
$ fitstopnm -scanmax -printmax "$FITS_FILE"
-12.5 843.75
Use -min and -max when you deliberately want bounds different from the header or scan. Both take floating-point numbers:
$ fitstopnm -min 0 -max 500 -printmax "$FITS_FILE"
0 500
That last command only reports the selected limits; it still does not write an image. Treat clipping as a visualisation choice. If your scientific interpretation depends on the full measured range, record the limits and keep the FITS original rather than assuming the PNM is a lossless copy.
4. Convert a two-dimensional FITS image
For a FITS image with two axes, run the converter and redirect standard output to a new PNM file:
$ fitstopnm "$FITS_FILE" > observation.pgm
$ test -s observation.pgm && echo 'PNM output is non-empty'
PNM output is non-empty
$ file observation.pgm
observation.pgm: Netpbm image data, size 2048 x 2048, graymap
Your dimensions and file description will follow your own input; a two-axis image normally produces PGM. For floating-point FITS samples the documented default output maximum is 255, because the input precision is effectively unlimited. For other input the default maximum is chosen to keep the available integer precision, based on the sample range.
- Write to a temporary name first when replacing an existing derived image, so a failed conversion cannot leave a truncated file in its place.
$ fitstopnm "$FITS_FILE" > observation.pgm.new
$ test -s observation.pgm.new
$ mv observation.pgm.new observation.pgm
The mv is the only state-changing step. If conversion or verification fails, remove just observation.pgm.new and the previous observation.pgm is still there. Never delete the original FITS as part of cleanup.
5. Select one plane from a three-axis file
A FITS file with three image planes can produce a pseudo-PPM by default, and that is often not a colour image at all: the third axis commonly represents time or another measurement, not red, green and blue channels.
Select one plane explicitly with -image. Replace 1 with the plane number you actually need:
$ fitstopnm -image 1 "$FITS_FILE" > observation-plane-1.pgm
$ file observation-plane-1.pgm
observation-plane-1.pgm: Netpbm image data, size 2048 x 2048, graymap
The manpage recommends -image for exactly this reason: it stops three-axis FITS data turning into an unwanted pseudo-PPM. Do not assume plane 1 is the earliest observation, or that the third axis is colour; check the FITS metadata and instrument documentation before giving a plane scientific meaning.
If you genuinely need all three planes, omit -image and verify the result as a PPM:
$ fitstopnm "$FITS_FILE" > observation-planes.ppm
$ file observation-planes.ppm
observation-planes.ppm: Netpbm image data, size 2048 x 2048, pixmap
The output type and dimensions above are only representative. Trust the command's own report and your local inspection rather than copying these values blindly.
6. Set output precision deliberately
Use -omaxval when a downstream tool or comparison needs a particular PNM maximum value:
$ fitstopnm -omaxval 255 "$FITS_FILE" > observation-8bit.pgm
$ head -n 3 observation-8bit.pgm
P5
2048 2048
255
Raw PNM output is a text header followed by binary sample data, so head is only a quick header check; do not open the whole file in a text editor. Changing the maximum changes the numeric representation available downstream. It does not restore anything already clipped by your -min and -max choices.
7. Check orientation and diagnose failures
The Netpbm manual warns that FITS pixel order may need a top-to-bottom flip. If your image looks vertically inverted, make the flip its own reviewable step rather than guessing:
$ pamflip -topbottom observation.pgm > observation-topdown.pgm
$ file observation-topdown.pgm
observation-topdown.pgm: Netpbm image data, size 2048 x 2048, graymap
This assumes pamflip is installed, and it leaves the converted PGM untouched. If you do not need a flip, keep the first output. Compare either result against a trusted FITS viewer before you read anything into the features you see.
A non-zero exit status means conversion did not finish. For a missing input, the installed command reports that it cannot open the file and returns status 1, so check the path and read permission first:
$ ls -l -- "$FITS_FILE"
$ test -r "$FITS_FILE" && echo readable
readable
If the file is readable but the output looks wrong, rerun with -printmax, then decide whether stale header limits, explicit -min/-max, -scanmax, or an explicit -image selection is the fix. Note each command and its chosen limits in your processing log.
Done means
- Version confirmed.
fitstopnmis the expected Netpbm build and the FITS input is readable. - Range checked before converting, whenever header limits or clipping mattered.
- Output is separate and verified. A non-empty PGM or PPM file whose type and dimensions you actually inspected.
- Plane handling was deliberate. A three-axis FITS file was treated as pseudo-PPM on purpose, or a plane was chosen explicitly.
- Replacements went through a temp file, so a failed conversion could never truncate the previous result.
- Original FITS file untouched, and orientation was checked before you interpreted the image.