Blender  V2.93
COM_ColorCorrectionOperation.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * Copyright 2011, Blender Foundation.
17  */
18 
20 #include "BLI_math.h"
21 
22 #include "IMB_colormanagement.h"
23 
24 namespace blender::compositor {
25 
27 {
31  this->m_inputImage = nullptr;
32  this->m_inputMask = nullptr;
33  this->m_redChannelEnabled = true;
34  this->m_greenChannelEnabled = true;
35  this->m_blueChannelEnabled = true;
36 }
38 {
39  this->m_inputImage = this->getInputSocketReader(0);
40  this->m_inputMask = this->getInputSocketReader(1);
41 }
42 
43 /* Calculate x^y if the function is defined. Otherwise return the given fallback value. */
44 BLI_INLINE float color_correct_powf_safe(const float x, const float y, const float fallback_value)
45 {
46  if (x < 0) {
47  return fallback_value;
48  }
49  return powf(x, y);
50 }
51 
53  float x,
54  float y,
55  PixelSampler sampler)
56 {
57  float inputImageColor[4];
58  float inputMask[4];
59  this->m_inputImage->readSampled(inputImageColor, x, y, sampler);
60  this->m_inputMask->readSampled(inputMask, x, y, sampler);
61 
62  float level = (inputImageColor[0] + inputImageColor[1] + inputImageColor[2]) / 3.0f;
63  float contrast = this->m_data->master.contrast;
64  float saturation = this->m_data->master.saturation;
65  float gamma = this->m_data->master.gamma;
66  float gain = this->m_data->master.gain;
67  float lift = this->m_data->master.lift;
68  float r, g, b;
69 
70  float value = inputMask[0];
71  value = MIN2(1.0f, value);
72  const float mvalue = 1.0f - value;
73 
74  float levelShadows = 0.0;
75  float levelMidtones = 0.0;
76  float levelHighlights = 0.0;
77 #define MARGIN 0.10f
78 #define MARGIN_DIV (0.5f / MARGIN)
79  if (level < this->m_data->startmidtones - MARGIN) {
80  levelShadows = 1.0f;
81  }
82  else if (level < this->m_data->startmidtones + MARGIN) {
83  levelMidtones = ((level - this->m_data->startmidtones) * MARGIN_DIV) + 0.5f;
84  levelShadows = 1.0f - levelMidtones;
85  }
86  else if (level < this->m_data->endmidtones - MARGIN) {
87  levelMidtones = 1.0f;
88  }
89  else if (level < this->m_data->endmidtones + MARGIN) {
90  levelHighlights = ((level - this->m_data->endmidtones) * MARGIN_DIV) + 0.5f;
91  levelMidtones = 1.0f - levelHighlights;
92  }
93  else {
94  levelHighlights = 1.0f;
95  }
96 #undef MARGIN
97 #undef MARGIN_DIV
98  contrast *= (levelShadows * this->m_data->shadows.contrast) +
99  (levelMidtones * this->m_data->midtones.contrast) +
100  (levelHighlights * this->m_data->highlights.contrast);
101  saturation *= (levelShadows * this->m_data->shadows.saturation) +
102  (levelMidtones * this->m_data->midtones.saturation) +
103  (levelHighlights * this->m_data->highlights.saturation);
104  gamma *= (levelShadows * this->m_data->shadows.gamma) +
105  (levelMidtones * this->m_data->midtones.gamma) +
106  (levelHighlights * this->m_data->highlights.gamma);
107  gain *= (levelShadows * this->m_data->shadows.gain) +
108  (levelMidtones * this->m_data->midtones.gain) +
109  (levelHighlights * this->m_data->highlights.gain);
110  lift += (levelShadows * this->m_data->shadows.lift) +
111  (levelMidtones * this->m_data->midtones.lift) +
112  (levelHighlights * this->m_data->highlights.lift);
113 
114  float invgamma = 1.0f / gamma;
115  float luma = IMB_colormanagement_get_luminance(inputImageColor);
116 
117  r = inputImageColor[0];
118  g = inputImageColor[1];
119  b = inputImageColor[2];
120 
121  r = (luma + saturation * (r - luma));
122  g = (luma + saturation * (g - luma));
123  b = (luma + saturation * (b - luma));
124 
125  r = 0.5f + ((r - 0.5f) * contrast);
126  g = 0.5f + ((g - 0.5f) * contrast);
127  b = 0.5f + ((b - 0.5f) * contrast);
128 
129  /* Check for negative values to avoid nan. */
130  r = color_correct_powf_safe(r * gain + lift, invgamma, r);
131  g = color_correct_powf_safe(g * gain + lift, invgamma, g);
132  b = color_correct_powf_safe(b * gain + lift, invgamma, b);
133 
134  // mix with mask
135  r = mvalue * inputImageColor[0] + value * r;
136  g = mvalue * inputImageColor[1] + value * g;
137  b = mvalue * inputImageColor[2] + value * b;
138 
139  if (this->m_redChannelEnabled) {
140  output[0] = r;
141  }
142  else {
143  output[0] = inputImageColor[0];
144  }
145  if (this->m_greenChannelEnabled) {
146  output[1] = g;
147  }
148  else {
149  output[1] = inputImageColor[1];
150  }
151  if (this->m_blueChannelEnabled) {
152  output[2] = b;
153  }
154  else {
155  output[2] = inputImageColor[2];
156  }
157  output[3] = inputImageColor[3];
158 }
159 
161 {
162  this->m_inputImage = nullptr;
163  this->m_inputMask = nullptr;
164 }
165 
166 } // namespace blender::compositor
#define BLI_INLINE
#define MIN2(a, b)
#define MARGIN
#define MARGIN_DIV
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3])
#define output
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override
void readSampled(float result[4], float x, float y, PixelSampler sampler)
void addInputSocket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
void addOutputSocket(DataType datatype)
SocketReader * getInputSocketReader(unsigned int inputSocketindex)
#define powf(x, y)
BLI_INLINE float color_correct_powf_safe(const float x, const float y, const float fallback_value)
ColorCorrectionData shadows
ColorCorrectionData midtones
ColorCorrectionData master
ColorCorrectionData highlights