Skip to content

Evaluate XYZ compression #8

@Brankale

Description

@Brankale

when the source white point and the destination white point are different, the source white point can be clipped after the colorspace conversion has been applied (e.g. (258, 250, 250) becomes (255, 250, 250)).

One possible approach to fix this is with a chromatic adaptation to the clipped white point in order to preserve "perceptual accuracy".
NB: this is true under the assumption that the game is full screen and no other OS UI elements with full D65 white point are present on screen.
NB: this is true if there are a lot of bright elements on screen which triggers human eye chromatic adaptation

To avoid clipping and chromatic adaptation, you can apply a compression on the XYZ coordinates XYZ' = k * XYZ where k is chosen so that XYZ' is inside the destination colorspace (e.g. sRGB).

this way chromaticity coordinates Yxy are preserved at the expense of the luminance which is lower:

x = X / (X + Y + Z)
x' = kX / (kX + kY + kZ) = kX / k(X + Y + Z) = X / (X + Y + Z)

y = Y / (X + Y + Z)
y' = kY / (kX + kY + kZ) = kY / k(X + Y + Z) = Y / (X + Y + Z)

Y' = k * Y

NB: If k << 1 the resulting image can be pretty dark


NB: scaling XYZ is equivalent to scaling linear RGB (i.e. RGB with EOTF applied) values because

(R,G,B) ∈ [0,1] implies (kR,kG,kB) ∈ [0,1] for 0 <= k <= 1

and

XYZ' = M * (k * RGB_lin​) = k * (M * RGB_lin​) = k * XYZ

RGB_lin = [M] * XYZ_w

where M is the XYZ -> RGB matrix of the destination colorspace and XYZ_w are the XYZ coordinates of the white point of the starting colorspace

k = min(1, 1 / RGB_lin[0], 1 / 1 / RGB_lin[1], 1 / 1 / RGB_lin[2])

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions