Search code examples
jpegcolor-palettejpeg-xl

JPEG-XL: Handling of palette in libjxl command line tools


I am trying to make sense of the following presentation, see page 27:

Legacy image format friendly

Could someone please describe the command line tools available in libjxl that can help me work with existing palettes ?

I tried a naive:

% convert -size 512x512 -depth 8 xc:white PNG8:white8.png
% convert -size 512x512 -depth 8 xc:white PNG24:white24.png

which gives me the exected:

% file white8.png white24.png
white8.png:  PNG image data, 512 x 512, 8-bit colormap, non-interlaced
white24.png: PNG image data, 512 x 512, 8-bit/color RGB, non-interlaced

But then:

% cjxl -d 0 white8.png white8.jxl
% cjxl -d 0 white24.png white24.jxl

Gives:

% md5sum white8.jxl white24.jxl
68c88befec21604eab33f5e691a2a667  white8.jxl
68c88befec21604eab33f5e691a2a667  white24.jxl

where

% jxlinfo white8.jxl
dimensions: 512x512
have_container: 0
uses_original_profile: 1
bits_per_sample: 8
have_preview: 0
have_animation: 0
intrinsic xsize: 512
intrinsic ysize: 512
orientation: 1 (Normal)
num_color_channels: 3
num_extra_channels: 0
color profile:
  format: JPEG XL encoded color profile
  color_space: 0 (RGB color)
  white_point: 1 (D65)
  primaries: 1 (sRGB)
  transfer_function: gamma: 0.454550
  rendering_intent: 0 (Perceptual)
frame:
  still frame, unnamed

I also tried:

% cjxl -d 0 --palette=1024 white24.png palette.jxl

which also gives:

% md5sum palette.jxl
68c88befec21604eab33f5e691a2a667  palette.jxl

Solution

  • The libjxl encoder either takes a JPEG bitstream as input (for the special case of lossless JPEG recompression), or pixels. It does not make any difference if those pixels are given via a PPM file, a PNG8 file, a PNG24 file, an RGB memory buffer, or any other way, if the pixels are the same, the result will be the same.

    In your example, you have an image that is just solid white, so it will be encoded the same way regardless of how you pass it to cjxl.

    Now if those pixels happen to use only few colors, as will be the case for PNG8 since there can be at most 256 colors in that case, the encoder (at a default effort setting) will detect this and use the jxl Palette transform to represent the image more compactly. In jxl, palettes can have arbitrary sizes, there is no limit to 256 colors. The --palette option in cjxl can be used to set the maximum number of colors for which it will still use the Palette transform — if the input image has more colors than that, it will not use Palette.

    The use of Palette is considered an internal encoding tool in jxl, not part of the externally exposed image metadata. It can be used by the encoder to effectively recompress PNG8 files, but by no means will it necessarily always use that encoding tool when the input is PNG8, and it might also use Palette when the input has more than 256 colors. The Palette transform of jxl is quite versatile, it can also be applied to individual channels, to more or less than 3 channels, and palette entries can be not only specific colors but also so-called "delta palette entries" which are not a color but signed pixel values that get added to the predicted pixel value.