Overte C++ Documentation
ColorUtils.h
1 //
2 // ColorUtils.h
3 // libraries/shared/src
4 //
5 // Created by Sam Gateau on 10/24/15.
6 // Copyright 2014 High Fidelity, Inc.
7 //
8 // Distributed under the Apache License, Version 2.0.
9 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
10 //
11 
12 #ifndef hifi_ColorUtils_h
13 #define hifi_ColorUtils_h
14 
15 #include <glm/glm.hpp>
16 
17 #include "SharedUtil.h"
18 
19 #include "DependencyManager.h"
20 
21 extern const float srgbToLinearLookupTable[256];
22 
23 class ColorUtils {
24 public:
25  inline static glm::vec3 toVec3(const glm::u8vec3& color);
26 
27  // Convert to gamma 2.2 space from linear
28  inline static glm::vec3 toGamma22Vec3(const glm::vec3& linear);
29 
30  // Convert from sRGB gamma space to linear.
31  // This is pretty different from converting from 2.2.
32  inline static glm::vec3 sRGBToLinearVec3(const glm::vec3& srgb);
33  inline static glm::vec3 tosRGBVec3(const glm::vec3& srgb);
34 
35  inline static glm::vec4 sRGBToLinearVec4(const glm::vec4& srgb);
36  inline static glm::vec4 tosRGBVec4(const glm::vec4& srgb);
37 
38  inline static float sRGBToLinearFloat(const float& srgb);
39  inline static float sRGB8ToLinearFloat(const uint8_t srgb);
40  inline static float tosRGBFloat(const float& linear);
41 };
42 
43 inline glm::vec3 ColorUtils::toVec3(const glm::u8vec3& color) {
44  const float ONE_OVER_255 = 1.0f / 255.0f;
45  return glm::vec3(color.x * ONE_OVER_255, color.y * ONE_OVER_255, color.z * ONE_OVER_255);
46 }
47 
48 inline glm::vec3 ColorUtils::toGamma22Vec3(const glm::vec3& linear) {
49  const float INV_GAMMA_22 = 1.0f / 2.2f;
50  // Couldn't find glm::pow(vec3, vec3) ? so did it myself...
51  return glm::vec3(glm::pow(linear.x, INV_GAMMA_22), glm::pow(linear.y, INV_GAMMA_22), glm::pow(linear.z, INV_GAMMA_22));
52 }
53 
54 // Convert from sRGB color space to linear color space.
55 inline glm::vec3 ColorUtils::sRGBToLinearVec3(const glm::vec3& srgb) {
56  return glm::vec3(sRGBToLinearFloat(srgb.x), sRGBToLinearFloat(srgb.y), sRGBToLinearFloat(srgb.z));
57 }
58 
59 // Convert from linear color space to sRGB color space.
60 inline glm::vec3 ColorUtils::tosRGBVec3(const glm::vec3& linear) {
61  return glm::vec3(tosRGBFloat(linear.x), tosRGBFloat(linear.y), tosRGBFloat(linear.z));
62 }
63 
64 // Convert from sRGB color space with alpha to linear color space with alpha.
65 inline glm::vec4 ColorUtils::sRGBToLinearVec4(const glm::vec4& srgb) {
66  return glm::vec4(sRGBToLinearFloat(srgb.x), sRGBToLinearFloat(srgb.y), sRGBToLinearFloat(srgb.z), srgb.w);
67 }
68 
69 // Convert from linear color space with alpha to sRGB color space with alpha.
70 inline glm::vec4 ColorUtils::tosRGBVec4(const glm::vec4& linear) {
71  return glm::vec4(tosRGBFloat(linear.x), tosRGBFloat(linear.y), tosRGBFloat(linear.z), linear.w);
72 }
73 
74 // This is based upon the conversions found in section 8.24 of the OpenGL 4.4 4.4 specification.
75 // glm::pow(color, 2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers.
76 inline float ColorUtils::sRGBToLinearFloat(const float &srgb) {
77  const float SRGB_ELBOW = 0.04045f;
78  float linearValue = 0.0f;
79 
80  // This should mirror the conversion table found in section 8.24: sRGB Texture Color Conversion
81  if (srgb <= SRGB_ELBOW) {
82  linearValue = srgb / 12.92f;
83  } else {
84  linearValue = powf(((srgb + 0.055f) / 1.055f), 2.4f);
85  }
86 
87  return linearValue;
88 }
89 inline float ColorUtils::sRGB8ToLinearFloat(const uint8_t srgb) {
90  return srgbToLinearLookupTable[srgb];
91 }
92 
93 // This is based upon the conversions found in section 17.3.9 of the OpenGL 4.4 specification.
94 // glm::pow(color, 1.0f/2.2f) is approximate, and will cause subtle differences when used with sRGB framebuffers.
95 inline float ColorUtils::tosRGBFloat(const float &linear) {
96  const float SRGB_ELBOW_INV = 0.0031308f;
97  float sRGBValue = 0.0f;
98 
99  // This should mirror the conversion table found in section 17.3.9: sRGB Conversion
100  if (linear <= 0.0f) {
101  sRGBValue = 0.0f;
102  } else if (0 < linear && linear < SRGB_ELBOW_INV) {
103  sRGBValue = 12.92f * linear;
104  } else if (SRGB_ELBOW_INV <= linear && linear < 1) {
105  sRGBValue = 1.055f * powf(linear, 0.41666f) - 0.055f;
106  } else {
107  sRGBValue = 1.0f;
108  }
109 
110  return sRGBValue;
111 }
112 
113 #endif // hifi_ColorUtils_h