https://bugs.kde.org/show_bug.cgi?id=528375

--- Comment #2 from Jozsef Tar <[email protected]> ---
DESCRIPTION

The sRGB inverse EOTF implementation in src/core/colorspace.cpp contains an
incorrect operation in its linear segment.

In `TransferFunction::sRGBinverseEOTF(double nits)`, the following code is used
when the normalized input is below the threshold of 0.0031308:

return std::max(normalized / 12.92, 0.0);

However, the linear segment of the inverse sRGB transfer function should
multiply the normalized linear-light input by 12.92, not divide it.

The expected implementation is:

return std::max(normalized * 12.92, 0.0);

For example, with a normalized linear-light input of 0.001:

- Current implementation: 0.001 / 12.92 ≈ 0.0000773994
- Expected implementation: 0.001 * 12.92 = 0.01292

The current implementation therefore produces an output approximately 167 times
smaller than the expected value in this linear segment.

Cross-validation against Weston

Weston's independent inverse sRGB transfer function implementation
(`sRGB_two_piece_inv()` in `tests/harness/color_util.c`) uses multiplication by
12.92 in the linear segment:

Weston's threshold (0.04045 / 12.92 ≈ 0.00313080495) is equivalent, within
rounding precision, to KWin's threshold of 0.0031308.

Weston source code:
https://fossies.org/linux/weston/tests/harness/color_util.c

Gamma table comparison (measured test results)

I performed tests comparing the generated gamma table values from Weston and
Plasma.

The following table shows selected measured results. The input indices are
8-bit values (0–255), while the corresponding gamma table output values are
16-bit values (0–65535).

The most noticeable discrepancy occurs between indices 10 and 11:

- At index 10, the Plasma output is 15, compared to the linear reference value
of 2570.
- At index 11, the Plasma output is already 2827, matching the reference value.

These measured results show a significant discrepancy at low input values,
consistent with the incorrect calculation in the linear segment of KWin's
inverse sRGB transfer function.

STEPS TO REPRODUCE

1. Use KWin 6.8.2 with the original sRGB inverse EOTF implementation.
2. Examine `TransferFunction::sRGBinverseEOTF()` in `src/core/colorspace.cpp`.
3. Evaluate the linear segment with a normalized input below 0.0031308, for
example 0.001.
4. Compare the result with the expected inverse sRGB calculation or Weston's
implementation.
5. Compare the generated gamma table values at low input indices.

OBSERVED RESULT

The function divides the normalized linear-light input by 12.92 in the linear
segment, resulting in an incorrect sRGB conversion.

For an input of 0.001, the function returns approximately 0.0000773994 instead
of 0.01292.

My gamma table tests also show a significant discrepancy at low input indices,
as illustrated above.

I reproduced the resulting issue on Fedora 44 running KDE Plasma Wayland.

EXPECTED RESULT

The linear segment of the inverse sRGB transfer function should multiply the
normalized linear-light input by 12.92:

```cpp
return std::max(normalized * 12.92, 0.0);
```

This is consistent with Weston's independent inverse sRGB implementation.

SOFTWARE/OS VERSIONS

Operating System: Fedora Linux 44

KDE Plasma Version: 6.8.2

KDE Frameworks Version: 6.31.0

Qt Version: 6.11.2

KWin Version: 6.8.2-3.fc44 (original Fedora package)

Session type: Wayland

ADDITIONAL INFORMATION

I built a locally patched KWin 6.8.2 RPM package using the proposed one-line
change.

After installing the patched package, the issue I was investigating disappeared
on my system.

Original Fedora package: 6.8.2-3.fc44

Locally patched package: 6.8.2-3.fc44.1

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to