Blender V4.3
COM_KeyingOperation.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2012 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BLI_math_geom.h"
8
9namespace blender::compositor {
10
11static float get_pixel_saturation(const float pixel_color[4],
12 float screen_balance,
13 int primary_channel)
14{
15 const int other_1 = (primary_channel + 1) % 3;
16 const int other_2 = (primary_channel + 2) % 3;
17
18 const int min_channel = std::min(other_1, other_2);
19 const int max_channel = std::max(other_1, other_2);
20
21 const float val = pixel_color[max_channel] +
22 screen_balance * (pixel_color[min_channel] - pixel_color[max_channel]);
23
24 return (pixel_color[primary_channel] - val) * fabsf(1.0f - val);
25}
26
37
39 const rcti &area,
41{
42 for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
43 const float *pixel_color = it.in(0);
44 const float *screen_color = it.in(1);
45
46 const int primary_channel = max_axis_v3(screen_color);
47 const float min_pixel_color = min_fff(pixel_color[0], pixel_color[1], pixel_color[2]);
48
49 if (min_pixel_color > 1.0f) {
50 /* Overexposure doesn't happen on screen itself and usually happens
51 * on light sources in the shot, this need to be checked separately
52 * because saturation and falloff calculation is based on the fact
53 * that pixels are not overexposed.
54 */
55 it.out[0] = 1.0f;
56 }
57 else {
58 const float saturation = get_pixel_saturation(pixel_color, screen_balance_, primary_channel);
59 const float screen_saturation = get_pixel_saturation(
60 screen_color, screen_balance_, primary_channel);
61
62 if (saturation < 0) {
63 /* Means main channel of pixel is different from screen,
64 * assume this is completely a foreground.
65 */
66 it.out[0] = 1.0f;
67 }
68 else if (saturation >= screen_saturation) {
69 /* Matched main channels and higher saturation on pixel
70 * is treated as completely background.
71 */
72 it.out[0] = 0.0f;
73 }
74 else {
75 /* Nice alpha falloff on edges. */
76 const float distance = 1.0f - saturation / screen_saturation;
77 it.out[0] = distance;
78 }
79 }
80 }
81}
82
83} // namespace blender::compositor
MINLINE float min_fff(float a, float b, float c)
MINLINE int max_axis_v3(const float vec[3])
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
a MemoryBuffer contains access to the data
void add_output_socket(DataType datatype)
void add_input_socket(DataType datatype, ResizeMode resize_mode=ResizeMode::Center)
#define fabsf(x)
static float get_pixel_saturation(const float pixel_color[4], float screen_balance, int primary_channel)
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
float distance(float a, float b)