GCC Code Coverage Report


Directory: ./
File: channeloutput/GammaLUT.h
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 27 33 81.8%
Functions: 6 6 100.0%
Branches: 19 30 63.3%

Line Branch Exec Source
1 #pragma once
2 /*
3 * This file is part of the Falcon Player (FPP) and is Copyright (C)
4 * 2013-2025 by the Falcon Player Developers.
5 *
6 * The Falcon Player (FPP) is free software, and is covered under
7 * multiple Open Source licenses. Please see the included 'LICENSES'
8 * file for descriptions of what files are covered by each license.
9 *
10 * This source file is covered under the LGPL v2.1 as described in the
11 * included LICENSE.LGPL file.
12 */
13
14 #include <cmath>
15 #include <cstdlib>
16
17 #include "fpp-json.h"
18
19 // The 256 entry gamma curve every matrix output builds from its "gamma" config
20 // value. Header only so the channel output plugins, which each link their own
21 // object list, pick it up without a new object to link.
22 namespace GammaLUT {
23
24 // Outputs fall back to their own default both when gamma is unconfigured and
25 // when the configured value is outside the range they accept, so the default is
26 // a per caller parameter. Written so NaN ("gamma": "nan") is out of range too:
27 // it fails every comparison, and as a gamma it built a curve that lit every
28 // channel at full brightness.
29 117 inline float Clamp(float gamma, float def) {
30
2/4
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 117 times.
117 if (!(gamma >= 0.01f && gamma <= 50.0f)) {
31 ✗ return def;
32 }
33 117 return gamma;
34 }
35
36 117 inline float ParseConfig(const Json::Value& config, float def) {
37 117 float gamma = def;
38
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 103 times.
117 if (config.isMember("gamma")) {
39
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 gamma = atof(config["gamma"].asString().c_str());
40 }
41 117 return Clamp(gamma, def);
42 }
43
44 // Full scale value a panel bit depth can carry. Depths of 8 or less drive the
45 // plain 8 bit range.
46 14 inline float MaxForColorDepth(int colorDepth) {
47
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
14 if (colorDepth > 8 && colorDepth <= 16) {
48 ✗ return (float)((1 << colorDepth) - 1);
49 }
50 14 return 255.0f;
51 }
52
53 // scale trims the whole curve, for a matrix that has to make up the difference
54 // when it shares hardware set up for a brighter one. floorLowEnd keeps a value
55 // that rounds to 0, but sits more than a quarter step above it, at 1 so the
56 // bottom of the curve does not go fully black.
57 template<typename T>
58 117 inline void Build(T* curve, float gamma, float max = 255.0f, float scale = 1.0f, bool floorLowEnd = false) {
59
2/2
✓ Branch 0 taken 29952 times.
✓ Branch 1 taken 117 times.
30069 for (int x = 0; x < 256; x++) {
60 29952 float f = x;
61 29952 f = max * std::pow(f / 255.0f, gamma) * scale;
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29952 times.
29952 if (f > max) {
63 ✗ f = max;
64 }
65
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29952 times.
29952 if (f < 0.0f) {
66 ✗ f = 0.0f;
67 }
68 29952 curve[x] = std::round(f);
69
5/6
✓ Branch 0 taken 3584 times.
✓ Branch 1 taken 26368 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3570 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
29952 if (floorLowEnd && curve[x] == 0 && f > 0.25) {
70 ✗ curve[x] = 1;
71 }
72 }
73 117 }
74
75 template<typename T>
76 14 inline void BuildForColorDepth(T* curve, float gamma, int colorDepth, float scale = 1.0f) {
77 14 Build(curve, gamma, MaxForColorDepth(colorDepth), scale, true);
78 // The two shallowest depths have no step low enough to render these values,
79 // so they take the first step the panel can actually show.
80
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 13 times.
14 if (colorDepth == 6) {
81 1 curve[2] = curve[4];
82 1 curve[3] = curve[4];
83
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 } else if (colorDepth == 7) {
84 ✗ curve[1] = curve[2];
85 }
86 14 }
87
88 } // namespace GammaLUT
89