babl: don't create LUT for destination formats with premultiplied colors.
authorJehan <jehan@girinstud.io>
Sun, 12 Feb 2023 12:05:14 +0000 (13:05 +0100)
committerJehan <jehan@girinstud.io>
Sun, 12 Feb 2023 12:27:47 +0000 (13:27 +0100)
This is a different issue than previous commit, but was revealed by
fixing the bug. So in a way, it's a followup.

When the destination format uses premultiplied colors, we would end up
with a LUT where all colors in the table are (0, 0, 0) since we store
them with alpha = 0. We could also generate them with alpha = 1, but
then we'd have to special-case the conversion step, re-multiplying each
pre-multiplied value with the real alpha, etc. So instead, I just bypass
these conversion cases and don't create LUT for these.

For the record, we had this case on GIMP when rendering u8 images to
display, since it would require for instance a LUT from R'G'B'A u8 to
cairo-ARGB32 (Cairo's ARGB32 being pre-multiplied with alpha). So the
whole image would render black (even though, when color-picking colors,
we'd see pixels' colors are not black).

Note that this bug existed before, but was simply hidden by the bug
fixed in the previous commit (since conversion was done twice: first
with LUT, then through usual conversion paths, the second conversion was
hiding the broken LUT conversion).

babl/babl-fish-path.c

index fcf998e5245f418f4114c06271c2232169296975..808381cad5fee1b4b986f3e7d4c69caf62ba86bd 100644 (file)
@@ -975,10 +975,12 @@ _babl_fish_prepare_bpp (Babl *babl)
      // as long as the highest 8bit of the 32bit of a 4 byte input is ignored
      // (alpha) - and it is not an associated color model. A 24 bit LUT provides
      // exact data. Thus this is valid for instance for "YA half"
+     // Additionally we also avoid associated destination models too.
 
      if ((babl->conversion.source->format.type[0]->bits < 32 &&
-          (source_bpp < 4 
-         || (babl->conversion.source->format.model->flags & BABL_MODEL_FLAG_ASSOCIATED)==0)))
+          (source_bpp < 4 ||
+           (babl->conversion.source->format.model->flags & BABL_MODEL_FLAG_ASSOCIATED)==0) &&
+         (babl->conversion.destination->format.model->flags & BABL_MODEL_FLAG_ASSOCIATED)==0))
      {
        static int measured_timings = 0;
        float scaling = 10.0;