Blender  V3.3
COM_ChromaMatteOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. */
3 
5 
6 namespace blender::compositor {
7 
9 {
13 
14  input_image_program_ = nullptr;
15  input_key_program_ = nullptr;
16  flags_.can_be_constant = true;
17 }
18 
20 {
21  input_image_program_ = this->get_input_socket_reader(0);
22  input_key_program_ = this->get_input_socket_reader(1);
23 }
24 
26 {
27  input_image_program_ = nullptr;
28  input_key_program_ = nullptr;
29 }
30 
32  float x,
33  float y,
35 {
36  float in_key[4];
37  float in_image[4];
38 
39  const float acceptance = settings_->t1; /* in radians */
40  const float cutoff = settings_->t2; /* in radians */
41  const float gain = settings_->fstrength;
42 
43  float x_angle, z_angle, alpha;
44  float theta, beta;
45  float kfg;
46 
47  input_key_program_->read_sampled(in_key, x, y, sampler);
48  input_image_program_->read_sampled(in_image, x, y, sampler);
49 
50  /* Store matte(alpha) value in [0] to go with
51  * #COM_SetAlphaMultiplyOperation and the Value output. */
52 
53  /* Algorithm from book "Video Demystified", does not include the spill reduction part. */
54  /* Find theta, the angle that the color space should be rotated based on key. */
55 
56  /* rescale to -1.0..1.0 */
57  // in_image[0] = (in_image[0] * 2.0f) - 1.0f; // UNUSED
58  in_image[1] = (in_image[1] * 2.0f) - 1.0f;
59  in_image[2] = (in_image[2] * 2.0f) - 1.0f;
60 
61  // in_key[0] = (in_key[0] * 2.0f) - 1.0f; // UNUSED
62  in_key[1] = (in_key[1] * 2.0f) - 1.0f;
63  in_key[2] = (in_key[2] * 2.0f) - 1.0f;
64 
65  theta = atan2(in_key[2], in_key[1]);
66 
67  /* Rotate the cb and cr into x/z space. */
68  x_angle = in_image[1] * cosf(theta) + in_image[2] * sinf(theta);
69  z_angle = in_image[2] * cosf(theta) - in_image[1] * sinf(theta);
70 
71  /* If within the acceptance angle. */
72  /* If kfg is <0 then the pixel is outside of the key color. */
73  kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f));
74 
75  if (kfg > 0.0f) { /* found a pixel that is within key color */
76  alpha = 1.0f - (kfg / gain);
77 
78  beta = atan2(z_angle, x_angle);
79 
80  /* if beta is within the cutoff angle */
81  if (fabsf(beta) < (cutoff / 2.0f)) {
82  alpha = 0.0f;
83  }
84 
85  /* don't make something that was more transparent less transparent */
86  if (alpha < in_image[3]) {
87  output[0] = alpha;
88  }
89  else {
90  output[0] = in_image[3];
91  }
92  }
93  else { /* Pixel is outside key color. */
94  output[0] = in_image[3]; /* Make pixel just as transparent as it was before. */
95  }
96 }
97 
99  const rcti &area,
101 {
102  const float acceptance = settings_->t1; /* In radians. */
103  const float cutoff = settings_->t2; /* In radians. */
104  const float gain = settings_->fstrength;
105  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
106  const float *in_image = it.in(0);
107  const float *in_key = it.in(1);
108 
109  /* Store matte(alpha) value in [0] to go with
110  * #COM_SetAlphaMultiplyOperation and the Value output. */
111 
112  /* Algorithm from book "Video Demystified", does not include the spill reduction part. */
113  /* Find theta, the angle that the color space should be rotated based on key. */
114 
115  /* Rescale to `-1.0..1.0`. */
116  // const float image_Y = (in_image[0] * 2.0f) - 1.0f; // UNUSED
117  const float image_cb = (in_image[1] * 2.0f) - 1.0f;
118  const float image_cr = (in_image[2] * 2.0f) - 1.0f;
119 
120  // const float key_Y = (in_key[0] * 2.0f) - 1.0f; // UNUSED
121  const float key_cb = (in_key[1] * 2.0f) - 1.0f;
122  const float key_cr = (in_key[2] * 2.0f) - 1.0f;
123 
124  const float theta = atan2(key_cr, key_cb);
125 
126  /* Rotate the cb and cr into x/z space. */
127  const float x_angle = image_cb * cosf(theta) + image_cr * sinf(theta);
128  const float z_angle = image_cr * cosf(theta) - image_cb * sinf(theta);
129 
130  /* If within the acceptance angle. */
131  /* If kfg is <0 then the pixel is outside of the key color. */
132  const float kfg = x_angle - (fabsf(z_angle) / tanf(acceptance / 2.0f));
133 
134  if (kfg > 0.0f) { /* Found a pixel that is within key color. */
135  const float beta = atan2(z_angle, x_angle);
136  float alpha = 1.0f - (kfg / gain);
137 
138  /* Ff beta is within the cutoff angle. */
139  if (fabsf(beta) < (cutoff / 2.0f)) {
140  alpha = 0.0f;
141  }
142 
143  /* Don't make something that was more transparent less transparent. */
144  it.out[0] = alpha < in_image[3] ? alpha : in_image[3];
145  }
146  else { /* Pixel is outside key color. */
147  it.out[0] = in_image[3]; /* Make pixel just as transparent as it was before. */
148  }
149  }
150 }
151 
152 } // namespace blender::compositor
_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
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
a MemoryBuffer contains access to the data of a chunk
void add_output_socket(DataType datatype)
SocketReader * get_input_socket_reader(unsigned int index)
void read_sampled(float result[4], float x, float y, PixelSampler sampler)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define tanf(x)
Definition: cuda/compat.h:104
depth_tx sampler(1, ImageType::FLOAT_2D, "combined_tx") .sampler(2
ccl_global KernelShaderEvalInput ccl_global float * output
#define fabsf(x)
Definition: metal/compat.h:219
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
Definition: rall1d.h:429
static void area(int d1, int d2, int e1, int e2, float weights[2])
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
static bNodeSocketTemplate inputs[]
ccl_device_inline float beta(float x, float y)
Definition: util/math.h:775