Skip to content

[css-color-4] CSS gamut mapping algorithm pseudocode can result in infinite looping for some inputs #6999

Closed
@weinig

Description

@weinig

The CSS gamut mapping algorithm pseudocode can result in infinite looping for some inputs. As an example, gamut mapping the color oklch(104.4% 0 336) to display-p3 loops indefinitely due to the following steps:

gamut map oklch(104.4% 0 336) to display-p3:

origin_OKLCH -> oklch(104.4% 0 336)
inGamut<display-p3>(origin_OKLCH) -> false

min -> 0
max -> 0

start bisection loop:
    chroma -> 0
    current -> oklch(104.4% 0 336)

    inGamut<display-p3>(current) -> false
    current as display-p3 -> color(display-p3 1.058 1.058 1.058)

    clipped -> (display-p3 1 1 1)
    E -> delta(clipped, current)
          -> clipped as oklab(100% 0 5.96E-8)
          -> current as oklab(104.4% 0 0)
          -> sqrt(((100 / 100) - (104.4 / 100))^2 + (0 - 0)^2 + (5.96E-8 - 0)^2)
          -> 0.04

    0.04 is not less than JND of 0.02, so we loop forever

I added a condition to step 9.4.3 to also check if chroma was 0, making it something like:

        3. if E < JND or chroma is 0 convert clipped to destination and return it as the gamut mapped color

(though, it isn't really necessary to say "convert clipped to destination" since clipped is already in the destination color space by the definition of clip() in step 6.)

I haven't thought too deeply about whether there are any other cases that could infinite loop.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions