Blender V5.0
rectop.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <algorithm>
10#include <cstdlib>
11
12#include "BLI_math_base.h"
14#include "BLI_math_vector.h"
15#include "BLI_rect.h"
16#include "BLI_task.hh"
17#include "BLI_utildefines.h"
18
19#include "IMB_imbuf.hh"
20#include "IMB_imbuf_types.hh"
21
23
24#include "MEM_guardedalloc.h"
25
26#include <cstring>
27
29 const uchar src1[4],
30 const uchar src2[4],
31 IMB_BlendMode mode)
32{
33 switch (mode) {
34 case IMB_BLEND_MIX:
35 blend_color_mix_byte(dst, src1, src2);
36 break;
37 case IMB_BLEND_ADD:
38 blend_color_add_byte(dst, src1, src2);
39 break;
40 case IMB_BLEND_SUB:
41 blend_color_sub_byte(dst, src1, src2);
42 break;
43 case IMB_BLEND_MUL:
44 blend_color_mul_byte(dst, src1, src2);
45 break;
47 blend_color_lighten_byte(dst, src1, src2);
48 break;
50 blend_color_darken_byte(dst, src1, src2);
51 break;
53 blend_color_erase_alpha_byte(dst, src1, src2);
54 break;
56 blend_color_add_alpha_byte(dst, src1, src2);
57 break;
59 blend_color_overlay_byte(dst, src1, src2);
60 break;
62 blend_color_hardlight_byte(dst, src1, src2);
63 break;
65 blend_color_burn_byte(dst, src1, src2);
66 break;
68 blend_color_linearburn_byte(dst, src1, src2);
69 break;
71 blend_color_dodge_byte(dst, src1, src2);
72 break;
74 blend_color_screen_byte(dst, src1, src2);
75 break;
77 blend_color_softlight_byte(dst, src1, src2);
78 break;
80 blend_color_pinlight_byte(dst, src1, src2);
81 break;
83 blend_color_linearlight_byte(dst, src1, src2);
84 break;
86 blend_color_vividlight_byte(dst, src1, src2);
87 break;
89 blend_color_difference_byte(dst, src1, src2);
90 break;
92 blend_color_exclusion_byte(dst, src1, src2);
93 break;
94 case IMB_BLEND_COLOR:
95 blend_color_color_byte(dst, src1, src2);
96 break;
97 case IMB_BLEND_HUE:
98 blend_color_hue_byte(dst, src1, src2);
99 break;
101 blend_color_saturation_byte(dst, src1, src2);
102 break;
104 blend_color_luminosity_byte(dst, src1, src2);
105 break;
106
107 default:
108 dst[0] = src1[0];
109 dst[1] = src1[1];
110 dst[2] = src1[2];
111 dst[3] = src1[3];
112 break;
113 }
114}
115
116void IMB_blend_color_float(float dst[4],
117 const float src1[4],
118 const float src2[4],
119 IMB_BlendMode mode)
120{
121 switch (mode) {
122 case IMB_BLEND_MIX:
123 blend_color_mix_float(dst, src1, src2);
124 break;
125 case IMB_BLEND_ADD:
126 blend_color_add_float(dst, src1, src2);
127 break;
128 case IMB_BLEND_SUB:
129 blend_color_sub_float(dst, src1, src2);
130 break;
131 case IMB_BLEND_MUL:
132 blend_color_mul_float(dst, src1, src2);
133 break;
135 blend_color_lighten_float(dst, src1, src2);
136 break;
137 case IMB_BLEND_DARKEN:
138 blend_color_darken_float(dst, src1, src2);
139 break;
141 blend_color_erase_alpha_float(dst, src1, src2);
142 break;
144 blend_color_add_alpha_float(dst, src1, src2);
145 break;
147 blend_color_overlay_float(dst, src1, src2);
148 break;
150 blend_color_hardlight_float(dst, src1, src2);
151 break;
153 blend_color_burn_float(dst, src1, src2);
154 break;
156 blend_color_linearburn_float(dst, src1, src2);
157 break;
159 blend_color_dodge_float(dst, src1, src2);
160 break;
161 case IMB_BLEND_SCREEN:
162 blend_color_screen_float(dst, src1, src2);
163 break;
165 blend_color_softlight_float(dst, src1, src2);
166 break;
168 blend_color_pinlight_float(dst, src1, src2);
169 break;
171 blend_color_linearlight_float(dst, src1, src2);
172 break;
174 blend_color_vividlight_float(dst, src1, src2);
175 break;
177 blend_color_difference_float(dst, src1, src2);
178 break;
180 blend_color_exclusion_float(dst, src1, src2);
181 break;
182 case IMB_BLEND_COLOR:
183 blend_color_color_float(dst, src1, src2);
184 break;
185 case IMB_BLEND_HUE:
186 blend_color_hue_float(dst, src1, src2);
187 break;
189 blend_color_saturation_float(dst, src1, src2);
190 break;
192 blend_color_luminosity_float(dst, src1, src2);
193 break;
194 default:
195 dst[0] = src1[0];
196 dst[1] = src1[1];
197 dst[2] = src1[2];
198 dst[3] = src1[3];
199 break;
200 }
201}
202
203/* -------------------------------------------------------------------- */
206
207static void rect_crop_4bytes(void **buf_p, const int size_src[2], const rcti *crop)
208{
209 if (*buf_p == nullptr) {
210 return;
211 }
212 const int size_dst[2] = {
213 BLI_rcti_size_x(crop) + 1,
214 BLI_rcti_size_y(crop) + 1,
215 };
216 uint *src = static_cast<uint *>(*buf_p);
217 uint *dst = src + crop->ymin * size_src[0] + crop->xmin;
218 for (int y = 0; y < size_dst[1]; y++, src += size_dst[0], dst += size_src[0]) {
219 memmove(src, dst, sizeof(uint) * size_dst[0]);
220 }
221 *buf_p = MEM_reallocN(*buf_p, sizeof(uint) * size_dst[0] * size_dst[1]);
222}
223
224static void rect_crop_16bytes(void **buf_p, const int size_src[2], const rcti *crop)
225{
226 if (*buf_p == nullptr) {
227 return;
228 }
229 const int size_dst[2] = {
230 BLI_rcti_size_x(crop) + 1,
231 BLI_rcti_size_y(crop) + 1,
232 };
233 uint(*src)[4] = static_cast<uint(*)[4]>(*buf_p);
234 uint(*dst)[4] = src + crop->ymin * size_src[0] + crop->xmin;
235 for (int y = 0; y < size_dst[1]; y++, src += size_dst[0], dst += size_src[0]) {
236 memmove(src, dst, sizeof(uint[4]) * size_dst[0]);
237 }
238 *buf_p = (void *)MEM_reallocN(*buf_p, sizeof(uint[4]) * size_dst[0] * size_dst[1]);
239}
240
241void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
242{
243 const int size_src[2] = {
244 ibuf->x,
245 ibuf->y,
246 };
247 const int size_dst[2] = {
248 BLI_rcti_size_x(crop) + 1,
249 BLI_rcti_size_y(crop) + 1,
250 };
251 BLI_assert(size_dst[0] > 0 && size_dst[1] > 0);
252 BLI_assert(crop->xmin >= 0 && crop->ymin >= 0);
253 BLI_assert(crop->xmax < ibuf->x && crop->ymax < ibuf->y);
254
255 if ((size_dst[0] == ibuf->x) && (size_dst[1] == ibuf->y)) {
256 return;
257 }
258
259 /* TODO(sergey: Validate ownership. */
260 rect_crop_4bytes((void **)&ibuf->byte_buffer.data, size_src, crop);
261 rect_crop_16bytes((void **)&ibuf->float_buffer.data, size_src, crop);
262
263 ibuf->x = size_dst[0];
264 ibuf->y = size_dst[1];
265}
266
270static void rect_realloc_4bytes(void **buf_p, const uint size[2])
271{
272 if (*buf_p == nullptr) {
273 return;
274 }
275 MEM_freeN(*buf_p);
276 *buf_p = MEM_malloc_arrayN<uint>(size_t(size[0]) * size_t(size[1]), __func__);
277}
278
279static void rect_realloc_16bytes(void **buf_p, const uint size[2])
280{
281 if (*buf_p == nullptr) {
282 return;
283 }
284 MEM_freeN(*buf_p);
285 *buf_p = MEM_malloc_arrayN<uint>(4 * size_t(size[0]) * size_t(size[1]), __func__);
286}
287
288void IMB_rect_size_set(ImBuf *ibuf, const uint size[2])
289{
290 BLI_assert(size[0] > 0 && size[1] > 0);
291 if ((size[0] == ibuf->x) && (size[1] == ibuf->y)) {
292 return;
293 }
294
295 /* TODO(sergey: Validate ownership. */
296 rect_realloc_4bytes((void **)&ibuf->byte_buffer.data, size);
297 rect_realloc_16bytes((void **)&ibuf->float_buffer.data, size);
298
299 ibuf->x = size[0];
300 ibuf->y = size[1];
301}
302
304
305/* clipping */
306
308 const ImBuf *sbuf,
309 int *destx,
310 int *desty,
311 int *srcx,
312 int *srcy,
313 int *width,
314 int *height)
315{
316 int tmp;
317
318 if (dbuf == nullptr) {
319 return;
320 }
321
322 if (*destx < 0) {
323 *srcx -= *destx;
324 *width += *destx;
325 *destx = 0;
326 }
327 if (*srcx < 0) {
328 *destx -= *srcx;
329 *width += *srcx;
330 *srcx = 0;
331 }
332 if (*desty < 0) {
333 *srcy -= *desty;
334 *height += *desty;
335 *desty = 0;
336 }
337 if (*srcy < 0) {
338 *desty -= *srcy;
339 *height += *srcy;
340 *srcy = 0;
341 }
342
343 tmp = dbuf->x - *destx;
344 *width = std::min(*width, tmp);
345 tmp = dbuf->y - *desty;
346 *height = std::min(*height, tmp);
347
348 if (sbuf) {
349 tmp = sbuf->x - *srcx;
350 *width = std::min(*width, tmp);
351 tmp = sbuf->y - *srcy;
352 *height = std::min(*height, tmp);
353 }
354
355 if ((*height <= 0) || (*width <= 0)) {
356 *width = 0;
357 *height = 0;
358 }
359}
360
361static void imb_rectclip3(ImBuf *dbuf,
362 const ImBuf *obuf,
363 const ImBuf *sbuf,
364 int *destx,
365 int *desty,
366 int *origx,
367 int *origy,
368 int *srcx,
369 int *srcy,
370 int *width,
371 int *height)
372{
373 int tmp;
374
375 if (dbuf == nullptr) {
376 return;
377 }
378
379 if (*destx < 0) {
380 *srcx -= *destx;
381 *origx -= *destx;
382 *width += *destx;
383 *destx = 0;
384 }
385 if (*origx < 0) {
386 *destx -= *origx;
387 *srcx -= *origx;
388 *width += *origx;
389 *origx = 0;
390 }
391 if (*srcx < 0) {
392 *destx -= *srcx;
393 *origx -= *srcx;
394 *width += *srcx;
395 *srcx = 0;
396 }
397
398 if (*desty < 0) {
399 *srcy -= *desty;
400 *origy -= *desty;
401 *height += *desty;
402 *desty = 0;
403 }
404 if (*origy < 0) {
405 *desty -= *origy;
406 *srcy -= *origy;
407 *height += *origy;
408 *origy = 0;
409 }
410 if (*srcy < 0) {
411 *desty -= *srcy;
412 *origy -= *srcy;
413 *height += *srcy;
414 *srcy = 0;
415 }
416
417 tmp = dbuf->x - *destx;
418 *width = std::min(*width, tmp);
419 tmp = dbuf->y - *desty;
420 *height = std::min(*height, tmp);
421
422 if (obuf) {
423 tmp = obuf->x - *origx;
424 *width = std::min(*width, tmp);
425 tmp = obuf->y - *origy;
426 *height = std::min(*height, tmp);
427 }
428
429 if (sbuf) {
430 tmp = sbuf->x - *srcx;
431 *width = std::min(*width, tmp);
432 tmp = sbuf->y - *srcy;
433 *height = std::min(*height, tmp);
434 }
435
436 if ((*height <= 0) || (*width <= 0)) {
437 *width = 0;
438 *height = 0;
439 }
440}
441
442/* copy and blend */
443
445 const ImBuf *sbuf,
446 int destx,
447 int desty,
448 int srcx,
449 int srcy,
450 int width,
451 int height)
452{
453 IMB_rectblend(dbuf,
454 dbuf,
455 sbuf,
456 nullptr,
457 nullptr,
458 nullptr,
459 0,
460 destx,
461 desty,
462 destx,
463 desty,
464 srcx,
465 srcy,
466 width,
467 height,
469 false);
470}
471
472using IMB_blend_func = void (*)(uchar *dst, const uchar *src1, const uchar *src2);
473using IMB_blend_func_float = void (*)(float *dst, const float *src1, const float *src2);
474
476 const ImBuf *obuf,
477 const ImBuf *sbuf,
478 ushort *dmask,
479 const ushort *curvemask,
480 const ushort *texmask,
481 float mask_max,
482 int destx,
483 int desty,
484 int origx,
485 int origy,
486 int srcx,
487 int srcy,
488 int width,
489 int height,
490 IMB_BlendMode mode,
491 bool accumulate)
492{
493 uint *drect = nullptr, *orect = nullptr, *srect = nullptr, *dr, *outr, *sr;
494 float *drectf = nullptr, *orectf = nullptr, *srectf = nullptr, *drf, *orf, *srf;
495 const ushort *cmaskrect = curvemask, *cmr;
496 ushort *dmaskrect = dmask, *dmr;
497 const ushort *texmaskrect = texmask, *tmr;
498 int srcskip, destskip, origskip, x;
499 IMB_blend_func func = nullptr;
500 IMB_blend_func_float func_float = nullptr;
501
502 if (dbuf == nullptr || obuf == nullptr) {
503 return;
504 }
505
506 imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height);
507
508 if (width == 0 || height == 0) {
509 return;
510 }
511 if (sbuf && sbuf->channels != 4) {
512 return;
513 }
514 if (dbuf->channels != 4) {
515 return;
516 }
517
518 const bool do_char = (sbuf && sbuf->byte_buffer.data && dbuf->byte_buffer.data &&
519 obuf->byte_buffer.data);
520 const bool do_float = (sbuf && sbuf->float_buffer.data && dbuf->float_buffer.data &&
521 obuf->float_buffer.data);
522
523 if (do_char) {
524 drect = (uint *)dbuf->byte_buffer.data + size_t(desty) * dbuf->x + destx;
525 orect = (uint *)obuf->byte_buffer.data + size_t(origy) * obuf->x + origx;
526 }
527 if (do_float) {
528 drectf = dbuf->float_buffer.data + (size_t(desty) * dbuf->x + destx) * 4;
529 orectf = obuf->float_buffer.data + (size_t(origy) * obuf->x + origx) * 4;
530 }
531
532 if (dmaskrect) {
533 dmaskrect += size_t(origy) * obuf->x + origx;
534 }
535
536 destskip = dbuf->x;
537 origskip = obuf->x;
538
539 if (sbuf) {
540 if (do_char) {
541 srect = (uint *)sbuf->byte_buffer.data + size_t(srcy) * sbuf->x + srcx;
542 }
543 if (do_float) {
544 srectf = sbuf->float_buffer.data + (size_t(srcy) * sbuf->x + srcx) * 4;
545 }
546 srcskip = sbuf->x;
547
548 if (cmaskrect) {
549 cmaskrect += size_t(srcy) * sbuf->x + srcx;
550 }
551
552 if (texmaskrect) {
553 texmaskrect += size_t(srcy) * sbuf->x + srcx;
554 }
555 }
556 else {
557 srect = drect;
558 srectf = drectf;
559 srcskip = destskip;
560 }
561
562 if (mode == IMB_BLEND_COPY) {
563 /* copy */
564 for (; height > 0; height--) {
565 if (do_char) {
566 memcpy(drect, srect, width * sizeof(int));
567 drect += destskip;
568 srect += srcskip;
569 }
570
571 if (do_float) {
572 memcpy(drectf, srectf, sizeof(float[4]) * width);
573 drectf += destskip * 4;
574 srectf += srcskip * 4;
575 }
576 }
577 }
578 else if (mode == IMB_BLEND_COPY_RGB) {
579 /* copy rgb only */
580 for (; height > 0; height--) {
581 if (do_char) {
582 dr = drect;
583 sr = srect;
584 for (x = width; x > 0; x--, dr++, sr++) {
585 ((char *)dr)[0] = ((char *)sr)[0];
586 ((char *)dr)[1] = ((char *)sr)[1];
587 ((char *)dr)[2] = ((char *)sr)[2];
588 }
589 drect += destskip;
590 srect += srcskip;
591 }
592
593 if (do_float) {
594 drf = drectf;
595 srf = srectf;
596 for (x = width; x > 0; x--, drf += 4, srf += 4) {
597 float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3];
598
599 drf[0] = srf[0] * map_alpha;
600 drf[1] = srf[1] * map_alpha;
601 drf[2] = srf[2] * map_alpha;
602 }
603 drectf += destskip * 4;
604 srectf += srcskip * 4;
605 }
606 }
607 }
608 else if (mode == IMB_BLEND_COPY_ALPHA) {
609 /* copy alpha only */
610 for (; height > 0; height--) {
611 if (do_char) {
612 dr = drect;
613 sr = srect;
614 for (x = width; x > 0; x--, dr++, sr++) {
615 ((char *)dr)[3] = ((char *)sr)[3];
616 }
617 drect += destskip;
618 srect += srcskip;
619 }
620
621 if (do_float) {
622 drf = drectf;
623 srf = srectf;
624 for (x = width; x > 0; x--, drf += 4, srf += 4) {
625 drf[3] = srf[3];
626 }
627 drectf += destskip * 4;
628 srectf += srcskip * 4;
629 }
630 }
631 }
632 else {
633 switch (mode) {
634 case IMB_BLEND_MIX:
637 func_float = blend_color_mix_float;
638 break;
639 case IMB_BLEND_ADD:
641 func_float = blend_color_add_float;
642 break;
643 case IMB_BLEND_SUB:
645 func_float = blend_color_sub_float;
646 break;
647 case IMB_BLEND_MUL:
649 func_float = blend_color_mul_float;
650 break;
653 func_float = blend_color_lighten_float;
654 break;
655 case IMB_BLEND_DARKEN:
657 func_float = blend_color_darken_float;
658 break;
662 break;
665 func_float = blend_color_add_alpha_float;
666 break;
669 func_float = blend_color_overlay_float;
670 break;
673 func_float = blend_color_hardlight_float;
674 break;
677 func_float = blend_color_burn_float;
678 break;
681 func_float = blend_color_linearburn_float;
682 break;
685 func_float = blend_color_dodge_float;
686 break;
687 case IMB_BLEND_SCREEN:
689 func_float = blend_color_screen_float;
690 break;
693 func_float = blend_color_softlight_float;
694 break;
697 func_float = blend_color_pinlight_float;
698 break;
702 break;
705 func_float = blend_color_vividlight_float;
706 break;
709 func_float = blend_color_difference_float;
710 break;
713 func_float = blend_color_exclusion_float;
714 break;
715 case IMB_BLEND_COLOR:
717 func_float = blend_color_color_float;
718 break;
719 case IMB_BLEND_HUE:
721 func_float = blend_color_hue_float;
722 break;
725 func_float = blend_color_saturation_float;
726 break;
729 func_float = blend_color_luminosity_float;
730 break;
731 default:
732 break;
733 }
734
735 /* blend */
736 for (; height > 0; height--) {
737 if (do_char) {
738 dr = drect;
739 outr = orect;
740 sr = srect;
741
742 if (cmaskrect) {
743 /* mask accumulation for painting */
744 cmr = cmaskrect;
745 tmr = texmaskrect;
746
747 /* destination mask present, do max alpha masking */
748 if (dmaskrect) {
749 dmr = dmaskrect;
750 for (x = width; x > 0; x--, dr++, outr++, sr++, dmr++, cmr++) {
751 uchar *src = (uchar *)sr;
752 float mask_lim = mask_max * (*cmr);
753
754 if (texmaskrect) {
755 mask_lim *= ((*tmr++) / 65535.0f);
756 }
757
758 if (src[3] && mask_lim) {
759 float mask;
760
761 if (accumulate) {
762 mask = *dmr + mask_lim;
763 }
764 else {
765 mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
766 }
767
768 mask = min_ff(mask, 65535.0);
769
770 if (mask > *dmr) {
771 uchar mask_src[4];
772
773 *dmr = mask;
774
775 mask_src[0] = src[0];
776 mask_src[1] = src[1];
777 mask_src[2] = src[2];
778
779 if (mode == IMB_BLEND_INTERPOLATE) {
780 mask_src[3] = src[3];
782 (uchar *)dr, (uchar *)outr, mask_src, mask / 65535.0f);
783 }
784 else {
785 mask_src[3] = divide_round_i(src[3] * mask, 65535);
786 func((uchar *)dr, (uchar *)outr, mask_src);
787 }
788 }
789 }
790 }
791 dmaskrect += origskip;
792 }
793 /* No destination mask buffer, do regular blend with mask-texture if present. */
794 else {
795 for (x = width; x > 0; x--, dr++, outr++, sr++, cmr++) {
796 uchar *src = (uchar *)sr;
797 float mask = mask_max * float(*cmr);
798
799 if (texmaskrect) {
800 mask *= (float(*tmr++) / 65535.0f);
801 }
802
803 mask = min_ff(mask, 65535.0);
804
805 if (src[3] && (mask > 0.0f)) {
806 uchar mask_src[4];
807
808 mask_src[0] = src[0];
809 mask_src[1] = src[1];
810 mask_src[2] = src[2];
811
812 if (mode == IMB_BLEND_INTERPOLATE) {
813 mask_src[3] = src[3];
815 (uchar *)dr, (uchar *)outr, mask_src, mask / 65535.0f);
816 }
817 else {
818 mask_src[3] = divide_round_i(src[3] * mask, 65535);
819 func((uchar *)dr, (uchar *)outr, mask_src);
820 }
821 }
822 }
823 }
824
825 cmaskrect += srcskip;
826 if (texmaskrect) {
827 texmaskrect += srcskip;
828 }
829 }
830 else {
831 /* regular blending */
832 for (x = width; x > 0; x--, dr++, outr++, sr++) {
833 if (((uchar *)sr)[3]) {
834 func((uchar *)dr, (uchar *)outr, (uchar *)sr);
835 }
836 }
837 }
838
839 drect += destskip;
840 orect += origskip;
841 srect += srcskip;
842 }
843
844 if (do_float) {
845 drf = drectf;
846 orf = orectf;
847 srf = srectf;
848
849 if (cmaskrect) {
850 /* mask accumulation for painting */
851 cmr = cmaskrect;
852 tmr = texmaskrect;
853
854 /* destination mask present, do max alpha masking */
855 if (dmaskrect) {
856 dmr = dmaskrect;
857 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
858 float mask_lim = mask_max * (*cmr);
859
860 if (texmaskrect) {
861 mask_lim *= ((*tmr++) / 65535.0f);
862 }
863
864 if (srf[3] && mask_lim) {
865 float mask;
866
867 if (accumulate) {
868 mask = min_ff(*dmr + mask_lim, 65535.0);
869 }
870 else {
871 mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
872 }
873
874 mask = min_ff(mask, 65535.0);
875
876 if (mask > *dmr) {
877 *dmr = mask;
878
879 if (mode == IMB_BLEND_INTERPOLATE) {
880 blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
881 }
882 else {
883 float mask_srf[4];
884 mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
885 func_float(drf, orf, mask_srf);
886 }
887 }
888 }
889 }
890 dmaskrect += origskip;
891 }
892 /* No destination mask buffer, do regular blend with mask-texture if present. */
893 else {
894 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
895 float mask = mask_max * float(*cmr);
896
897 if (texmaskrect) {
898 mask *= (float(*tmr++) / 65535.0f);
899 }
900
901 mask = min_ff(mask, 65535.0);
902
903 if (srf[3] && (mask > 0.0f)) {
904 if (mode == IMB_BLEND_INTERPOLATE) {
905 blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
906 }
907 else {
908 float mask_srf[4];
909 mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
910 func_float(drf, orf, mask_srf);
911 }
912 }
913 }
914 }
915
916 cmaskrect += srcskip;
917 if (texmaskrect) {
918 texmaskrect += srcskip;
919 }
920 }
921 else {
922 /* regular blending */
923 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) {
924 if (srf[3] != 0) {
925 func_float(drf, orf, srf);
926 }
927 }
928 }
929
930 drectf += destskip * 4;
931 orectf += origskip * 4;
932 srectf += srcskip * 4;
933 }
934 }
935 }
936}
937
939 const ImBuf *obuf,
940 const ImBuf *sbuf,
941 ushort *dmask,
942 const ushort *curvemask,
943 const ushort *texmask,
944 float mask_max,
945 int destx,
946 int desty,
947 int origx,
948 int origy,
949 int srcx,
950 int srcy,
951 int width,
952 int height,
953 IMB_BlendMode mode,
954 bool accumulate)
955{
956 using namespace blender;
957 threading::parallel_for(IndexRange(height), 16, [&](const IndexRange y_range) {
958 IMB_rectblend(dbuf,
959 obuf,
960 sbuf,
961 dmask,
962 curvemask,
963 texmask,
964 mask_max,
965 destx,
966 desty + y_range.first(),
967 origx,
968 origy + y_range.first(),
969 srcx,
970 srcy + y_range.first(),
971 width,
972 y_range.size(),
973 mode,
974 accumulate);
975 });
976}
977
978void IMB_rectfill(ImBuf *drect, const float col[4])
979{
980 size_t num;
981
982 if (drect->byte_buffer.data) {
983 uint *rrect = (uint *)drect->byte_buffer.data;
984
985 char ccol[4];
987
988 num = IMB_get_pixel_count(drect);
989 for (; num > 0; num--) {
990 *rrect++ = *((uint *)ccol);
991 }
992 }
993
994 if (drect->float_buffer.data) {
995 float *rrectf = drect->float_buffer.data;
996
997 num = IMB_get_pixel_count(drect);
998 for (; num > 0; num--) {
999 *rrectf++ = col[0];
1000 *rrectf++ = col[1];
1001 *rrectf++ = col[2];
1002 *rrectf++ = col[3];
1003 }
1004 }
1005}
1006
1008 ImBuf *ibuf, const float scene_linear_color[4], int x1, int y1, int x2, int y2)
1009{
1010 if (!ibuf) {
1011 return;
1012 }
1013
1014 uchar *rect = ibuf->byte_buffer.data;
1015 float *rectf = ibuf->float_buffer.data;
1016 const int width = ibuf->x;
1017 const int height = ibuf->y;
1018
1019 if ((!rect && !rectf) || scene_linear_color[3] == 0.0f) {
1020 return;
1021 }
1022
1023 /* sanity checks for coords */
1024 CLAMP(x1, 0, width);
1025 CLAMP(x2, 0, width);
1026 CLAMP(y1, 0, height);
1027 CLAMP(y2, 0, height);
1028
1029 if (x1 > x2) {
1030 std::swap(x1, x2);
1031 }
1032 if (y1 > y2) {
1033 std::swap(y1, y2);
1034 }
1035 if (x1 == x2 || y1 == y2) {
1036 return;
1037 }
1038 const int x_span = x2 - x1;
1039 const int y_span = y2 - y1;
1040
1041 /* Alpha. */
1042 const float a = scene_linear_color[3];
1043 /* Alpha inverted. */
1044 const float ai = 1 - a;
1045 /* Alpha, inverted, ai/255.0 - Convert char to float at the same time. */
1046 const float aich = ai / 255.0f;
1047
1048 if (rect) {
1049 uchar *pixel;
1050 uchar chr = 0, chg = 0, chb = 0;
1051 float fr = 0, fg = 0, fb = 0;
1052
1053 const int alphaint = unit_float_to_uchar_clamp(a);
1054
1055 float col[3];
1056 copy_v3_v3(col, scene_linear_color);
1057 if (ibuf->byte_buffer.colorspace) {
1059 }
1060 else {
1062 }
1063
1064 if (a == 1.0f) {
1068 }
1069 else {
1070 fr = col[0] * a;
1071 fg = col[1] * a;
1072 fb = col[2] * a;
1073 }
1074 for (int j = 0; j < y_span; j++) {
1075 pixel = rect + (4 * (((size_t(y1) + size_t(j)) * size_t(width)) + size_t(x1)));
1076 for (int i = 0; i < x_span; i++) {
1077 BLI_assert(pixel >= rect && pixel < rect + (4 * (size_t(width) * size_t(height))));
1078 if (a == 1.0f) {
1079 pixel[0] = chr;
1080 pixel[1] = chg;
1081 pixel[2] = chb;
1082 pixel[3] = 255;
1083 }
1084 else {
1085 int alphatest;
1086 pixel[0] = char((fr + (float(pixel[0]) * aich)) * 255.0f);
1087 pixel[1] = char((fg + (float(pixel[1]) * aich)) * 255.0f);
1088 pixel[2] = char((fb + (float(pixel[2]) * aich)) * 255.0f);
1089 pixel[3] = char((alphatest = (int(pixel[3]) + alphaint)) < 255 ? alphatest : 255);
1090 }
1091 pixel += 4;
1092 }
1093 }
1094 }
1095
1096 if (rectf) {
1097 float *pixel;
1098
1099 for (int j = 0; j < y_span; j++) {
1100 pixel = rectf + (4 * (((size_t(y1) + j) * size_t(width)) + size_t(x1)));
1101 for (int i = 0; i < x_span; i++) {
1102 BLI_assert(pixel >= rectf && pixel < rectf + (4 * (size_t(width) * size_t(height))));
1103 if (a == 1.0f) {
1104 pixel[0] = scene_linear_color[0];
1105 pixel[1] = scene_linear_color[1];
1106 pixel[2] = scene_linear_color[2];
1107 pixel[3] = 1.0f;
1108 }
1109 else {
1110 float alphatest;
1111 pixel[0] = (scene_linear_color[0] * a) + (pixel[0] * ai);
1112 pixel[1] = (scene_linear_color[1] * a) + (pixel[1] * ai);
1113 pixel[2] = (scene_linear_color[2] * a) + (pixel[2] * ai);
1114 pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
1115 }
1116 pixel += 4;
1117 }
1118 }
1119 }
1120}
1121
1122void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
1123{
1124 size_t i;
1125
1126 if (ibuf->float_buffer.data && (ibuf->channels == 4)) {
1127 float *fbuf = ibuf->float_buffer.data + 3;
1128 for (i = IMB_get_pixel_count(ibuf); i > 0; i--, fbuf += 4) {
1129 *fbuf = value;
1130 }
1131 }
1132
1133 if (ibuf->byte_buffer.data) {
1134 const uchar cvalue = value * 255;
1135 uchar *cbuf = ibuf->byte_buffer.data + 3;
1136 for (i = IMB_get_pixel_count(ibuf); i > 0; i--, cbuf += 4) {
1137 *cbuf = cvalue;
1138 }
1139 }
1140}
#define BLI_assert(a)
Definition BLI_assert.h:46
MINLINE float min_ff(float a, float b)
MINLINE int divide_round_i(int a, int b)
MINLINE void blend_color_add_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_exclusion_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_linearburn_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_overlay_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_saturation_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_burn_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_erase_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_color_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_linearlight_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_sub_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_saturation_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_hue_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_difference_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_dodge_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_luminosity_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_pinlight_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_mul_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_pinlight_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_erase_alpha_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_screen_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_screen_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_add_alpha_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_vividlight_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_linearburn_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_mul_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_vividlight_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_darken_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_luminosity_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_difference_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_burn_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_add_alpha_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_color_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_overlay_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_dodge_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_hardlight_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_sub_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_darken_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_softlight_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_add_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_hue_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_lighten_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_exclusion_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_mix_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4])
MINLINE void blend_color_hardlight_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_interpolate_byte(unsigned char dst[4], const unsigned char src1[4], const unsigned char src2[4], float ft)
MINLINE void blend_color_linearlight_byte(unsigned char dst[4], const uchar src1[4], const uchar src2[4])
MINLINE void blend_color_lighten_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_softlight_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
ATTR_WARN_UNUSED_RESULT const size_t num
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
unsigned char uchar
unsigned int uint
unsigned short ushort
#define CLAMP(a, b, c)
void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], const ColorSpace *colorspace)
BLI_INLINE void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scene_linear[3])
IMB_BlendMode
Definition IMB_imbuf.hh:178
@ IMB_BLEND_EXCLUSION
Definition IMB_imbuf.hh:198
@ IMB_BLEND_DIFFERENCE
Definition IMB_imbuf.hh:197
@ IMB_BLEND_HARDLIGHT
Definition IMB_imbuf.hh:188
@ IMB_BLEND_COLORBURN
Definition IMB_imbuf.hh:189
@ IMB_BLEND_COLORDODGE
Definition IMB_imbuf.hh:191
@ IMB_BLEND_ERASE_ALPHA
Definition IMB_imbuf.hh:185
@ IMB_BLEND_SCREEN
Definition IMB_imbuf.hh:192
@ IMB_BLEND_HUE
Definition IMB_imbuf.hh:199
@ IMB_BLEND_MUL
Definition IMB_imbuf.hh:182
@ IMB_BLEND_ADD_ALPHA
Definition IMB_imbuf.hh:186
@ IMB_BLEND_DARKEN
Definition IMB_imbuf.hh:184
@ IMB_BLEND_OVERLAY
Definition IMB_imbuf.hh:187
@ IMB_BLEND_SATURATION
Definition IMB_imbuf.hh:200
@ IMB_BLEND_VIVIDLIGHT
Definition IMB_imbuf.hh:195
@ IMB_BLEND_LUMINOSITY
Definition IMB_imbuf.hh:201
@ IMB_BLEND_LIGHTEN
Definition IMB_imbuf.hh:183
@ IMB_BLEND_SOFTLIGHT
Definition IMB_imbuf.hh:193
@ IMB_BLEND_COPY_RGB
Definition IMB_imbuf.hh:206
@ IMB_BLEND_COLOR
Definition IMB_imbuf.hh:202
@ IMB_BLEND_LINEARLIGHT
Definition IMB_imbuf.hh:196
@ IMB_BLEND_COPY_ALPHA
Definition IMB_imbuf.hh:207
@ IMB_BLEND_PINLIGHT
Definition IMB_imbuf.hh:194
@ IMB_BLEND_MIX
Definition IMB_imbuf.hh:179
@ IMB_BLEND_COPY
Definition IMB_imbuf.hh:205
@ IMB_BLEND_INTERPOLATE
Definition IMB_imbuf.hh:203
@ IMB_BLEND_ADD
Definition IMB_imbuf.hh:180
@ IMB_BLEND_SUB
Definition IMB_imbuf.hh:181
@ IMB_BLEND_LINEARBURN
Definition IMB_imbuf.hh:190
size_t IMB_get_pixel_count(const ImBuf *ibuf)
Get the length of the data of the given image buffer in pixels.
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
constexpr int64_t first() const
constexpr int64_t size() const
nullptr float
uint col
BLI_INLINE float fb(float length, float L)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
#define unit_float_to_uchar_clamp_v4(v1, v2)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
static void rect_realloc_16bytes(void **buf_p, const uint size[2])
Definition rectop.cc:279
void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
Definition rectop.cc:1122
static void rect_crop_4bytes(void **buf_p, const int size_src[2], const rcti *crop)
Definition rectop.cc:207
static void rect_crop_16bytes(void **buf_p, const int size_src[2], const rcti *crop)
Definition rectop.cc:224
void IMB_rectblend_threaded(ImBuf *dbuf, const ImBuf *obuf, const ImBuf *sbuf, ushort *dmask, const ushort *curvemask, const ushort *texmask, float mask_max, int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height, IMB_BlendMode mode, bool accumulate)
Definition rectop.cc:938
void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
Definition rectop.cc:241
void IMB_rectblend(ImBuf *dbuf, const ImBuf *obuf, const ImBuf *sbuf, ushort *dmask, const ushort *curvemask, const ushort *texmask, float mask_max, int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height, IMB_BlendMode mode, bool accumulate)
Definition rectop.cc:475
void(*)(uchar *dst, const uchar *src1, const uchar *src2) IMB_blend_func
Definition rectop.cc:472
void IMB_rectclip(ImBuf *dbuf, const ImBuf *sbuf, int *destx, int *desty, int *srcx, int *srcy, int *width, int *height)
Definition rectop.cc:307
static void imb_rectclip3(ImBuf *dbuf, const ImBuf *obuf, const ImBuf *sbuf, int *destx, int *desty, int *origx, int *origy, int *srcx, int *srcy, int *width, int *height)
Definition rectop.cc:361
void IMB_blend_color_byte(uchar dst[4], const uchar src1[4], const uchar src2[4], IMB_BlendMode mode)
Definition rectop.cc:28
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Definition rectop.cc:116
void IMB_rectfill(ImBuf *drect, const float col[4])
Definition rectop.cc:978
void IMB_rectfill_area(ImBuf *ibuf, const float scene_linear_color[4], int x1, int y1, int x2, int y2)
Definition rectop.cc:1007
void(*)(float *dst, const float *src1, const float *src2) IMB_blend_func_float
Definition rectop.cc:473
void IMB_rect_size_set(ImBuf *ibuf, const uint size[2])
Definition rectop.cc:288
static void rect_realloc_4bytes(void **buf_p, const uint size[2])
Definition rectop.cc:270
void IMB_rectcpy(ImBuf *dbuf, const ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
Definition rectop.cc:444
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
int ymin
int ymax
int xmin
int xmax
i
Definition text_draw.cc:230