Convert JPEG-2000 Files to PNM with jpeg2ktopam

Someone hands you a .jp2 or .jpc file and asks for a plain PNM, and jpeg2ktopam does the job in one command with no format flag to remember. Allow about ten minutes if the input path is known. The examples use Netpbm 11.5.2, installed here as package version 2:11.05.02-1.1build1.

This is a read-and-convert operation. You need the netpbm package and write access to the output directory. It normally needs no elevated privileges. Do not use sudo merely because the file is an image; use it only when your existing file permissions genuinely require administrative access.

1. Check the installed command

Confirm which executable your shell will run and record the local version:

$ command -v jpeg2ktopam
/usr/bin/jpeg2ktopam
$ jpeg2ktopam --version
jpeg2ktopam: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
...

The version output includes build details as well as the Netpbm version, so the exact trailing lines can differ between packages. The installed manual documents -verbose and -debuglevel as the command-specific options, plus the usual Netpbm common options including -quiet.

2. Convert a named JPEG-2000 file

Give the input filename and redirect standard output to a new PNM file:

$ jpeg2ktopam /path/to/input.jp2 > converted.pnm

The same command accepts a JPEG-2000 code stream with a .jpc name:

$ jpeg2ktopam /path/to/input.jpc > converted.pnm

JP2 and JPC are related but different formats. JP2 carries image metadata around a JPEG-2000 code stream, while JPC is the code stream itself. jpeg2ktopam handles both, provided the installed Jasper decoder can read the particular input.

Checkpoint: a successful conversion writes the image to standard output and normally writes no progress text. Check the output before opening it:

$ test -s converted.pnm && echo 'output is non-empty'
output is non-empty
$ pamfile converted.pnm
converted.pnm:    PPM raw, 1920 by 1080  maxval 255

Your dimensions and the wording from pamfile will depend on the source. The useful checks are that the file is non-empty, the dimensions are expected, and the reported format is one that you intended to create.

3. Let the output type follow the input colour space

The command has no output-format flag. It picks the Netpbm type from the decoded image:

This matters when a script expects a particular header. Do not rename a file from .pam to .ppm after conversion. Inspect the result with pamfile, then pass it to a tool that supports the reported format.

There is also a colour-management boundary. For PGM and PPM output, the program treats sample intensities as PGM or PPM intensities, including the ITU-R BT.709 interpretation. JP2 input uses sRGB encoding, so converting a JP2 RGB image to PPM can shift its displayed colour slightly. The numeric samples in PAM output are preserved, subject to the documented unsigned two's-complement representation for signed input samples.

4. Read from standard input in a pipeline

Omit the filename when another command supplies the JPEG-2000 bytes on standard input:

$ cat /path/to/input.jpc | jpeg2ktopam > converted.pnm
$ pamfile converted.pnm
converted.pnm:    PPM raw, 1920 by 1080  maxval 255

In a script, prefer a direct redirection or a pipeline that preserves failure status. A plain pipeline can report the status of its last command in many shells, even if the producer failed. In Bash, enable pipefail when the producer's failure must stop the workflow:

$ set -o pipefail
$ cat /path/to/input.jpc | jpeg2ktopam > converted.pnm
$ status=$?
$ test "$status" -eq 0 || { printf 'conversion failed: %s\n' "$status" >&2; exit "$status"; }

For one input file, the named-file form is easier to audit and gives the converter a direct path to report if opening the input fails.

5. Avoid losing an existing output

Shell > truncates its destination before jpeg2ktopam starts. That is destructive if converted.pnm already contains a good image. Convert to a temporary file in the same directory, check it, then replace the destination deliberately:

$ jpeg2ktopam /path/to/input.jp2 > converted.pnm.new
$ test -s converted.pnm.new
$ pamfile converted.pnm.new
converted.pnm.new:  PPM raw, 1920 by 1080  maxval 255
$ mv converted.pnm.new converted.pnm

If conversion fails, leave the old output alone and inspect the command's error. Remove the incomplete .new file only after checking that it is not needed for diagnosis. The mv above replaces an existing destination; if you need a recovery point, copy it first:

$ cp --preserve=all converted.pnm converted.pnm.backup

Warning: deleting that backup is irreversible, so do it separately after the replacement has been checked.

6. Use diagnostics when decoding fails

First check that the input exists and is readable without changing it:

$ ls -l /path/to/input.jp2
$ test -r /path/to/input.jp2 && echo readable

If the file is readable but decoding still fails, enable the program's informational messages:

$ jpeg2ktopam -verbose /path/to/input.jp2 > converted.pnm

For lower-level Jasper decoder diagnostics, pass a numeric debug level:

$ jpeg2ktopam -debuglevel=1 /path/to/input.jp2 > converted.pnm

These options report information; they do not repair a damaged file or change the decoder's output format. Keep diagnostic output separate from the image: do not redirect standard error into standard output, because that mixes text into the binary PNM or PAM stream. If the decoder rejects the file, confirm its actual format with a trusted file-inspection tool and keep the original for another decoder or recovery attempt.

Done means