Blender  V3.3
COM_ConvertOperation.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2011 Blender Foundation. */
3 
4 #include "COM_ConvertOperation.h"
5 
6 #include "BLI_color.hh"
7 
8 #include "IMB_colormanagement.h"
9 
10 namespace blender::compositor {
11 
13 {
14  input_operation_ = nullptr;
15  flags_.can_be_constant = true;
16 }
17 
19 {
21 }
22 
24 {
25  input_operation_ = nullptr;
26 }
27 
29 {
30 }
31 
33  const rcti &area,
35 {
36  BuffersIterator<float> it = output->iterate_with(inputs, area);
38 }
39 
40 /* ******** Value to Color ******** */
41 
43 {
46 }
47 
49  float x,
50  float y,
52 {
53  float value;
55  output[0] = output[1] = output[2] = value;
56  output[3] = 1.0f;
57 }
58 
60 {
61  for (; !it.is_end(); ++it) {
62  it.out[0] = it.out[1] = it.out[2] = *it.in(0);
63  it.out[3] = 1.0f;
64  }
65 }
66 
67 /* ******** Color to Value ******** */
68 
70 {
73 }
74 
76  float x,
77  float y,
79 {
80  float input_color[4];
81  input_operation_->read_sampled(input_color, x, y, sampler);
82  output[0] = (input_color[0] + input_color[1] + input_color[2]) / 3.0f;
83 }
84 
86 {
87  for (; !it.is_end(); ++it) {
88  const float *in = it.in(0);
89  it.out[0] = (in[0] + in[1] + in[2]) / 3.0f;
90  }
91 }
92 
93 /* ******** Color to BW ******** */
94 
96 {
99 }
100 
102  float x,
103  float y,
105 {
106  float input_color[4];
107  input_operation_->read_sampled(input_color, x, y, sampler);
108  output[0] = IMB_colormanagement_get_luminance(input_color);
109 }
110 
112 {
113  for (; !it.is_end(); ++it) {
114  it.out[0] = IMB_colormanagement_get_luminance(it.in(0));
115  }
116 }
117 
118 /* ******** Color to Vector ******** */
119 
121 {
124 }
125 
127  float x,
128  float y,
130 {
131  float color[4];
134 }
135 
137 {
138  for (; !it.is_end(); ++it) {
139  copy_v3_v3(it.out, it.in(0));
140  }
141 }
142 
143 /* ******** Value to Vector ******** */
144 
146 {
149 }
150 
152  float x,
153  float y,
155 {
156  float value;
158  output[0] = output[1] = output[2] = value;
159 }
160 
162 {
163  for (; !it.is_end(); ++it) {
164  it.out[0] = it.out[1] = it.out[2] = *it.in(0);
165  }
166 }
167 
168 /* ******** Vector to Color ******** */
169 
171 {
174 }
175 
177  float x,
178  float y,
180 {
182  output[3] = 1.0f;
183 }
184 
186 {
187  for (; !it.is_end(); ++it) {
188  copy_v3_v3(it.out, it.in(0));
189  it.out[3] = 1.0f;
190  }
191 }
192 
193 /* ******** Vector to Value ******** */
194 
196 {
199 }
200 
202  float x,
203  float y,
205 {
206  float input[4];
208  output[0] = (input[0] + input[1] + input[2]) / 3.0f;
209 }
210 
212 {
213  for (; !it.is_end(); ++it) {
214  const float *in = it.in(0);
215  it.out[0] = (in[0] + in[1] + in[2]) / 3.0f;
216  }
217 }
218 
219 /* ******** RGB to YCC ******** */
220 
222 {
225 }
226 
228 {
229  switch (mode) {
230  case 0:
231  mode_ = BLI_YCC_ITU_BT601;
232  break;
233  case 2:
234  mode_ = BLI_YCC_JFIF_0_255;
235  break;
236  case 1:
237  default:
238  mode_ = BLI_YCC_ITU_BT709;
239  break;
240  }
241 }
242 
244  float x,
245  float y,
247 {
248  float input_color[4];
249  float color[3];
250 
251  input_operation_->read_sampled(input_color, x, y, sampler);
252  rgb_to_ycc(
253  input_color[0], input_color[1], input_color[2], &color[0], &color[1], &color[2], mode_);
254 
255  /* divided by 255 to normalize for viewing in */
256  /* R,G,B --> Y,Cb,Cr */
257  mul_v3_v3fl(output, color, 1.0f / 255.0f);
258  output[3] = input_color[3];
259 }
260 
262 {
264  hash_param(mode_);
265 }
266 
268 {
269  for (; !it.is_end(); ++it) {
270  const float *in = it.in(0);
271  rgb_to_ycc(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], mode_);
272 
273  /* Normalize for viewing (#rgb_to_ycc returns 0-255 values). */
274  mul_v3_fl(it.out, 1.0f / 255.0f);
275  it.out[3] = in[3];
276  }
277 }
278 
279 /* ******** YCC to RGB ******** */
280 
282 {
285 }
286 
288 {
289  switch (mode) {
290  case 0:
291  mode_ = BLI_YCC_ITU_BT601;
292  break;
293  case 2:
294  mode_ = BLI_YCC_JFIF_0_255;
295  break;
296  case 1:
297  default:
298  mode_ = BLI_YCC_ITU_BT709;
299  break;
300  }
301 }
302 
304  float x,
305  float y,
307 {
308  float input_color[4];
309  input_operation_->read_sampled(input_color, x, y, sampler);
310 
311  /* need to un-normalize the data */
312  /* R,G,B --> Y,Cb,Cr */
313  mul_v3_fl(input_color, 255.0f);
314 
315  ycc_to_rgb(
316  input_color[0], input_color[1], input_color[2], &output[0], &output[1], &output[2], mode_);
317  output[3] = input_color[3];
318 }
319 
321 {
323  hash_param(mode_);
324 }
325 
327 {
328  for (; !it.is_end(); ++it) {
329  const float *in = it.in(0);
330  /* Multiply by 255 to un-normalize (#ycc_to_rgb needs input values in 0-255 range). */
331  ycc_to_rgb(
332  in[0] * 255.0f, in[1] * 255.0f, in[2] * 255.0f, &it.out[0], &it.out[1], &it.out[2], mode_);
333  it.out[3] = in[3];
334  }
335 }
336 
337 /* ******** RGB to YUV ******** */
338 
340 {
343 }
344 
346  float x,
347  float y,
349 {
350  float input_color[4];
351  input_operation_->read_sampled(input_color, x, y, sampler);
352  rgb_to_yuv(input_color[0],
353  input_color[1],
354  input_color[2],
355  &output[0],
356  &output[1],
357  &output[2],
359  output[3] = input_color[3];
360 }
361 
363 {
364  for (; !it.is_end(); ++it) {
365  const float *in = it.in(0);
366  rgb_to_yuv(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709);
367  it.out[3] = in[3];
368  }
369 }
370 
371 /* ******** YUV to RGB ******** */
372 
374 {
377 }
378 
380  float x,
381  float y,
383 {
384  float input_color[4];
385  input_operation_->read_sampled(input_color, x, y, sampler);
386  yuv_to_rgb(input_color[0],
387  input_color[1],
388  input_color[2],
389  &output[0],
390  &output[1],
391  &output[2],
393  output[3] = input_color[3];
394 }
395 
397 {
398  for (; !it.is_end(); ++it) {
399  const float *in = it.in(0);
400  yuv_to_rgb(in[0], in[1], in[2], &it.out[0], &it.out[1], &it.out[2], BLI_YUV_ITU_BT709);
401  it.out[3] = in[3];
402  }
403 }
404 
405 /* ******** RGB to HSV ******** */
406 
408 {
411 }
412 
414  float x,
415  float y,
417 {
418  float input_color[4];
419  input_operation_->read_sampled(input_color, x, y, sampler);
420  rgb_to_hsv_v(input_color, output);
421  output[3] = input_color[3];
422 }
423 
425 {
426  for (; !it.is_end(); ++it) {
427  const float *in = it.in(0);
428  rgb_to_hsv_v(in, it.out);
429  it.out[3] = in[3];
430  }
431 }
432 
433 /* ******** HSV to RGB ******** */
434 
436 {
439 }
440 
442  float x,
443  float y,
445 {
446  float input_color[4];
447  input_operation_->read_sampled(input_color, x, y, sampler);
448  hsv_to_rgb_v(input_color, output);
449  output[0] = max_ff(output[0], 0.0f);
450  output[1] = max_ff(output[1], 0.0f);
451  output[2] = max_ff(output[2], 0.0f);
452  output[3] = input_color[3];
453 }
454 
456 {
457  for (; !it.is_end(); ++it) {
458  const float *in = it.in(0);
459  hsv_to_rgb_v(in, it.out);
460  it.out[0] = max_ff(it.out[0], 0.0f);
461  it.out[1] = max_ff(it.out[1], 0.0f);
462  it.out[2] = max_ff(it.out[2], 0.0f);
463  it.out[3] = in[3];
464  }
465 }
466 
467 /* ******** RGB to HSL ******** */
468 
470 {
473 }
474 
476  float x,
477  float y,
479 {
480  float input_color[4];
481  input_operation_->read_sampled(input_color, x, y, sampler);
482  rgb_to_hsl_v(input_color, output);
483  output[3] = input_color[3];
484 }
485 
487 {
488  for (; !it.is_end(); ++it) {
489  const float *in = it.in(0);
490  rgb_to_hsl_v(in, it.out);
491  it.out[3] = in[3];
492  }
493 }
494 
495 /* ******** HSL to RGB ******** */
496 
498 {
501 }
502 
504  float x,
505  float y,
507 {
508  float input_color[4];
509  input_operation_->read_sampled(input_color, x, y, sampler);
510  hsl_to_rgb_v(input_color, output);
511  output[0] = max_ff(output[0], 0.0f);
512  output[1] = max_ff(output[1], 0.0f);
513  output[2] = max_ff(output[2], 0.0f);
514  output[3] = input_color[3];
515 }
516 
518 {
519  for (; !it.is_end(); ++it) {
520  const float *in = it.in(0);
521  hsl_to_rgb_v(in, it.out);
522  it.out[0] = max_ff(it.out[0], 0.0f);
523  it.out[1] = max_ff(it.out[1], 0.0f);
524  it.out[2] = max_ff(it.out[2], 0.0f);
525  it.out[3] = in[3];
526  }
527 }
528 
529 /* ******** Premul to Straight ******** */
530 
532 {
535 }
536 
538  float x,
539  float y,
541 {
544  ColorSceneLinear4f<eAlpha::Straight> converted = input.unpremultiply_alpha();
545  copy_v4_v4(output, converted);
546 }
547 
549 {
550  for (; !it.is_end(); ++it) {
552  }
553 }
554 
555 /* ******** Straight to Premul ******** */
556 
558 {
561 }
562 
564  float x,
565  float y,
567 {
570  ColorSceneLinear4f<eAlpha::Premultiplied> converted = input.premultiply_alpha();
571  copy_v4_v4(output, converted);
572 }
573 
575 {
576  for (; !it.is_end(); ++it) {
578  }
579 }
580 
581 /* ******** Separate Channels ******** */
582 
584 {
587  input_operation_ = nullptr;
588 }
590 {
591  input_operation_ = this->get_input_socket_reader(0);
592 }
593 
595 {
596  input_operation_ = nullptr;
597 }
598 
600  float x,
601  float y,
603 {
604  float input[4];
605  input_operation_->read_sampled(input, x, y, sampler);
606  output[0] = input[channel_];
607 }
608 
610  const rcti &area,
612 {
613  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
614  it.out[0] = it.in(0)[channel_];
615  }
616 }
617 
618 /* ******** Combine Channels ******** */
619 
621 {
627  this->set_canvas_input_index(0);
628  input_channel1_operation_ = nullptr;
629  input_channel2_operation_ = nullptr;
630  input_channel3_operation_ = nullptr;
631  input_channel4_operation_ = nullptr;
632 }
633 
635 {
636  input_channel1_operation_ = this->get_input_socket_reader(0);
637  input_channel2_operation_ = this->get_input_socket_reader(1);
638  input_channel3_operation_ = this->get_input_socket_reader(2);
639  input_channel4_operation_ = this->get_input_socket_reader(3);
640 }
641 
643 {
644  input_channel1_operation_ = nullptr;
645  input_channel2_operation_ = nullptr;
646  input_channel3_operation_ = nullptr;
647  input_channel4_operation_ = nullptr;
648 }
649 
651  float x,
652  float y,
654 {
655  float input[4];
656  if (input_channel1_operation_) {
657  input_channel1_operation_->read_sampled(input, x, y, sampler);
658  output[0] = input[0];
659  }
660  if (input_channel2_operation_) {
661  input_channel2_operation_->read_sampled(input, x, y, sampler);
662  output[1] = input[0];
663  }
664  if (input_channel3_operation_) {
665  input_channel3_operation_->read_sampled(input, x, y, sampler);
666  output[2] = input[0];
667  }
668  if (input_channel4_operation_) {
669  input_channel4_operation_->read_sampled(input, x, y, sampler);
670  output[3] = input[0];
671  }
672 }
673 
675  const rcti &area,
677 {
678  for (BuffersIterator<float> it = output->iterate_with(inputs, area); !it.is_end(); ++it) {
679  it.out[0] = *it.in(0);
680  it.out[1] = *it.in(1);
681  it.out[2] = *it.in(2);
682  it.out[3] = *it.in(3);
683  }
684 }
685 
686 } // namespace blender::compositor
MINLINE float max_ff(float a, float b)
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition: math_color.c:49
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
Definition: math_color.c:232
#define BLI_YUV_ITU_BT709
#define BLI_YCC_JFIF_0_255
void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
Definition: math_color.c:54
void ycc_to_rgb(float y, float cb, float cr, float *r_r, float *r_g, float *r_b, int colorspace)
Definition: math_color.c:142
#define BLI_YCC_ITU_BT601
void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr, int colorspace)
Definition: math_color.c:107
void rgb_to_yuv(float r, float g, float b, float *r_y, float *r_u, float *r_v, int colorspace)
Definition: math_color.c:59
void yuv_to_rgb(float y, float u, float v, float *r_r, float *r_g, float *r_b, int colorspace)
Definition: math_color.c:83
void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
Definition: math_color.c:292
#define BLI_YCC_ITU_BT709
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
_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])
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert a color
ColorSceneLinear4f< eAlpha::Premultiplied > premultiply_alpha() const
Definition: BLI_color.hh:184
ColorSceneLinear4f< eAlpha::Straight > unpremultiply_alpha() const
Definition: BLI_color.hh:201
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) final
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(BuffersIterator< float > &it) override
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
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)
void set_canvas_input_index(unsigned int index)
set the index of the input socket that will determine the canvas of this operation
void execute_pixel_sampled(float output[4], float x, float y, PixelSampler sampler) override
calculate a single pixel
void update_memory_buffer_partial(MemoryBuffer *output, const rcti &area, Span< MemoryBuffer * > inputs) override
depth_tx sampler(1, ImageType::FLOAT_2D, "combined_tx") .sampler(2
@ Vector
Vector data type.
ccl_global KernelShaderEvalInput ccl_global float * output
ccl_global KernelShaderEvalInput * input
static void area(int d1, int d2, int e1, int e2, float weights[2])
typename BuffersIteratorBuilder< T >::Iterator BuffersIterator
static bNodeSocketTemplate inputs[]