Function toLinearSRgb

Converts CIE XYZ D65 to linear-light sRGB.

LinearSRgb!T toLinearSRgb(T)(
  XyzD65!T xyz
) pure nothrow @nogc @safe;

Use this conversion when XYZ D65 data must enter linear-light sRGB calculations. Extended values are transformed without gamut clipping. Extreme finite inputs retain representable results where possible; callers should not rely on one particular floating-point evaluation order.

Parameters

NameDescription
xyz CIE XYZ D65 value to convert.

Returns

The corresponding linear-light sRGB value.

Standards

Uses the inverse of the high-precision sRGB/D65 transformation represented by the W3C CSS Color Module Level 4 reference matrix.

See Also

toXyzD65

Example

const black = XyzD65d(0.0, 0.0, 0.0).toLinearSRgb;

assert(black == LinearSRgbd(0.0, 0.0, 0.0));

Example

import std.math : fabs;

const double factorX = -0.75;
const double factorY = -0.75;
const double factorZ = -1.0;

const rgb =
    XyzD65d(
        factorX * double.max,
        factorY * double.max,
        factorZ * double.max
    ).toLinearSRgb;

const double expectedR =
    ratio!double(12831, 3959) * factorX +
    ratio!double(-329, 214) * factorY +
    ratio!double(-1974, 3959) * factorZ;

const double expectedG =
    ratio!double(-851781, 878810) * factorX +
    ratio!double(1648619, 878810) * factorY +
    ratio!double(36519, 878810) * factorZ;

const double expectedB =
    ratio!double(705, 12673) * factorX +
    ratio!double(-2585, 12673) * factorY +
    ratio!double(705, 667) * factorZ;

assert(finiteInfinityBounds(rgb.r));
assert(finiteInfinityBounds(rgb.g));
assert(finiteInfinityBounds(rgb.b));

assert(fabs(rgb.r / double.max - expectedR) < 1e-14);
assert(fabs(rgb.g / double.max - expectedG) < 1e-14);
assert(fabs(rgb.b / double.max - expectedB) < 1e-14);

Example

import std.math : fabs;

const float factorX = -0.75f;
const float factorY = -0.75f;
const float factorZ = -1.0f;

const rgb =
    XyzD65f(
        factorX * float.max,
        factorY * float.max,
        factorZ * float.max
    ).toLinearSRgb;

const float expectedR =
    ratio!float(12831, 3959) * factorX +
    ratio!float(-329, 214) * factorY +
    ratio!float(-1974, 3959) * factorZ;

const float expectedG =
    ratio!float(-851781, 878810) * factorX +
    ratio!float(1648619, 878810) * factorY +
    ratio!float(36519, 878810) * factorZ;

const float expectedB =
    ratio!float(705, 12673) * factorX +
    ratio!float(-2585, 12673) * factorY +
    ratio!float(705, 667) * factorZ;

assert(finiteInfinityBounds(rgb.r));
assert(finiteInfinityBounds(rgb.g));
assert(finiteInfinityBounds(rgb.b));

assert(fabs(rgb.r / float.max - expectedR) < 2e-6f);
assert(fabs(rgb.g / float.max - expectedG) < 2e-6f);
assert(fabs(rgb.b / float.max - expectedB) < 2e-6f);