strukturag / libheif

libheif is an HEIF and AVIF file format decoder and encoder.
Other
1.76k stars 302 forks source link

`only_use_preferred_chroma_algorithm` doesn't work as expected #935

Closed homm closed 1 year ago

homm commented 1 year ago
struct heif_color_conversion_options
{
  uint8_t version;

  // --- version 1 options

  enum heif_chroma_downsampling_algorithm preferred_chroma_downsampling_algorithm;
  enum heif_chroma_upsampling_algorithm preferred_chroma_upsampling_algorithm;

  // When set to 'false', libheif may also use a different algorithm if the preferred one is not available.
  uint8_t only_use_preferred_chroma_algorithm;
};

Expected

From the description: the different algorithm will be used when the preferred one is not available. So, if the preferred algorithm is available, it should be used, right?

I'm using the following settings:

    p_options.color_conversion_options.preferred_chroma_upsampling_algorithm = 2
    p_options.color_conversion_options.only_use_preferred_chroma_algorithm = 0

It's set preferred_chroma_upsampling_algorithm to heif_chroma_upsampling_bilinear The same settings are default, by the way.

Actual result

The decoded image is pixelated in red-to-blue areas (you can use the example from #586), which means that nearest neighbor upsampling is used instead of the preffered.

Despite this (that nearest neighbor is used), if you set only_use_preferred_chroma_algorithm to 1 (true), the image will be not so pixelated, which means that bilinear algorithm will be used and therefore it is available and therefore is should be used for upsampling if only_use_preferred_chroma_algorithm is false.

The same happens with preferred_chroma_downsampling_algorithm.

farindk commented 1 year ago

I agree that the comment

  // When set to 'false', libheif may also use a different algorithm if the preferred one is not available.

is not accurate. Libheif evaluates different options how to do the conversion, also taking into account the computational complexity. If only_use_preferred_chroma_algorithm=false, it may select a different chroma algorithm even if the selected one is available, if it finds that the other conversion would be simpler.

I.e. if no algorithm is forced, even though the preferred one is set to bilinear, it uses:

$ heif-enc flat-color-test.png -A -p chroma=420 -o out.avif
final pipeline has 1 steps:
> 20Op_RGB24_32_to_YCbCr

This is RGB->YCbCr with implicit subsampling in one step.

On the other hand, if we force it into bilinear, it uses:

$ heif-enc flat-color-test.png -A -p chroma=420 -o out.avif -C average
final pipeline has 3 steps:
> 18Op_RGB24_32_to_RGB
> 15Op_RGB_to_YCbCrIhE
> 31Op_YCbCr444_to_YCbCr420_averageIhE

I think that this is actually the desired behavior, but the comment is inaccurate. I will reformulate the comment.

farindk commented 1 year ago

comment changed in 0e6fa57