Encode a PPM Image as JPEG XR with JxrEncApp

JxrEncApp turns a BMP, PNM, TIFF or HDR source into a JPEG XR file, but it will not guess your pixel format for you. Get -c wrong and you get a valid-looking file with scrambled colours. This guide uses JxrEncApp from libjxr-tools version 1.2~git20170615.f752187-5.1ubuntu2, the version installed on this machine.

Allow about fifteen minutes. You need a shell, a readable input image, enough space for a new output file, and a program such as file for the final check. No step needs sudo. Keep the original image until the JPEG XR output has been tested.

1. Check the installed encoder

Confirm that the command and package are the ones you expect. This is read-only:

$ command -v JxrEncApp
/usr/bin/JxrEncApp
$ dpkg-query -W -f='${Package} ${Version}\n' libjxr-tools
libjxr-tools 1.2~git20170615.f752187-5.1ubuntu2
$ JxrEncApp --help

The help text is also the quickest local check of the accepted input formats and pixel-format numbers. The manpage describes BMP, PNM, TIFF and HDR input, but the uncompressed pixel format is not reliably inferred: -c is required. Do not skip it.

Checkpoint: You have the installed version, and your input is one of the formats listed by the local help.

2. Choose the source pixel format

Pass the number that describes the uncompressed source data, not the JPEG XR output. For a normal 24-bit RGB PNM file, use -c 9. For a 24bpp BGR source use -c 0. The other useful common values are 2 for 8bpp greyscale, 10 for 48bpp RGB and 22 for 32bpp BGRA.

Images with alpha need a second choice. Use -a 2 for planar alpha or -a 3 for interleaved alpha, as appropriate for the source. The manual marks -a as required for pixel formats containing an alpha channel. Do not guess: a wrong format can produce a failed encode or incorrectly interpreted pixels.

For a one-bit black and white image, use -c 1. The -b option controls whether zero means black or white; it defaults to zero meaning black.

3. Encode a supported PNM image

Choose an output path that does not contain a file you need to preserve. The command below uses a placeholder RGB PPM and writes a new JPEG XR file:

$ JxrEncApp -i /path/to/input.ppm -o /path/to/output.jxr -c 9 -q 1
$ printf 'encoder status: %s\n' "$?"
encoder status: 0

Replace both paths before running the command. A zero exit status means the encoder completed. It does not prove that you selected the right colour layout, so inspect the output in the next step.

The -q value is a quality value in the range 0.0 to less than 1.0. Its default is 1.0, which the program documents as lossless. The alternative quantisation form accepts integers from 1 to 255, with 1 as lossless. Use the lossless default for a first conversion and record any lower setting in the workflow that produces the image.

Safety warning: JxrEncApp can replace an existing output path. Use a new filename while testing. If you deliberately overwrote a file and need recovery, restore it from your backup or regenerate it from the original input; the encoder has no undo operation.

4. Verify the file and encoder diagnostics

Check the result without opening it in an untrusted viewer:

$ file /path/to/output.jxr
/path/to/output.jxr: JPEG-XR
$ test -s /path/to/output.jxr && echo 'non-empty output'
non-empty output

For a useful first run, add -v and -t:

$ JxrEncApp -i /path/to/input.ppm -o /path/to/output.jxr -c 9 -q 1 -v -t
================================
Input file:   /path/to/input.ppm
Output file:  /path/to/output.jxr
Internal cf:  YUV_444
Overlap:      yes
...

The exact timing, colour-format identifier, tile details and bitstream sizes depend on the image. -v displays encoder information and -t displays timing information; neither changes the encoding settings. If file reports an empty or generic file, stop and investigate the exit status rather than deleting the source.

5. Adjust compression deliberately

Quality below 1.0 is not the only setting that changes the result:

Set both explicitly when reproducibility matters; this is an easy source of surprising differences between two commands that only appear to change quality. For a reproducible lower-quality conversion, make those choices visible:

$ JxrEncApp -i /path/to/input.ppm -o /path/to/preview.jxr \
    -c 9 -q 0.75 -d 3 -l 1 -p

Here -p turns progressive mode off, selecting sequential mode. Keep the output beside the lossless file until visual and downstream-reader checks are complete.

6. Diagnose the common failures

A non-zero status with an empty output usually means the input, format or dimensions do not match what this older utility accepts. Check the path and file type first:

$ test -r /path/to/input.ppm && echo readable
readable
$ file /path/to/input.ppm
/path/to/input.ppm: Netpbm image data, ...

Then compare the file's actual channels and bit depth with -c. Do not use -c 9 for a greyscale or BGR source merely because the extension is .ppm. If a tiny test image fails, try a normal image with dimensions suitable for the JPEG XR encoder; successful encoding on this installation produced a non-empty JPEG XR from a resized RGB PPM.

When the source is an unusual TIFF, HDR or alpha image, first convert a copy to a simple RGB PNM and test that. Keep the original unchanged. Conversion tools may have their own colour-management behaviour, so compare the decoded result rather than assuming that a successful exit preserves every colour profile or metadata field.

Done means