Blender V4.3
mathutils_Color.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10
11#include <Python.h>
12
13#include "mathutils.hh"
14
15#include "BLI_utildefines.h"
16
19
20#ifndef MATH_STANDALONE
21# include "IMB_colormanagement.hh"
22#endif
23
24#ifndef MATH_STANDALONE
25# include "BLI_dynstr.h"
26#endif
27
28#define COLOR_SIZE 3
29
30/* -------------------------------------------------------------------- */
33
37static PyObject *Color_to_tuple_ex(ColorObject *self, int ndigits)
38{
39 PyObject *ret;
40 int i;
41
42 ret = PyTuple_New(COLOR_SIZE);
43
44 if (ndigits >= 0) {
45 for (i = 0; i < COLOR_SIZE; i++) {
46 PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round(double(self->col[i]), ndigits)));
47 }
48 }
49 else {
50 for (i = 0; i < COLOR_SIZE; i++) {
51 PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->col[i]));
52 }
53 }
54
55 return ret;
56}
57
59
60/* -------------------------------------------------------------------- */
63
64static PyObject *Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
65{
66 float col[3] = {0.0f, 0.0f, 0.0f};
67
68 if (kwds && PyDict_Size(kwds)) {
69 PyErr_SetString(PyExc_TypeError,
70 "mathutils.Color(): "
71 "takes no keyword args");
72 return nullptr;
73 }
74
75 switch (PyTuple_GET_SIZE(args)) {
76 case 0:
77 break;
78 case 1:
80 col, COLOR_SIZE, COLOR_SIZE, PyTuple_GET_ITEM(args, 0), "mathutils.Color()") == -1)
81 {
82 return nullptr;
83 }
84 break;
85 default:
86 PyErr_SetString(PyExc_TypeError,
87 "mathutils.Color(): "
88 "more than a single arg given");
89 return nullptr;
90 }
91 return Color_CreatePyObject(col, type);
92}
93
95
96/* -------------------------------------------------------------------- */
99
100#ifndef MATH_STANDALONE
101
103 /* Wrap. */
104 Color_from_scene_linear_to_srgb_doc,
105 ".. function:: from_scene_linear_to_srgb()\n"
106 "\n"
107 " Convert from scene linear to sRGB color space.\n"
108 "\n"
109 " :return: A color in sRGB color space.\n"
110 " :rtype: :class:`Color`\n");
112{
113 float col[3];
115 return Color_CreatePyObject(col, Py_TYPE(self));
116}
117
119 /* Wrap. */
120 Color_from_srgb_to_scene_linear_doc,
121 ".. function:: from_srgb_to_scene_linear()\n"
122 "\n"
123 " Convert from sRGB to scene linear color space.\n"
124 "\n"
125 " :return: A color in scene linear color space.\n"
126 " :rtype: :class:`Color`\n");
128{
129 float col[3];
131 return Color_CreatePyObject(col, Py_TYPE(self));
132}
133
135 /* Wrap. */
136 Color_from_scene_linear_to_xyz_d65_doc,
137 ".. function:: from_scene_linear_to_xyz_d65()\n"
138 "\n"
139 " Convert from scene linear to CIE XYZ (Illuminant D65) color space.\n"
140 "\n"
141 " :return: A color in XYZ color space.\n"
142 " :rtype: :class:`Color`\n");
144{
145 float col[3];
147 return Color_CreatePyObject(col, Py_TYPE(self));
148}
149
151 /* Wrap. */
152 Color_from_xyz_d65_to_scene_linear_doc,
153 ".. function:: from_xyz_d65_to_scene_linear()\n"
154 "\n"
155 " Convert from CIE XYZ (Illuminant D65) to scene linear color space.\n"
156 "\n"
157 " :return: A color in scene linear color space.\n"
158 " :rtype: :class:`Color`\n");
160{
161 float col[3];
163 return Color_CreatePyObject(col, Py_TYPE(self));
164}
165
167 /* Wrap. */
168 Color_from_scene_linear_to_aces_doc,
169 ".. function:: from_scene_linear_to_aces()\n"
170 "\n"
171 " Convert from scene linear to ACES2065-1 linear color space.\n"
172 "\n"
173 " :return: A color in ACES2065-1 linear color space.\n"
174 " :rtype: :class:`Color`\n");
176{
177 float col[3];
179 return Color_CreatePyObject(col, Py_TYPE(self));
180}
181
183 /* Wrap. */
184 Color_from_aces_to_scene_linear_doc,
185 ".. function:: from_aces_to_scene_linear()\n"
186 "\n"
187 " Convert from ACES2065-1 linear to scene linear color space.\n"
188 "\n"
189 " :return: A color in scene linear color space.\n"
190 " :rtype: :class:`Color`\n");
192{
193 float col[3];
195 return Color_CreatePyObject(col, Py_TYPE(self));
196}
197
199 /* Wrap. */
200 Color_from_scene_linear_to_rec709_linear_doc,
201 ".. function:: from_scene_linear_to_rec709_linear()\n"
202 "\n"
203 " Convert from scene linear to Rec.709 linear color space.\n"
204 "\n"
205 " :return: A color in Rec.709 linear color space.\n"
206 " :rtype: :class:`Color`\n");
213
215 /* Wrap. */
216 Color_from_rec709_linear_to_scene_linear_doc,
217 ".. function:: from_rec709_linear_to_scene_linear()\n"
218 "\n"
219 " Convert from Rec.709 linear color space to scene linear color space.\n"
220 "\n"
221 " :return: A color in scene linear color space.\n"
222 " :rtype: :class:`Color`\n");
229
230#endif /* !MATH_STANDALONE */
231
233
234/* -------------------------------------------------------------------- */
237
239 /* Wrap. */
240 Color_copy_doc,
241 ".. function:: copy()\n"
242 "\n"
243 " Returns a copy of this color.\n"
244 "\n"
245 " :return: A copy of the color.\n"
246 " :rtype: :class:`Color`\n"
247 "\n"
248 " .. note:: use this to get a copy of a wrapped color with\n"
249 " no reference to the original data.\n");
250static PyObject *Color_copy(ColorObject *self)
251{
252 if (BaseMath_ReadCallback(self) == -1) {
253 return nullptr;
254 }
255
256 return Color_CreatePyObject(self->col, Py_TYPE(self));
257}
258static PyObject *Color_deepcopy(ColorObject *self, PyObject *args)
259{
260 if (!PyC_CheckArgs_DeepCopy(args)) {
261 return nullptr;
262 }
263 return Color_copy(self);
264}
265
267
268/* -------------------------------------------------------------------- */
271
272static PyObject *Color_repr(ColorObject *self)
273{
274 PyObject *ret, *tuple;
275
276 if (BaseMath_ReadCallback(self) == -1) {
277 return nullptr;
278 }
279
280 tuple = Color_to_tuple_ex(self, -1);
281
282 ret = PyUnicode_FromFormat("Color(%R)", tuple);
283
284 Py_DECREF(tuple);
285 return ret;
286}
287
288#ifndef MATH_STANDALONE
289static PyObject *Color_str(ColorObject *self)
290{
291 DynStr *ds;
292
293 if (BaseMath_ReadCallback(self) == -1) {
294 return nullptr;
295 }
296
297 ds = BLI_dynstr_new();
298
300 ds, "<Color (r=%.4f, g=%.4f, b=%.4f)>", self->col[0], self->col[1], self->col[2]);
301
302 return mathutils_dynstr_to_py(ds); /* frees ds */
303}
304#endif
305
307
308/* -------------------------------------------------------------------- */
311
312static PyObject *Color_richcmpr(PyObject *a, PyObject *b, int op)
313{
314 PyObject *res;
315 int ok = -1; /* zero is true */
316
318 ColorObject *colA = (ColorObject *)a;
319 ColorObject *colB = (ColorObject *)b;
320
321 if (BaseMath_ReadCallback(colA) == -1 || BaseMath_ReadCallback(colB) == -1) {
322 return nullptr;
323 }
324
325 ok = EXPP_VectorsAreEqual(colA->col, colB->col, COLOR_SIZE, 1) ? 0 : -1;
326 }
327
328 switch (op) {
329 case Py_NE:
330 ok = !ok;
332 case Py_EQ:
333 res = ok ? Py_False : Py_True;
334 break;
335
336 case Py_LT:
337 case Py_LE:
338 case Py_GT:
339 case Py_GE:
340 res = Py_NotImplemented;
341 break;
342 default:
343 PyErr_BadArgument();
344 return nullptr;
345 }
346
347 return Py_NewRef(res);
348}
349
351
352/* -------------------------------------------------------------------- */
355
356static Py_hash_t Color_hash(ColorObject *self)
357{
358 if (BaseMath_ReadCallback(self) == -1) {
359 return -1;
360 }
361
363 return -1;
364 }
365
367}
368
370
371/* -------------------------------------------------------------------- */
374
376static Py_ssize_t Color_len(ColorObject * /*self*/)
377{
378 return COLOR_SIZE;
379}
380
382static PyObject *Color_item(ColorObject *self, Py_ssize_t i)
383{
384 if (i < 0) {
385 i = COLOR_SIZE - i;
386 }
387
388 if (i < 0 || i >= COLOR_SIZE) {
389 PyErr_SetString(PyExc_IndexError,
390 "color[item]: "
391 "array index out of range");
392 return nullptr;
393 }
394
395 if (BaseMath_ReadIndexCallback(self, i) == -1) {
396 return nullptr;
397 }
398
399 return PyFloat_FromDouble(self->col[i]);
400}
401
403static int Color_ass_item(ColorObject *self, Py_ssize_t i, PyObject *value)
404{
405 float f;
406
407 if (BaseMath_Prepare_ForWrite(self) == -1) {
408 return -1;
409 }
410
411 f = PyFloat_AsDouble(value);
412 if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */
413 PyErr_SetString(PyExc_TypeError,
414 "color[item] = x: "
415 "assigned value not a number");
416 return -1;
417 }
418
419 if (i < 0) {
420 i = COLOR_SIZE - i;
421 }
422
423 if (i < 0 || i >= COLOR_SIZE) {
424 PyErr_SetString(PyExc_IndexError,
425 "color[item] = x: "
426 "array assignment index out of range");
427 return -1;
428 }
429
430 self->col[i] = f;
431
432 if (BaseMath_WriteIndexCallback(self, i) == -1) {
433 return -1;
434 }
435
436 return 0;
437}
438
440static PyObject *Color_slice(ColorObject *self, int begin, int end)
441{
442 PyObject *tuple;
443 int count;
444
445 if (BaseMath_ReadCallback(self) == -1) {
446 return nullptr;
447 }
448
449 CLAMP(begin, 0, COLOR_SIZE);
450 if (end < 0) {
451 end = (COLOR_SIZE + 1) + end;
452 }
453 CLAMP(end, 0, COLOR_SIZE);
454 begin = std::min(begin, end);
455
456 tuple = PyTuple_New(end - begin);
457 for (count = begin; count < end; count++) {
458 PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->col[count]));
459 }
460
461 return tuple;
462}
463
465static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
466{
467 int i, size;
468 float col[COLOR_SIZE];
469
471 return -1;
472 }
473
474 CLAMP(begin, 0, COLOR_SIZE);
475 if (end < 0) {
476 end = (COLOR_SIZE + 1) + end;
477 }
478 CLAMP(end, 0, COLOR_SIZE);
479 begin = std::min(begin, end);
480
481 if ((size = mathutils_array_parse(col, 0, COLOR_SIZE, seq, "mathutils.Color[begin:end] = []")) ==
482 -1)
483 {
484 return -1;
485 }
486
487 if (size != (end - begin)) {
488 PyErr_SetString(PyExc_ValueError,
489 "color[begin:end] = []: "
490 "size mismatch in slice assignment");
491 return -1;
492 }
493
494 for (i = 0; i < COLOR_SIZE; i++) {
495 self->col[begin + i] = col[i];
496 }
497
499 return 0;
500}
501
503static PyObject *Color_subscript(ColorObject *self, PyObject *item)
504{
505 if (PyIndex_Check(item)) {
506 Py_ssize_t i;
507 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
508 if (i == -1 && PyErr_Occurred()) {
509 return nullptr;
510 }
511 if (i < 0) {
512 i += COLOR_SIZE;
513 }
514 return Color_item(self, i);
515 }
516 if (PySlice_Check(item)) {
517 Py_ssize_t start, stop, step, slicelength;
518
519 if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) {
520 return nullptr;
521 }
522
523 if (slicelength <= 0) {
524 return PyTuple_New(0);
525 }
526 if (step == 1) {
527 return Color_slice(self, start, stop);
528 }
529
530 PyErr_SetString(PyExc_IndexError, "slice steps not supported with color");
531 return nullptr;
532 }
533
534 PyErr_Format(
535 PyExc_TypeError, "color indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
536 return nullptr;
537}
538
540static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
541{
542 if (PyIndex_Check(item)) {
543 Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
544 if (i == -1 && PyErr_Occurred()) {
545 return -1;
546 }
547 if (i < 0) {
548 i += COLOR_SIZE;
549 }
550 return Color_ass_item(self, i, value);
551 }
552 if (PySlice_Check(item)) {
553 Py_ssize_t start, stop, step, slicelength;
554
555 if (PySlice_GetIndicesEx(item, COLOR_SIZE, &start, &stop, &step, &slicelength) < 0) {
556 return -1;
557 }
558
559 if (step == 1) {
560 return Color_ass_slice(self, start, stop, value);
561 }
562
563 PyErr_SetString(PyExc_IndexError, "slice steps not supported with color");
564 return -1;
565 }
566
567 PyErr_Format(
568 PyExc_TypeError, "color indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
569 return -1;
570}
571
573
574/* -------------------------------------------------------------------- */
577
579static PyObject *Color_add(PyObject *v1, PyObject *v2)
580{
581 ColorObject *color1 = nullptr, *color2 = nullptr;
582 float col[COLOR_SIZE];
583
584 if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
585 PyErr_Format(PyExc_TypeError,
586 "Color addition: (%s + %s) "
587 "invalid type for this operation",
588 Py_TYPE(v1)->tp_name,
589 Py_TYPE(v2)->tp_name);
590 return nullptr;
591 }
592 color1 = (ColorObject *)v1;
593 color2 = (ColorObject *)v2;
594
595 if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
596 return nullptr;
597 }
598
599 add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
600
601 return Color_CreatePyObject(col, Py_TYPE(v1));
602}
603
605static PyObject *Color_iadd(PyObject *v1, PyObject *v2)
606{
607 ColorObject *color1 = nullptr, *color2 = nullptr;
608
609 if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
610 PyErr_Format(PyExc_TypeError,
611 "Color addition: (%s += %s) "
612 "invalid type for this operation",
613 Py_TYPE(v1)->tp_name,
614 Py_TYPE(v2)->tp_name);
615 return nullptr;
616 }
617 color1 = (ColorObject *)v1;
618 color2 = (ColorObject *)v2;
619
620 if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
621 return nullptr;
622 }
623
624 add_vn_vn(color1->col, color2->col, COLOR_SIZE);
625
626 (void)BaseMath_WriteCallback(color1);
627 Py_INCREF(v1);
628 return v1;
629}
630
632static PyObject *Color_sub(PyObject *v1, PyObject *v2)
633{
634 ColorObject *color1 = nullptr, *color2 = nullptr;
635 float col[COLOR_SIZE];
636
637 if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
638 PyErr_Format(PyExc_TypeError,
639 "Color subtraction: (%s - %s) "
640 "invalid type for this operation",
641 Py_TYPE(v1)->tp_name,
642 Py_TYPE(v2)->tp_name);
643 return nullptr;
644 }
645 color1 = (ColorObject *)v1;
646 color2 = (ColorObject *)v2;
647
648 if (BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
649 return nullptr;
650 }
651
652 sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE);
653
654 return Color_CreatePyObject(col, Py_TYPE(v1));
655}
656
658static PyObject *Color_isub(PyObject *v1, PyObject *v2)
659{
660 ColorObject *color1 = nullptr, *color2 = nullptr;
661
662 if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) {
663 PyErr_Format(PyExc_TypeError,
664 "Color subtraction: (%s -= %s) "
665 "invalid type for this operation",
666 Py_TYPE(v1)->tp_name,
667 Py_TYPE(v2)->tp_name);
668 return nullptr;
669 }
670 color1 = (ColorObject *)v1;
671 color2 = (ColorObject *)v2;
672
673 if (BaseMath_ReadCallback_ForWrite(color1) == -1 || BaseMath_ReadCallback(color2) == -1) {
674 return nullptr;
675 }
676
677 sub_vn_vn(color1->col, color2->col, COLOR_SIZE);
678
679 (void)BaseMath_WriteCallback(color1);
680 Py_INCREF(v1);
681 return v1;
682}
683
684static PyObject *color_mul_float(ColorObject *color, const float scalar)
685{
686 float tcol[COLOR_SIZE];
687 mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar);
688 return Color_CreatePyObject(tcol, Py_TYPE(color));
689}
690
692static PyObject *Color_mul(PyObject *v1, PyObject *v2)
693{
694 ColorObject *color1 = nullptr, *color2 = nullptr;
695 float scalar;
696
697 if (ColorObject_Check(v1)) {
698 color1 = (ColorObject *)v1;
699 if (BaseMath_ReadCallback(color1) == -1) {
700 return nullptr;
701 }
702 }
703 if (ColorObject_Check(v2)) {
704 color2 = (ColorObject *)v2;
705 if (BaseMath_ReadCallback(color2) == -1) {
706 return nullptr;
707 }
708 }
709
710 /* make sure v1 is always the vector */
711 if (color1 && color2) {
712 /* col * col, don't support yet! */
713 }
714 else if (color1) {
715 if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */
716 return color_mul_float(color1, scalar);
717 }
718 }
719 else if (color2) {
720 if (((scalar = PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred()) == 0) { /* FLOAT * COLOR */
721 return color_mul_float(color2, scalar);
722 }
723 }
724 else {
725 BLI_assert_msg(0, "internal error");
726 }
727
728 PyErr_Format(PyExc_TypeError,
729 "Color multiplication: not supported between "
730 "'%.200s' and '%.200s' types",
731 Py_TYPE(v1)->tp_name,
732 Py_TYPE(v2)->tp_name);
733 return nullptr;
734}
735
737static PyObject *Color_div(PyObject *v1, PyObject *v2)
738{
739 ColorObject *color1 = nullptr;
740 float scalar;
741
742 if (ColorObject_Check(v1)) {
743 color1 = (ColorObject *)v1;
744 if (BaseMath_ReadCallback(color1) == -1) {
745 return nullptr;
746 }
747 }
748 else {
749 PyErr_SetString(PyExc_TypeError, "Color division not supported in this order");
750 return nullptr;
751 }
752
753 /* make sure v1 is always the vector */
754 if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR * FLOAT */
755 if (scalar == 0.0f) {
756 PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error");
757 return nullptr;
758 }
759 return color_mul_float(color1, 1.0f / scalar);
760 }
761
762 PyErr_Format(PyExc_TypeError,
763 "Color multiplication: not supported between "
764 "'%.200s' and '%.200s' types",
765 Py_TYPE(v1)->tp_name,
766 Py_TYPE(v2)->tp_name);
767 return nullptr;
768}
769
771static PyObject *Color_imul(PyObject *v1, PyObject *v2)
772{
774 float scalar;
775
777 return nullptr;
778 }
779
780 /* only support color *= float */
781 if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR *= FLOAT */
782 mul_vn_fl(color->col, COLOR_SIZE, scalar);
783 }
784 else {
785 PyErr_Format(PyExc_TypeError,
786 "Color multiplication: (%s *= %s) "
787 "invalid type for this operation",
788 Py_TYPE(v1)->tp_name,
789 Py_TYPE(v2)->tp_name);
790 return nullptr;
791 }
792
794 Py_INCREF(v1);
795 return v1;
796}
797
799static PyObject *Color_idiv(PyObject *v1, PyObject *v2)
800{
802 float scalar;
803
805 return nullptr;
806 }
807
808 /* only support color /= float */
809 if (((scalar = PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred()) == 0) { /* COLOR /= FLOAT */
810 if (scalar == 0.0f) {
811 PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error");
812 return nullptr;
813 }
814
815 mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar);
816 }
817 else {
818 PyErr_Format(PyExc_TypeError,
819 "Color division: (%s /= %s) "
820 "invalid type for this operation",
821 Py_TYPE(v1)->tp_name,
822 Py_TYPE(v2)->tp_name);
823 return nullptr;
824 }
825
827 Py_INCREF(v1);
828 return v1;
829}
830
832static PyObject *Color_neg(ColorObject *self)
833{
834 float tcol[COLOR_SIZE];
835
836 if (BaseMath_ReadCallback(self) == -1) {
837 return nullptr;
838 }
839
840 negate_vn_vn(tcol, self->col, COLOR_SIZE);
841 return Color_CreatePyObject(tcol, Py_TYPE(self));
842}
843
845
846/* -------------------------------------------------------------------- */
849
850static PySequenceMethods Color_SeqMethods = {
851 /*sq_length*/ (lenfunc)Color_len,
852 /*sq_concat*/ nullptr,
853 /*sq_repeat*/ nullptr,
854 /*sq_item*/ (ssizeargfunc)Color_item,
855 /*was_sq_slice*/ nullptr, /* DEPRECATED. */
856 /*sq_ass_item*/ (ssizeobjargproc)Color_ass_item,
857 /*was_sq_ass_slice*/ nullptr, /* DEPRECATED. */
858 /*sq_contains*/ nullptr,
859 /*sq_inplace_concat*/ nullptr,
860 /*sq_inplace_repeat*/ nullptr,
861};
862
863static PyMappingMethods Color_AsMapping = {
864 /*mp_length*/ (lenfunc)Color_len,
865 /*mp_subscript*/ (binaryfunc)Color_subscript,
866 /*mp_ass_subscript*/ (objobjargproc)Color_ass_subscript,
867};
868
869static PyNumberMethods Color_NumMethods = {
870 /*nb_add*/ (binaryfunc)Color_add,
871 /*nb_subtract*/ (binaryfunc)Color_sub,
872 /*nb_multiply*/ (binaryfunc)Color_mul,
873 /*nb_remainder*/ nullptr,
874 /*nb_divmod*/ nullptr,
875 /*nb_power*/ nullptr,
876 /*nb_negative*/ (unaryfunc)Color_neg,
877 /*nb_positive*/ (unaryfunc)Color_copy,
878 /*nb_absolute*/ nullptr,
879 /*nb_bool*/ nullptr,
880 /*nb_invert*/ nullptr,
881 /*nb_lshift*/ nullptr,
882 /*nb_rshift*/ nullptr,
883 /*nb_and*/ nullptr,
884 /*nb_xor*/ nullptr,
885 /*nb_or*/ nullptr,
886 /*nb_int*/ nullptr,
887 /*nb_reserved*/ nullptr,
888 /*nb_float*/ nullptr,
889 /*nb_inplace_add*/ Color_iadd,
890 /*nb_inplace_subtract*/ Color_isub,
891 /*nb_inplace_multiply*/ Color_imul,
892 /*nb_inplace_remainder*/ nullptr,
893 /*nb_inplace_power*/ nullptr,
894 /*nb_inplace_lshift*/ nullptr,
895 /*nb_inplace_rshift*/ nullptr,
896 /*nb_inplace_and*/ nullptr,
897 /*nb_inplace_xor*/ nullptr,
898 /*nb_inplace_or*/ nullptr,
899 /*nb_floor_divide*/ nullptr,
900 /*nb_true_divide*/ Color_div,
901 /*nb_inplace_floor_divide*/ nullptr,
902 /*nb_inplace_true_divide*/ Color_idiv,
903 /*nb_index*/ nullptr,
904 /*nb_matrix_multiply*/ nullptr,
905 /*nb_inplace_matrix_multiply*/ nullptr,
906};
907
909
910/* -------------------------------------------------------------------- */
913
914/* Color channel (RGB): `color.r/g/b`. */
915
917 /* Wrap. */
918 Color_channel_r_doc,
919 "Red color channel.\n"
920 "\n"
921 ":type: float");
923 /* Wrap. */
924 Color_channel_g_doc,
925 "Green color channel.\n"
926 "\n"
927 ":type: float");
929 /* Wrap. */
930 Color_channel_b_doc,
931 "Blue color channel.\n"
932 "\n"
933 ":type: float");
934
935static PyObject *Color_channel_get(ColorObject *self, void *type)
936{
937 return Color_item(self, POINTER_AS_INT(type));
938}
939
940static int Color_channel_set(ColorObject *self, PyObject *value, void *type)
941{
942 return Color_ass_item(self, POINTER_AS_INT(type), value);
943}
944
945/* Color channel (HSV): `color.h/s/v`. */
946
948 /* Wrap. */
949 Color_channel_hsv_h_doc,
950 "HSV Hue component in [0, 1].\n"
951 "\n"
952 ":type: float");
954 /* Wrap. */
955 Color_channel_hsv_s_doc,
956 "HSV Saturation component in [0, 1].\n"
957 "\n"
958 ":type: float");
960 /* Wrap. */
961 Color_channel_hsv_v_doc,
962 "HSV Value component in [0, 1].\n"
963 "\n"
964 ":type: float");
965
966static PyObject *Color_channel_hsv_get(ColorObject *self, void *type)
967{
968 float hsv[3];
969 const int i = POINTER_AS_INT(type);
970
971 if (BaseMath_ReadCallback(self) == -1) {
972 return nullptr;
973 }
974
975 rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
976
977 return PyFloat_FromDouble(hsv[i]);
978}
979
980static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type)
981{
982 float hsv[3];
983 const int i = POINTER_AS_INT(type);
984 float f = PyFloat_AsDouble(value);
985
986 if (f == -1 && PyErr_Occurred()) {
987 PyErr_SetString(PyExc_TypeError,
988 "color.h/s/v = value: "
989 "assigned value not a number");
990 return -1;
991 }
992
994 return -1;
995 }
996
997 rgb_to_hsv_v(self->col, hsv);
998 CLAMP(f, 0.0f, 1.0f);
999 hsv[i] = f;
1000 hsv_to_rgb_v(hsv, self->col);
1001
1002 if (BaseMath_WriteCallback(self) == -1) {
1003 return -1;
1004 }
1005
1006 return 0;
1007}
1008
1010 /* Wrap. */
1011 Color_hsv_doc,
1012 "HSV Values in [0, 1].\n"
1013 "\n"
1014 ":type: float triplet");
1016static PyObject *Color_hsv_get(ColorObject *self, void * /*closure*/)
1017{
1018 float hsv[3];
1019 PyObject *ret;
1020
1021 if (BaseMath_ReadCallback(self) == -1) {
1022 return nullptr;
1023 }
1024
1025 rgb_to_hsv(self->col[0], self->col[1], self->col[2], &(hsv[0]), &(hsv[1]), &(hsv[2]));
1026
1027 ret = PyTuple_New(3);
1029 ret, PyFloat_FromDouble(hsv[0]), PyFloat_FromDouble(hsv[1]), PyFloat_FromDouble(hsv[2]));
1030 return ret;
1031}
1032
1034static int Color_hsv_set(ColorObject *self, PyObject *value, void * /*closure*/)
1035{
1036 float hsv[3];
1037
1038 if (mathutils_array_parse(hsv, 3, 3, value, "mathutils.Color.hsv = value") == -1) {
1039 return -1;
1040 }
1041
1042 if (BaseMath_Prepare_ForWrite(self) == -1) {
1043 return -1;
1044 }
1045
1046 clamp_v3(hsv, 0.0f, 1.0f);
1047 hsv_to_rgb_v(hsv, self->col);
1048
1049 if (BaseMath_WriteCallback(self) == -1) {
1050 return -1;
1051 }
1052
1053 return 0;
1054}
1055
1057
1058/* -------------------------------------------------------------------- */
1061
1062static PyGetSetDef Color_getseters[] = {
1063 {"r",
1064 (getter)Color_channel_get,
1065 (setter)Color_channel_set,
1066 Color_channel_r_doc,
1067 POINTER_FROM_INT(0)},
1068 {"g",
1069 (getter)Color_channel_get,
1070 (setter)Color_channel_set,
1071 Color_channel_g_doc,
1072 POINTER_FROM_INT(1)},
1073 {"b",
1074 (getter)Color_channel_get,
1075 (setter)Color_channel_set,
1076 Color_channel_b_doc,
1077 POINTER_FROM_INT(2)},
1078
1079 {"h",
1080 (getter)Color_channel_hsv_get,
1081 (setter)Color_channel_hsv_set,
1082 Color_channel_hsv_h_doc,
1083 POINTER_FROM_INT(0)},
1084 {"s",
1085 (getter)Color_channel_hsv_get,
1086 (setter)Color_channel_hsv_set,
1087 Color_channel_hsv_s_doc,
1088 POINTER_FROM_INT(1)},
1089 {"v",
1090 (getter)Color_channel_hsv_get,
1091 (setter)Color_channel_hsv_set,
1092 Color_channel_hsv_v_doc,
1093 POINTER_FROM_INT(2)},
1094
1095 {"hsv", (getter)Color_hsv_get, (setter)Color_hsv_set, Color_hsv_doc, nullptr},
1096
1097 {"is_wrapped",
1099 (setter) nullptr,
1101 nullptr},
1102 {"is_frozen",
1104 (setter) nullptr,
1106 nullptr},
1107 {"is_valid",
1109 (setter) nullptr,
1111 nullptr},
1112 {"owner",
1114 (setter) nullptr,
1116 nullptr},
1117 {nullptr, nullptr, nullptr, nullptr, nullptr} /* Sentinel */
1118};
1119
1121
1122/* -------------------------------------------------------------------- */
1125
1126#if (defined(__GNUC__) && !defined(__clang__))
1127# pragma GCC diagnostic push
1128# pragma GCC diagnostic ignored "-Wcast-function-type"
1129#endif
1130
1131static PyMethodDef Color_methods[] = {
1132 {"copy", (PyCFunction)Color_copy, METH_NOARGS, Color_copy_doc},
1133 {"__copy__", (PyCFunction)Color_copy, METH_NOARGS, Color_copy_doc},
1134 {"__deepcopy__", (PyCFunction)Color_deepcopy, METH_VARARGS, Color_copy_doc},
1135
1136 /* base-math methods */
1137 {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
1138
1139/* Color-space methods. */
1140#ifndef MATH_STANDALONE
1141 {"from_scene_linear_to_srgb",
1143 METH_NOARGS,
1144 Color_from_scene_linear_to_srgb_doc},
1145 {"from_srgb_to_scene_linear",
1147 METH_NOARGS,
1148 Color_from_srgb_to_scene_linear_doc},
1149 {"from_scene_linear_to_xyz_d65",
1151 METH_NOARGS,
1152 Color_from_scene_linear_to_xyz_d65_doc},
1153 {"from_xyz_d65_to_scene_linear",
1155 METH_NOARGS,
1156 Color_from_xyz_d65_to_scene_linear_doc},
1157 {"from_scene_linear_to_aces",
1159 METH_NOARGS,
1160 Color_from_scene_linear_to_aces_doc},
1161 {"from_aces_to_scene_linear",
1163 METH_NOARGS,
1164 Color_from_aces_to_scene_linear_doc},
1165 {"from_scene_linear_to_rec709_linear",
1167 METH_NOARGS,
1168 Color_from_scene_linear_to_rec709_linear_doc},
1169 {"from_rec709_linear_to_scene_linear",
1171 METH_NOARGS,
1172 Color_from_rec709_linear_to_scene_linear_doc},
1173#endif /* !MATH_STANDALONE */
1174
1175 {nullptr, nullptr, 0, nullptr},
1176};
1177
1178#if (defined(__GNUC__) && !defined(__clang__))
1179# pragma GCC diagnostic pop
1180#endif
1181
1183
1184/* -------------------------------------------------------------------- */
1187
1188#ifdef MATH_STANDALONE
1189# define Color_str nullptr
1190#endif
1191
1193 /* Wrap. */
1194 color_doc,
1195 ".. class:: Color(rgb)\n"
1196 "\n"
1197 " This object gives access to Colors in Blender.\n"
1198 "\n"
1199 " Most colors returned by Blender APIs are in scene linear color space, as defined by "
1200 " the OpenColorIO configuration. The notable exception is user interface theming colors, "
1201 " which are in sRGB color space.\n"
1202 "\n"
1203 " :arg rgb: (red, green, blue) color values where (0, 0, 0) is black & (1, 1, 1) is white.\n"
1204 " :type rgb: Sequence[float]\n");
1205PyTypeObject color_Type = {
1206 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
1207 /*tp_name*/ "Color",
1208 /*tp_basicsize*/ sizeof(ColorObject),
1209 /*tp_itemsize*/ 0,
1210 /*tp_dealloc*/ (destructor)BaseMathObject_dealloc,
1211 /*tp_vectorcall_offset*/ 0,
1212 /*tp_getattr*/ nullptr,
1213 /*tp_setattr*/ nullptr,
1214 /*tp_as_async*/ nullptr,
1215 /*tp_repr*/ (reprfunc)Color_repr,
1216 /*tp_as_number*/ &Color_NumMethods,
1217 /*tp_as_sequence*/ &Color_SeqMethods,
1218 /*tp_as_mapping*/ &Color_AsMapping,
1219 /*tp_hash*/ (hashfunc)Color_hash,
1220 /*tp_call*/ nullptr,
1221 /*tp_str*/ (reprfunc)Color_str,
1222 /*tp_getattro*/ nullptr,
1223 /*tp_setattro*/ nullptr,
1224 /*tp_as_buffer*/ nullptr,
1225 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
1226 /*tp_doc*/ color_doc,
1227 /*tp_traverse*/ (traverseproc)BaseMathObject_traverse,
1228 /*tp_clear*/ (inquiry)BaseMathObject_clear,
1229 /*tp_richcompare*/ (richcmpfunc)Color_richcmpr,
1230 /*tp_weaklistoffset*/ 0,
1231 /*tp_iter*/ nullptr,
1232 /*tp_iternext*/ nullptr,
1233 /*tp_methods*/ Color_methods,
1234 /*tp_members*/ nullptr,
1235 /*tp_getset*/ Color_getseters,
1236 /*tp_base*/ nullptr,
1237 /*tp_dict*/ nullptr,
1238 /*tp_descr_get*/ nullptr,
1239 /*tp_descr_set*/ nullptr,
1240 /*tp_dictoffset*/ 0,
1241 /*tp_init*/ nullptr,
1242 /*tp_alloc*/ nullptr,
1243 /*tp_new*/ Color_new,
1244 /*tp_free*/ nullptr,
1245 /*tp_is_gc*/ (inquiry)BaseMathObject_is_gc,
1246 /*tp_bases*/ nullptr,
1247 /*tp_mro*/ nullptr,
1248 /*tp_cache*/ nullptr,
1249 /*tp_subclasses*/ nullptr,
1250 /*tp_weaklist*/ nullptr,
1251 /*tp_del*/ nullptr,
1252 /*tp_version_tag*/ 0,
1253 /*tp_finalize*/ nullptr,
1254 /*tp_vectorcall*/ nullptr,
1255};
1256
1257#ifdef MATH_STANDALONE
1258# define Color_str
1259#endif
1260
1262
1263/* -------------------------------------------------------------------- */
1266
1267PyObject *Color_CreatePyObject(const float col[3], PyTypeObject *base_type)
1268{
1270 float *col_alloc;
1271
1272 col_alloc = static_cast<float *>(PyMem_Malloc(COLOR_SIZE * sizeof(float)));
1273 if (UNLIKELY(col_alloc == nullptr)) {
1274 PyErr_SetString(PyExc_MemoryError,
1275 "Color(): "
1276 "problem allocating data");
1277 return nullptr;
1278 }
1279
1281 if (self) {
1282 self->col = col_alloc;
1283
1284 /* init callbacks as nullptr */
1285 self->cb_user = nullptr;
1286 self->cb_type = self->cb_subtype = 0;
1287
1288 /* NEW */
1289 if (col) {
1290 copy_v3_v3(self->col, col);
1291 }
1292 else {
1293 zero_v3(self->col);
1294 }
1295
1297 }
1298 else {
1299 PyMem_Free(col_alloc);
1300 }
1301
1302 return (PyObject *)self;
1303}
1304
1305PyObject *Color_CreatePyObject_wrap(float col[3], PyTypeObject *base_type)
1306{
1308
1310 if (self) {
1311 /* init callbacks as nullptr */
1312 self->cb_user = nullptr;
1313 self->cb_type = self->cb_subtype = 0;
1314
1315 /* WRAP */
1316 self->col = col;
1318 }
1319
1320 return (PyObject *)self;
1321}
1322
1323PyObject *Color_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar cb_subtype)
1324{
1325 ColorObject *self = (ColorObject *)Color_CreatePyObject(nullptr, nullptr);
1326 if (self) {
1327 Py_INCREF(cb_user);
1328 self->cb_user = cb_user;
1329 self->cb_type = cb_type;
1330 self->cb_subtype = cb_subtype;
1331 BLI_assert(!PyObject_GC_IsTracked((PyObject *)self));
1332 PyObject_GC_Track(self);
1333 }
1334
1335 return (PyObject *)self;
1336}
1337
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define ATTR_FALLTHROUGH
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_dynstr.c:37
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
double double_round(double x, int ndigits)
Definition math_base.c:28
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
Definition math_color.cc:57
void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
void add_vn_vn(float *array_tar, const float *array_src, int size)
void mul_vn_fl(float *array_tar, int size, float f)
MINLINE void clamp_v3(float vec[3], float min, float max)
void sub_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void add_vn_vnvn(float *array_tar, const float *array_src_a, const float *array_src_b, int size)
void negate_vn_vn(float *array_tar, const float *array_src, int size)
MINLINE void zero_v3(float r[3])
void mul_vn_vn_fl(float *array_tar, const float *array_src, int size, float f)
void sub_vn_vn(float *array_tar, const float *array_src, int size)
unsigned char uchar
#define CLAMP(a, b, c)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
BLI_INLINE void IMB_colormanagement_scene_linear_to_rec709(float rec709[3], const float scene_linear[3])
BLI_INLINE void IMB_colormanagement_aces_to_scene_linear(float scene_linear[3], const float aces[3])
BLI_INLINE void IMB_colormanagement_xyz_to_scene_linear(float scene_linear[3], const float xyz[3])
BLI_INLINE void IMB_colormanagement_rec709_to_scene_linear(float scene_linear[3], const float rec709[3])
BLI_INLINE void IMB_colormanagement_scene_linear_to_xyz(float xyz[3], const float scene_linear[3])
BLI_INLINE void IMB_colormanagement_scene_linear_to_aces(float aces[3], const float scene_linear[3])
BLI_INLINE void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scene_linear[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 Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves 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 Invert a color
ATTR_WARN_UNUSED_RESULT const BMVert * v2
PyObject * self
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
local_group_size(16, 16) .push_constant(Type b
uint col
int count
int BaseMathObject_is_gc(BaseMathObject *self)
Definition mathutils.cc:711
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition mathutils.cc:69
void BaseMathObject_dealloc(BaseMathObject *self)
Definition mathutils.cc:689
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition mathutils.cc:490
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:97
char BaseMathObject_is_valid_doc[]
Definition mathutils.cc:639
char BaseMathObject_is_wrapped_doc[]
Definition mathutils.cc:625
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *)
Definition mathutils.cc:619
char BaseMathObject_is_frozen_doc[]
Definition mathutils.cc:632
PyObject * mathutils_dynstr_to_py(DynStr *ds)
Definition mathutils.cc:502
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *)
Definition mathutils.cc:634
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition mathutils.cc:653
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *)
Definition mathutils.cc:627
char BaseMathObject_owner_doc[]
Definition mathutils.cc:618
char BaseMathObject_freeze_doc[]
Definition mathutils.cc:645
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *)
Definition mathutils.cc:640
int BaseMathObject_clear(BaseMathObject *self)
Definition mathutils.cc:671
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition mathutils.cc:665
#define BaseMath_ReadCallback_ForWrite(_self)
Definition mathutils.hh:135
#define BaseMath_ReadIndexCallback(_self, _index)
Definition mathutils.hh:129
#define BaseMath_WriteCallback(_self)
Definition mathutils.hh:127
#define BASE_MATH_NEW(struct_name, root_type, base_type)
Definition mathutils.hh:26
#define BaseMathObject_Prepare_ForHash(_self)
Definition mathutils.hh:150
#define BASE_MATH_FLAG_DEFAULT
Definition mathutils.hh:43
@ BASE_MATH_FLAG_IS_WRAP
Definition mathutils.hh:36
#define BaseMath_Prepare_ForWrite(_self)
Definition mathutils.hh:145
#define BaseMath_ReadCallback(_self)
Definition mathutils.hh:125
#define BaseMath_WriteIndexCallback(_self, _index)
Definition mathutils.hh:131
static PyObject * Color_from_scene_linear_to_rec709_linear(ColorObject *self)
static PyObject * Color_str(ColorObject *self)
PyObject * Color_CreatePyObject(const float col[3], PyTypeObject *base_type)
static PyObject * Color_from_xyz_d65_to_scene_linear(ColorObject *self)
PyTypeObject color_Type
static Py_hash_t Color_hash(ColorObject *self)
static int Color_ass_subscript(ColorObject *self, PyObject *item, PyObject *value)
static PyObject * color_mul_float(ColorObject *color, const float scalar)
static PyObject * Color_imul(PyObject *v1, PyObject *v2)
static PyObject * Color_richcmpr(PyObject *a, PyObject *b, int op)
static PyObject * Color_channel_get(ColorObject *self, void *type)
static int Color_ass_item(ColorObject *self, Py_ssize_t i, PyObject *value)
static PySequenceMethods Color_SeqMethods
static PyObject * Color_to_tuple_ex(ColorObject *self, int ndigits)
PyDoc_STRVAR(Color_from_scene_linear_to_srgb_doc, ".. function:: from_scene_linear_to_srgb()\n" "\n" " Convert from scene linear to sRGB color space.\n" "\n" " :return: A color in sRGB color space.\n" " :rtype: :class:`Color`\n")
static PyObject * Color_channel_hsv_get(ColorObject *self, void *type)
static PyGetSetDef Color_getseters[]
static int Color_hsv_set(ColorObject *self, PyObject *value, void *)
static PyObject * Color_from_scene_linear_to_xyz_d65(ColorObject *self)
#define COLOR_SIZE
static Py_ssize_t Color_len(ColorObject *)
static PyObject * Color_deepcopy(ColorObject *self, PyObject *args)
static PyObject * Color_iadd(PyObject *v1, PyObject *v2)
static PyObject * Color_copy(ColorObject *self)
static PyObject * Color_idiv(PyObject *v1, PyObject *v2)
static PyObject * Color_neg(ColorObject *self)
static PyObject * Color_div(PyObject *v1, PyObject *v2)
static PyNumberMethods Color_NumMethods
static PyObject * Color_subscript(ColorObject *self, PyObject *item)
static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq)
static PyObject * Color_add(PyObject *v1, PyObject *v2)
static PyObject * Color_from_srgb_to_scene_linear(ColorObject *self)
static PyObject * Color_sub(PyObject *v1, PyObject *v2)
PyObject * Color_CreatePyObject_cb(PyObject *cb_user, uchar cb_type, uchar cb_subtype)
static PyObject * Color_repr(ColorObject *self)
static PyObject * Color_hsv_get(ColorObject *self, void *)
static PyMappingMethods Color_AsMapping
static PyObject * Color_isub(PyObject *v1, PyObject *v2)
static PyObject * Color_mul(PyObject *v1, PyObject *v2)
static PyObject * Color_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static PyObject * Color_from_aces_to_scene_linear(ColorObject *self)
static PyMethodDef Color_methods[]
static int Color_channel_set(ColorObject *self, PyObject *value, void *type)
static int Color_channel_hsv_set(ColorObject *self, PyObject *value, void *type)
static PyObject * Color_from_scene_linear_to_aces(ColorObject *self)
static PyObject * Color_item(ColorObject *self, Py_ssize_t i)
PyObject * Color_CreatePyObject_wrap(float col[3], PyTypeObject *base_type)
static PyObject * Color_slice(ColorObject *self, int begin, int end)
static PyObject * Color_from_rec709_linear_to_scene_linear(ColorObject *self)
static PyObject * Color_from_scene_linear_to_srgb(ColorObject *self)
#define ColorObject_Check(v)
int PyC_CheckArgs_DeepCopy(PyObject *args)
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret