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

671 views Asked by At

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
2

There are 2 answers

1
Jon Sneyers On BEST ANSWER

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.

0
malat On

As explained by Jon Sneyers just above the palette is an internal encoding tool. I was confused by this, as I could not see any difference in the output of the jxlinfo command line.

So I ran the following experience on my side to convince myself:

$ cjxl -d 0 --palette=257 palette.png palette.257.jxl
$ cjxl -d 0 --palette=256 palette.png palette.256.jxl
$ cjxl -d 0 --palette=255 palette.png palette.255.jxl

Lead to:

% md5sum palette.*.jxl
e925521cbb976dce2646354ea3deee3b  palette.255.jxl
8d241b94d67aeb2706a1aad7aed55cc7  palette.256.jxl
8d241b94d67aeb2706a1aad7aed55cc7  palette.257.jxl

Where:

% du -sb palette.*.jxl
89616   palette.255.jxl
45627   palette.256.jxl
45627   palette.257.jxl

In all case jxlinfo reveals:

% jxlinfo palette.255.jxl
dimensions: 256x256
have_container: 0
uses_original_profile: 1
bits_per_sample: 8
have_preview: 0
have_animation: 0
intrinsic xsize: 256
intrinsic ysize: 256
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: 13 (sRGB)
  rendering_intent: 0 (Perceptual)
frame:
  still frame, unnamed

With:

% pnginfo palette.png
palette.png...
  Image Width: 256 Image Length: 256
  Bitdepth (Bits/Sample): 8
  Channels (Samples/Pixel): 1
  Pixel depth (Pixel Depth): 8
  Colour Type (Photometric Interpretation): PALETTED COLOUR (0 colours, 0 transparent)
  Image filter: Single row per byte filter
  Interlacing: No interlacing
  Compression Scheme: Deflate method 8, 32k window
  Resolution: 0, 0 (unit unknown)
  FillOrder: msb-to-lsb
  Byte Order: Network (Big Endian)
  Number of text strings: 0

enter image description here