Blender V4.3
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
9#include <cstdlib>
10
11#include "BLI_math_base.h"
12#include "BLI_math_color.h"
14#include "BLI_math_vector.h"
15#include "BLI_rect.h"
16#include "BLI_utildefines.h"
17
18#include "IMB_imbuf.hh"
19#include "IMB_imbuf_types.hh"
20
22
23#include "MEM_guardedalloc.h"
24
25#include <cstring>
26
28 const uchar src1[4],
29 const uchar src2[4],
30 IMB_BlendMode mode)
31{
32 switch (mode) {
33 case IMB_BLEND_MIX:
34 blend_color_mix_byte(dst, src1, src2);
35 break;
36 case IMB_BLEND_ADD:
37 blend_color_add_byte(dst, src1, src2);
38 break;
39 case IMB_BLEND_SUB:
40 blend_color_sub_byte(dst, src1, src2);
41 break;
42 case IMB_BLEND_MUL:
43 blend_color_mul_byte(dst, src1, src2);
44 break;
46 blend_color_lighten_byte(dst, src1, src2);
47 break;
49 blend_color_darken_byte(dst, src1, src2);
50 break;
52 blend_color_erase_alpha_byte(dst, src1, src2);
53 break;
55 blend_color_add_alpha_byte(dst, src1, src2);
56 break;
58 blend_color_overlay_byte(dst, src1, src2);
59 break;
61 blend_color_hardlight_byte(dst, src1, src2);
62 break;
64 blend_color_burn_byte(dst, src1, src2);
65 break;
67 blend_color_linearburn_byte(dst, src1, src2);
68 break;
70 blend_color_dodge_byte(dst, src1, src2);
71 break;
73 blend_color_screen_byte(dst, src1, src2);
74 break;
76 blend_color_softlight_byte(dst, src1, src2);
77 break;
79 blend_color_pinlight_byte(dst, src1, src2);
80 break;
82 blend_color_linearlight_byte(dst, src1, src2);
83 break;
85 blend_color_vividlight_byte(dst, src1, src2);
86 break;
88 blend_color_difference_byte(dst, src1, src2);
89 break;
91 blend_color_exclusion_byte(dst, src1, src2);
92 break;
93 case IMB_BLEND_COLOR:
94 blend_color_color_byte(dst, src1, src2);
95 break;
96 case IMB_BLEND_HUE:
97 blend_color_hue_byte(dst, src1, src2);
98 break;
100 blend_color_saturation_byte(dst, src1, src2);
101 break;
103 blend_color_luminosity_byte(dst, src1, src2);
104 break;
105
106 default:
107 dst[0] = src1[0];
108 dst[1] = src1[1];
109 dst[2] = src1[2];
110 dst[3] = src1[3];
111 break;
112 }
113}
114
115void IMB_blend_color_float(float dst[4],
116 const float src1[4],
117 const float src2[4],
118 IMB_BlendMode mode)
119{
120 switch (mode) {
121 case IMB_BLEND_MIX:
122 blend_color_mix_float(dst, src1, src2);
123 break;
124 case IMB_BLEND_ADD:
125 blend_color_add_float(dst, src1, src2);
126 break;
127 case IMB_BLEND_SUB:
128 blend_color_sub_float(dst, src1, src2);
129 break;
130 case IMB_BLEND_MUL:
131 blend_color_mul_float(dst, src1, src2);
132 break;
134 blend_color_lighten_float(dst, src1, src2);
135 break;
136 case IMB_BLEND_DARKEN:
137 blend_color_darken_float(dst, src1, src2);
138 break;
140 blend_color_erase_alpha_float(dst, src1, src2);
141 break;
143 blend_color_add_alpha_float(dst, src1, src2);
144 break;
146 blend_color_overlay_float(dst, src1, src2);
147 break;
149 blend_color_hardlight_float(dst, src1, src2);
150 break;
152 blend_color_burn_float(dst, src1, src2);
153 break;
155 blend_color_linearburn_float(dst, src1, src2);
156 break;
158 blend_color_dodge_float(dst, src1, src2);
159 break;
160 case IMB_BLEND_SCREEN:
161 blend_color_screen_float(dst, src1, src2);
162 break;
164 blend_color_softlight_float(dst, src1, src2);
165 break;
167 blend_color_pinlight_float(dst, src1, src2);
168 break;
170 blend_color_linearlight_float(dst, src1, src2);
171 break;
173 blend_color_vividlight_float(dst, src1, src2);
174 break;
176 blend_color_difference_float(dst, src1, src2);
177 break;
179 blend_color_exclusion_float(dst, src1, src2);
180 break;
181 case IMB_BLEND_COLOR:
182 blend_color_color_float(dst, src1, src2);
183 break;
184 case IMB_BLEND_HUE:
185 blend_color_hue_float(dst, src1, src2);
186 break;
188 blend_color_saturation_float(dst, src1, src2);
189 break;
191 blend_color_luminosity_float(dst, src1, src2);
192 break;
193 default:
194 dst[0] = src1[0];
195 dst[1] = src1[1];
196 dst[2] = src1[2];
197 dst[3] = src1[3];
198 break;
199 }
200}
201
202/* -------------------------------------------------------------------- */
206static void rect_crop_4bytes(void **buf_p, const int size_src[2], const rcti *crop)
207{
208 if (*buf_p == nullptr) {
209 return;
210 }
211 const int size_dst[2] = {
212 BLI_rcti_size_x(crop) + 1,
213 BLI_rcti_size_y(crop) + 1,
214 };
215 uint *src = static_cast<uint *>(*buf_p);
216 uint *dst = src + crop->ymin * size_src[0] + crop->xmin;
217 for (int y = 0; y < size_dst[1]; y++, src += size_dst[0], dst += size_src[0]) {
218 memmove(src, dst, sizeof(uint) * size_dst[0]);
219 }
220 *buf_p = MEM_reallocN(*buf_p, sizeof(uint) * size_dst[0] * size_dst[1]);
221}
222
223static void rect_crop_16bytes(void **buf_p, const int size_src[2], const rcti *crop)
224{
225 if (*buf_p == nullptr) {
226 return;
227 }
228 const int size_dst[2] = {
229 BLI_rcti_size_x(crop) + 1,
230 BLI_rcti_size_y(crop) + 1,
231 };
232 uint(*src)[4] = static_cast<uint(*)[4]>(*buf_p);
233 uint(*dst)[4] = src + crop->ymin * size_src[0] + crop->xmin;
234 for (int y = 0; y < size_dst[1]; y++, src += size_dst[0], dst += size_src[0]) {
235 memmove(src, dst, sizeof(uint[4]) * size_dst[0]);
236 }
237 *buf_p = (void *)MEM_reallocN(*buf_p, sizeof(uint[4]) * size_dst[0] * size_dst[1]);
238}
239
240void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
241{
242 const int size_src[2] = {
243 ibuf->x,
244 ibuf->y,
245 };
246 const int size_dst[2] = {
247 BLI_rcti_size_x(crop) + 1,
248 BLI_rcti_size_y(crop) + 1,
249 };
250 BLI_assert(size_dst[0] > 0 && size_dst[1] > 0);
251 BLI_assert(crop->xmin >= 0 && crop->ymin >= 0);
252 BLI_assert(crop->xmax < ibuf->x && crop->ymax < ibuf->y);
253
254 if ((size_dst[0] == ibuf->x) && (size_dst[1] == ibuf->y)) {
255 return;
256 }
257
258 /* TODO(sergey: Validate ownership. */
259 rect_crop_4bytes((void **)&ibuf->byte_buffer.data, size_src, crop);
260 rect_crop_16bytes((void **)&ibuf->float_buffer.data, size_src, crop);
261
262 ibuf->x = size_dst[0];
263 ibuf->y = size_dst[1];
264}
265
269static void rect_realloc_4bytes(void **buf_p, const uint size[2])
270{
271 if (*buf_p == nullptr) {
272 return;
273 }
274 MEM_freeN(*buf_p);
275 *buf_p = MEM_mallocN(sizeof(uint) * size[0] * size[1], __func__);
276}
277
278static void rect_realloc_16bytes(void **buf_p, const uint size[2])
279{
280 if (*buf_p == nullptr) {
281 return;
282 }
283 MEM_freeN(*buf_p);
284 *buf_p = MEM_mallocN(sizeof(uint[4]) * size[0] * size[1], __func__);
285}
286
287void IMB_rect_size_set(ImBuf *ibuf, const uint size[2])
288{
289 BLI_assert(size[0] > 0 && size[1] > 0);
290 if ((size[0] == ibuf->x) && (size[1] == ibuf->y)) {
291 return;
292 }
293
294 /* TODO(sergey: Validate ownership. */
295 rect_realloc_4bytes((void **)&ibuf->byte_buffer.data, size);
296 rect_realloc_16bytes((void **)&ibuf->float_buffer.data, size);
297
298 ibuf->x = size[0];
299 ibuf->y = size[1];
300}
301
304/* clipping */
305
307 const ImBuf *sbuf,
308 int *destx,
309 int *desty,
310 int *srcx,
311 int *srcy,
312 int *width,
313 int *height)
314{
315 int tmp;
316
317 if (dbuf == nullptr) {
318 return;
319 }
320
321 if (*destx < 0) {
322 *srcx -= *destx;
323 *width += *destx;
324 *destx = 0;
325 }
326 if (*srcx < 0) {
327 *destx -= *srcx;
328 *width += *srcx;
329 *srcx = 0;
330 }
331 if (*desty < 0) {
332 *srcy -= *desty;
333 *height += *desty;
334 *desty = 0;
335 }
336 if (*srcy < 0) {
337 *desty -= *srcy;
338 *height += *srcy;
339 *srcy = 0;
340 }
341
342 tmp = dbuf->x - *destx;
343 if (*width > tmp) {
344 *width = tmp;
345 }
346 tmp = dbuf->y - *desty;
347 if (*height > tmp) {
348 *height = tmp;
349 }
350
351 if (sbuf) {
352 tmp = sbuf->x - *srcx;
353 if (*width > tmp) {
354 *width = tmp;
355 }
356 tmp = sbuf->y - *srcy;
357 if (*height > tmp) {
358 *height = tmp;
359 }
360 }
361
362 if ((*height <= 0) || (*width <= 0)) {
363 *width = 0;
364 *height = 0;
365 }
366}
367
368static void imb_rectclip3(ImBuf *dbuf,
369 const ImBuf *obuf,
370 const ImBuf *sbuf,
371 int *destx,
372 int *desty,
373 int *origx,
374 int *origy,
375 int *srcx,
376 int *srcy,
377 int *width,
378 int *height)
379{
380 int tmp;
381
382 if (dbuf == nullptr) {
383 return;
384 }
385
386 if (*destx < 0) {
387 *srcx -= *destx;
388 *origx -= *destx;
389 *width += *destx;
390 *destx = 0;
391 }
392 if (*origx < 0) {
393 *destx -= *origx;
394 *srcx -= *origx;
395 *width += *origx;
396 *origx = 0;
397 }
398 if (*srcx < 0) {
399 *destx -= *srcx;
400 *origx -= *srcx;
401 *width += *srcx;
402 *srcx = 0;
403 }
404
405 if (*desty < 0) {
406 *srcy -= *desty;
407 *origy -= *desty;
408 *height += *desty;
409 *desty = 0;
410 }
411 if (*origy < 0) {
412 *desty -= *origy;
413 *srcy -= *origy;
414 *height += *origy;
415 *origy = 0;
416 }
417 if (*srcy < 0) {
418 *desty -= *srcy;
419 *origy -= *srcy;
420 *height += *srcy;
421 *srcy = 0;
422 }
423
424 tmp = dbuf->x - *destx;
425 if (*width > tmp) {
426 *width = tmp;
427 }
428 tmp = dbuf->y - *desty;
429 if (*height > tmp) {
430 *height = tmp;
431 }
432
433 if (obuf) {
434 tmp = obuf->x - *origx;
435 if (*width > tmp) {
436 *width = tmp;
437 }
438 tmp = obuf->y - *origy;
439 if (*height > tmp) {
440 *height = tmp;
441 }
442 }
443
444 if (sbuf) {
445 tmp = sbuf->x - *srcx;
446 if (*width > tmp) {
447 *width = tmp;
448 }
449 tmp = sbuf->y - *srcy;
450 if (*height > tmp) {
451 *height = tmp;
452 }
453 }
454
455 if ((*height <= 0) || (*width <= 0)) {
456 *width = 0;
457 *height = 0;
458 }
459}
460
461/* copy and blend */
462
464 const ImBuf *sbuf,
465 int destx,
466 int desty,
467 int srcx,
468 int srcy,
469 int width,
470 int height)
471{
472 IMB_rectblend(dbuf,
473 dbuf,
474 sbuf,
475 nullptr,
476 nullptr,
477 nullptr,
478 0,
479 destx,
480 desty,
481 destx,
482 desty,
483 srcx,
484 srcy,
485 width,
486 height,
488 false);
489}
490
491using IMB_blend_func = void (*)(uchar *dst, const uchar *src1, const uchar *src2);
492using IMB_blend_func_float = void (*)(float *dst, const float *src1, const float *src2);
493
495 const ImBuf *obuf,
496 const ImBuf *sbuf,
497 ushort *dmask,
498 const ushort *curvemask,
499 const ushort *texmask,
500 float mask_max,
501 int destx,
502 int desty,
503 int origx,
504 int origy,
505 int srcx,
506 int srcy,
507 int width,
508 int height,
509 IMB_BlendMode mode,
510 bool accumulate)
511{
512 uint *drect = nullptr, *orect = nullptr, *srect = nullptr, *dr, *outr, *sr;
513 float *drectf = nullptr, *orectf = nullptr, *srectf = nullptr, *drf, *orf, *srf;
514 const ushort *cmaskrect = curvemask, *cmr;
515 ushort *dmaskrect = dmask, *dmr;
516 const ushort *texmaskrect = texmask, *tmr;
517 int srcskip, destskip, origskip, x;
518 IMB_blend_func func = nullptr;
519 IMB_blend_func_float func_float = nullptr;
520
521 if (dbuf == nullptr || obuf == nullptr) {
522 return;
523 }
524
525 imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height);
526
527 if (width == 0 || height == 0) {
528 return;
529 }
530 if (sbuf && sbuf->channels != 4) {
531 return;
532 }
533 if (dbuf->channels != 4) {
534 return;
535 }
536
537 const bool do_char = (sbuf && sbuf->byte_buffer.data && dbuf->byte_buffer.data &&
538 obuf->byte_buffer.data);
539 const bool do_float = (sbuf && sbuf->float_buffer.data && dbuf->float_buffer.data &&
540 obuf->float_buffer.data);
541
542 if (do_char) {
543 drect = (uint *)dbuf->byte_buffer.data + size_t(desty) * dbuf->x + destx;
544 orect = (uint *)obuf->byte_buffer.data + size_t(origy) * obuf->x + origx;
545 }
546 if (do_float) {
547 drectf = dbuf->float_buffer.data + (size_t(desty) * dbuf->x + destx) * 4;
548 orectf = obuf->float_buffer.data + (size_t(origy) * obuf->x + origx) * 4;
549 }
550
551 if (dmaskrect) {
552 dmaskrect += size_t(origy) * obuf->x + origx;
553 }
554
555 destskip = dbuf->x;
556 origskip = obuf->x;
557
558 if (sbuf) {
559 if (do_char) {
560 srect = (uint *)sbuf->byte_buffer.data + size_t(srcy) * sbuf->x + srcx;
561 }
562 if (do_float) {
563 srectf = sbuf->float_buffer.data + (size_t(srcy) * sbuf->x + srcx) * 4;
564 }
565 srcskip = sbuf->x;
566
567 if (cmaskrect) {
568 cmaskrect += size_t(srcy) * sbuf->x + srcx;
569 }
570
571 if (texmaskrect) {
572 texmaskrect += size_t(srcy) * sbuf->x + srcx;
573 }
574 }
575 else {
576 srect = drect;
577 srectf = drectf;
578 srcskip = destskip;
579 }
580
581 if (mode == IMB_BLEND_COPY) {
582 /* copy */
583 for (; height > 0; height--) {
584 if (do_char) {
585 memcpy(drect, srect, width * sizeof(int));
586 drect += destskip;
587 srect += srcskip;
588 }
589
590 if (do_float) {
591 memcpy(drectf, srectf, sizeof(float[4]) * width);
592 drectf += destskip * 4;
593 srectf += srcskip * 4;
594 }
595 }
596 }
597 else if (mode == IMB_BLEND_COPY_RGB) {
598 /* copy rgb only */
599 for (; height > 0; height--) {
600 if (do_char) {
601 dr = drect;
602 sr = srect;
603 for (x = width; x > 0; x--, dr++, sr++) {
604 ((char *)dr)[0] = ((char *)sr)[0];
605 ((char *)dr)[1] = ((char *)sr)[1];
606 ((char *)dr)[2] = ((char *)sr)[2];
607 }
608 drect += destskip;
609 srect += srcskip;
610 }
611
612 if (do_float) {
613 drf = drectf;
614 srf = srectf;
615 for (x = width; x > 0; x--, drf += 4, srf += 4) {
616 float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3];
617
618 drf[0] = srf[0] * map_alpha;
619 drf[1] = srf[1] * map_alpha;
620 drf[2] = srf[2] * map_alpha;
621 }
622 drectf += destskip * 4;
623 srectf += srcskip * 4;
624 }
625 }
626 }
627 else if (mode == IMB_BLEND_COPY_ALPHA) {
628 /* copy alpha only */
629 for (; height > 0; height--) {
630 if (do_char) {
631 dr = drect;
632 sr = srect;
633 for (x = width; x > 0; x--, dr++, sr++) {
634 ((char *)dr)[3] = ((char *)sr)[3];
635 }
636 drect += destskip;
637 srect += srcskip;
638 }
639
640 if (do_float) {
641 drf = drectf;
642 srf = srectf;
643 for (x = width; x > 0; x--, drf += 4, srf += 4) {
644 drf[3] = srf[3];
645 }
646 drectf += destskip * 4;
647 srectf += srcskip * 4;
648 }
649 }
650 }
651 else {
652 switch (mode) {
653 case IMB_BLEND_MIX:
656 func_float = blend_color_mix_float;
657 break;
658 case IMB_BLEND_ADD:
660 func_float = blend_color_add_float;
661 break;
662 case IMB_BLEND_SUB:
664 func_float = blend_color_sub_float;
665 break;
666 case IMB_BLEND_MUL:
668 func_float = blend_color_mul_float;
669 break;
672 func_float = blend_color_lighten_float;
673 break;
674 case IMB_BLEND_DARKEN:
676 func_float = blend_color_darken_float;
677 break;
681 break;
684 func_float = blend_color_add_alpha_float;
685 break;
688 func_float = blend_color_overlay_float;
689 break;
692 func_float = blend_color_hardlight_float;
693 break;
696 func_float = blend_color_burn_float;
697 break;
700 func_float = blend_color_linearburn_float;
701 break;
704 func_float = blend_color_dodge_float;
705 break;
706 case IMB_BLEND_SCREEN:
708 func_float = blend_color_screen_float;
709 break;
712 func_float = blend_color_softlight_float;
713 break;
716 func_float = blend_color_pinlight_float;
717 break;
721 break;
724 func_float = blend_color_vividlight_float;
725 break;
728 func_float = blend_color_difference_float;
729 break;
732 func_float = blend_color_exclusion_float;
733 break;
734 case IMB_BLEND_COLOR:
736 func_float = blend_color_color_float;
737 break;
738 case IMB_BLEND_HUE:
740 func_float = blend_color_hue_float;
741 break;
744 func_float = blend_color_saturation_float;
745 break;
748 func_float = blend_color_luminosity_float;
749 break;
750 default:
751 break;
752 }
753
754 /* blend */
755 for (; height > 0; height--) {
756 if (do_char) {
757 dr = drect;
758 outr = orect;
759 sr = srect;
760
761 if (cmaskrect) {
762 /* mask accumulation for painting */
763 cmr = cmaskrect;
764 tmr = texmaskrect;
765
766 /* destination mask present, do max alpha masking */
767 if (dmaskrect) {
768 dmr = dmaskrect;
769 for (x = width; x > 0; x--, dr++, outr++, sr++, dmr++, cmr++) {
770 uchar *src = (uchar *)sr;
771 float mask_lim = mask_max * (*cmr);
772
773 if (texmaskrect) {
774 mask_lim *= ((*tmr++) / 65535.0f);
775 }
776
777 if (src[3] && mask_lim) {
778 float mask;
779
780 if (accumulate) {
781 mask = *dmr + mask_lim;
782 }
783 else {
784 mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
785 }
786
787 mask = min_ff(mask, 65535.0);
788
789 if (mask > *dmr) {
790 uchar mask_src[4];
791
792 *dmr = mask;
793
794 mask_src[0] = src[0];
795 mask_src[1] = src[1];
796 mask_src[2] = src[2];
797
798 if (mode == IMB_BLEND_INTERPOLATE) {
799 mask_src[3] = src[3];
801 (uchar *)dr, (uchar *)outr, mask_src, mask / 65535.0f);
802 }
803 else {
804 mask_src[3] = divide_round_i(src[3] * mask, 65535);
805 func((uchar *)dr, (uchar *)outr, mask_src);
806 }
807 }
808 }
809 }
810 dmaskrect += origskip;
811 }
812 /* No destination mask buffer, do regular blend with mask-texture if present. */
813 else {
814 for (x = width; x > 0; x--, dr++, outr++, sr++, cmr++) {
815 uchar *src = (uchar *)sr;
816 float mask = float(mask_max) * float(*cmr);
817
818 if (texmaskrect) {
819 mask *= (float(*tmr++) / 65535.0f);
820 }
821
822 mask = min_ff(mask, 65535.0);
823
824 if (src[3] && (mask > 0.0f)) {
825 uchar mask_src[4];
826
827 mask_src[0] = src[0];
828 mask_src[1] = src[1];
829 mask_src[2] = src[2];
830
831 if (mode == IMB_BLEND_INTERPOLATE) {
832 mask_src[3] = src[3];
834 (uchar *)dr, (uchar *)outr, mask_src, mask / 65535.0f);
835 }
836 else {
837 mask_src[3] = divide_round_i(src[3] * mask, 65535);
838 func((uchar *)dr, (uchar *)outr, mask_src);
839 }
840 }
841 }
842 }
843
844 cmaskrect += srcskip;
845 if (texmaskrect) {
846 texmaskrect += srcskip;
847 }
848 }
849 else {
850 /* regular blending */
851 for (x = width; x > 0; x--, dr++, outr++, sr++) {
852 if (((uchar *)sr)[3]) {
853 func((uchar *)dr, (uchar *)outr, (uchar *)sr);
854 }
855 }
856 }
857
858 drect += destskip;
859 orect += origskip;
860 srect += srcskip;
861 }
862
863 if (do_float) {
864 drf = drectf;
865 orf = orectf;
866 srf = srectf;
867
868 if (cmaskrect) {
869 /* mask accumulation for painting */
870 cmr = cmaskrect;
871 tmr = texmaskrect;
872
873 /* destination mask present, do max alpha masking */
874 if (dmaskrect) {
875 dmr = dmaskrect;
876 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
877 float mask_lim = mask_max * (*cmr);
878
879 if (texmaskrect) {
880 mask_lim *= ((*tmr++) / 65535.0f);
881 }
882
883 if (srf[3] && mask_lim) {
884 float mask;
885
886 if (accumulate) {
887 mask = min_ff(*dmr + mask_lim, 65535.0);
888 }
889 else {
890 mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
891 }
892
893 mask = min_ff(mask, 65535.0);
894
895 if (mask > *dmr) {
896 *dmr = mask;
897
898 if (mode == IMB_BLEND_INTERPOLATE) {
899 blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
900 }
901 else {
902 float mask_srf[4];
903 mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
904 func_float(drf, orf, mask_srf);
905 }
906 }
907 }
908 }
909 dmaskrect += origskip;
910 }
911 /* No destination mask buffer, do regular blend with mask-texture if present. */
912 else {
913 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
914 float mask = float(mask_max) * float(*cmr);
915
916 if (texmaskrect) {
917 mask *= (float(*tmr++) / 65535.0f);
918 }
919
920 mask = min_ff(mask, 65535.0);
921
922 if (srf[3] && (mask > 0.0f)) {
923 if (mode == IMB_BLEND_INTERPOLATE) {
924 blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
925 }
926 else {
927 float mask_srf[4];
928 mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
929 func_float(drf, orf, mask_srf);
930 }
931 }
932 }
933 }
934
935 cmaskrect += srcskip;
936 if (texmaskrect) {
937 texmaskrect += srcskip;
938 }
939 }
940 else {
941 /* regular blending */
942 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) {
943 if (srf[3] != 0) {
944 func_float(drf, orf, srf);
945 }
946 }
947 }
948
949 drectf += destskip * 4;
950 orectf += origskip * 4;
951 srectf += srcskip * 4;
952 }
953 }
954 }
955}
956
968
969static void rectblend_thread_do(void *data_v, int scanline)
970{
971 const int num_scanlines = 1;
973 IMB_rectblend(data->dbuf,
974 data->obuf,
975 data->sbuf,
976 data->dmask,
977 data->curvemask,
978 data->texmask,
979 data->mask_max,
980 data->destx,
981 data->desty + scanline,
982 data->origx,
983 data->origy + scanline,
984 data->srcx,
985 data->srcy + scanline,
986 data->width,
987 num_scanlines,
988 data->mode,
989 data->accumulate);
990}
991
993 const ImBuf *obuf,
994 const ImBuf *sbuf,
995 ushort *dmask,
996 const ushort *curvemask,
997 const ushort *texmask,
998 float mask_max,
999 int destx,
1000 int desty,
1001 int origx,
1002 int origy,
1003 int srcx,
1004 int srcy,
1005 int width,
1006 int height,
1007 IMB_BlendMode mode,
1008 bool accumulate)
1009{
1010 if (size_t(width) * height < 64 * 64) {
1011 IMB_rectblend(dbuf,
1012 obuf,
1013 sbuf,
1014 dmask,
1015 curvemask,
1016 texmask,
1017 mask_max,
1018 destx,
1019 desty,
1020 origx,
1021 origy,
1022 srcx,
1023 srcy,
1024 width,
1025 height,
1026 mode,
1027 accumulate);
1028 }
1029 else {
1031 data.dbuf = dbuf;
1032 data.obuf = obuf;
1033 data.sbuf = sbuf;
1034 data.dmask = dmask;
1035 data.curvemask = curvemask;
1036 data.texmask = texmask;
1037 data.mask_max = mask_max;
1038 data.destx = destx;
1039 data.desty = desty;
1040 data.origx = origx;
1041 data.origy = origy;
1042 data.srcx = srcx;
1043 data.srcy = srcy;
1044 data.width = width;
1045 data.mode = mode;
1046 data.accumulate = accumulate;
1048 }
1049}
1050
1051void IMB_rectfill(ImBuf *drect, const float col[4])
1052{
1053 int num;
1054
1055 if (drect->byte_buffer.data) {
1056 uint *rrect = (uint *)drect->byte_buffer.data;
1057 char ccol[4];
1058
1059 ccol[0] = int(col[0] * 255);
1060 ccol[1] = int(col[1] * 255);
1061 ccol[2] = int(col[2] * 255);
1062 ccol[3] = int(col[3] * 255);
1063
1064 num = drect->x * drect->y;
1065 for (; num > 0; num--) {
1066 *rrect++ = *((uint *)ccol);
1067 }
1068 }
1069
1070 if (drect->float_buffer.data) {
1071 float *rrectf = drect->float_buffer.data;
1072
1073 num = drect->x * drect->y;
1074 for (; num > 0; num--) {
1075 *rrectf++ = col[0];
1076 *rrectf++ = col[1];
1077 *rrectf++ = col[2];
1078 *rrectf++ = col[3];
1079 }
1080 }
1081}
1082
1084 const ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2)
1085{
1086 /* Sanity checks. */
1087 BLI_assert(ibuf->channels == 4);
1088
1089 if (ibuf->channels != 4) {
1090 return;
1091 }
1092
1093 int width = ibuf->x;
1094 int height = ibuf->y;
1095 CLAMP(x1, 0, width);
1096 CLAMP(x2, 0, width);
1097 CLAMP(y1, 0, height);
1098 CLAMP(y2, 0, height);
1099
1100 if (x1 > x2) {
1101 std::swap(x1, x2);
1102 }
1103 if (y1 > y2) {
1104 std::swap(y1, y2);
1105 }
1106 if (x1 == x2 || y1 == y2) {
1107 return;
1108 }
1109
1110 const uchar col_char[4] = {
1111 uchar(col[0] * 255), uchar(col[1] * 255), uchar(col[2] * 255), uchar(col[3] * 255)};
1112
1113 for (int y = y1; y < y2; y++) {
1114 for (int x = x1; x < x2; x++) {
1115 size_t offset = size_t(ibuf->x) * y * 4 + 4 * x;
1116
1117 if (ibuf->byte_buffer.data) {
1118 uchar *rrect = ibuf->byte_buffer.data + offset;
1119 memcpy(rrect, col_char, sizeof(uchar[4]));
1120 }
1121
1122 if (ibuf->float_buffer.data) {
1123 float *rrectf = ibuf->float_buffer.data + offset;
1124 memcpy(rrectf, col, sizeof(float[4]));
1125 }
1126 }
1127 }
1128}
1129
1131 float *rectf,
1132 int width,
1133 int height,
1134 const float col[4],
1135 ColorManagedDisplay *display,
1136 int x1,
1137 int y1,
1138 int x2,
1139 int y2)
1140{
1141 int i, j;
1142 float a; /* alpha */
1143 float ai; /* alpha inverted */
1144 float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
1145 if ((!rect && !rectf) || (!col) || col[3] == 0.0f) {
1146 return;
1147 }
1148
1149 /* sanity checks for coords */
1150 CLAMP(x1, 0, width);
1151 CLAMP(x2, 0, width);
1152 CLAMP(y1, 0, height);
1153 CLAMP(y2, 0, height);
1154
1155 if (x1 > x2) {
1156 std::swap(x1, x2);
1157 }
1158 if (y1 > y2) {
1159 std::swap(y1, y2);
1160 }
1161 if (x1 == x2 || y1 == y2) {
1162 return;
1163 }
1164
1165 a = col[3];
1166 ai = 1 - a;
1167 aich = ai / 255.0f;
1168
1169 if (rect) {
1170 uchar *pixel;
1171 uchar chr = 0, chg = 0, chb = 0;
1172 float fr = 0, fg = 0, fb = 0;
1173
1174 const int alphaint = unit_float_to_uchar_clamp(a);
1175
1176 if (a == 1.0f) {
1180 }
1181 else {
1182 fr = col[0] * a;
1183 fg = col[1] * a;
1184 fb = col[2] * a;
1185 }
1186 for (j = 0; j < y2 - y1; j++) {
1187 for (i = 0; i < x2 - x1; i++) {
1188 pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
1189 if (pixel >= rect && pixel < rect + (4 * (width * height))) {
1190 if (a == 1.0f) {
1191 pixel[0] = chr;
1192 pixel[1] = chg;
1193 pixel[2] = chb;
1194 pixel[3] = 255;
1195 }
1196 else {
1197 int alphatest;
1198 pixel[0] = char((fr + (float(pixel[0]) * aich)) * 255.0f);
1199 pixel[1] = char((fg + (float(pixel[1]) * aich)) * 255.0f);
1200 pixel[2] = char((fb + (float(pixel[2]) * aich)) * 255.0f);
1201 pixel[3] = char((alphatest = (int(pixel[3]) + alphaint)) < 255 ? alphatest : 255);
1202 }
1203 }
1204 }
1205 }
1206 }
1207
1208 if (rectf) {
1209 float col_conv[4];
1210 float *pixel;
1211
1212 if (display) {
1213 copy_v4_v4(col_conv, col);
1215 }
1216 else {
1217 srgb_to_linearrgb_v4(col_conv, col);
1218 }
1219
1220 for (j = 0; j < y2 - y1; j++) {
1221 for (i = 0; i < x2 - x1; i++) {
1222 pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
1223 if (a == 1.0f) {
1224 pixel[0] = col_conv[0];
1225 pixel[1] = col_conv[1];
1226 pixel[2] = col_conv[2];
1227 pixel[3] = 1.0f;
1228 }
1229 else {
1230 float alphatest;
1231 pixel[0] = (col_conv[0] * a) + (pixel[0] * ai);
1232 pixel[1] = (col_conv[1] * a) + (pixel[1] * ai);
1233 pixel[2] = (col_conv[2] * a) + (pixel[2] * ai);
1234 pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
1235 }
1236 }
1237 }
1238 }
1239}
1240
1242 ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, ColorManagedDisplay *display)
1243{
1244 if (!ibuf) {
1245 return;
1246 }
1248 ibuf->float_buffer.data,
1249 ibuf->x,
1250 ibuf->y,
1251 col,
1252 display,
1253 x1,
1254 y1,
1255 x2,
1256 y2);
1257}
1258
1259void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
1260{
1261 int i;
1262
1263 if (ibuf->float_buffer.data && (ibuf->channels == 4)) {
1264 float *fbuf = ibuf->float_buffer.data + 3;
1265 for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) {
1266 *fbuf = value;
1267 }
1268 }
1269
1270 if (ibuf->byte_buffer.data) {
1271 const uchar cvalue = value * 255;
1272 uchar *cbuf = ibuf->byte_buffer.data + 3;
1273 for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) {
1274 *cbuf = cvalue;
1275 }
1276 }
1277}
#define BLI_assert(a)
Definition BLI_assert.h:50
MINLINE float min_ff(float a, float b)
MINLINE int divide_round_i(int a, int b)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
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 copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
unsigned char uchar
unsigned short ushort
unsigned int uint
#define CLAMP(a, b, c)
void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], ColorManagedDisplay *display)
void IMB_processor_apply_threaded_scanlines(int total_scanlines, ScanlineThreadFunc do_thread, void *custom_data)
IMB_BlendMode
Definition IMB_imbuf.hh:186
@ IMB_BLEND_EXCLUSION
Definition IMB_imbuf.hh:206
@ IMB_BLEND_DIFFERENCE
Definition IMB_imbuf.hh:205
@ IMB_BLEND_HARDLIGHT
Definition IMB_imbuf.hh:196
@ IMB_BLEND_COLORBURN
Definition IMB_imbuf.hh:197
@ IMB_BLEND_COLORDODGE
Definition IMB_imbuf.hh:199
@ IMB_BLEND_ERASE_ALPHA
Definition IMB_imbuf.hh:193
@ IMB_BLEND_SCREEN
Definition IMB_imbuf.hh:200
@ IMB_BLEND_HUE
Definition IMB_imbuf.hh:207
@ IMB_BLEND_MUL
Definition IMB_imbuf.hh:190
@ IMB_BLEND_ADD_ALPHA
Definition IMB_imbuf.hh:194
@ IMB_BLEND_DARKEN
Definition IMB_imbuf.hh:192
@ IMB_BLEND_OVERLAY
Definition IMB_imbuf.hh:195
@ IMB_BLEND_SATURATION
Definition IMB_imbuf.hh:208
@ IMB_BLEND_VIVIDLIGHT
Definition IMB_imbuf.hh:203
@ IMB_BLEND_LUMINOSITY
Definition IMB_imbuf.hh:209
@ IMB_BLEND_LIGHTEN
Definition IMB_imbuf.hh:191
@ IMB_BLEND_SOFTLIGHT
Definition IMB_imbuf.hh:201
@ IMB_BLEND_COPY_RGB
Definition IMB_imbuf.hh:214
@ IMB_BLEND_COLOR
Definition IMB_imbuf.hh:210
@ IMB_BLEND_LINEARLIGHT
Definition IMB_imbuf.hh:204
@ IMB_BLEND_COPY_ALPHA
Definition IMB_imbuf.hh:215
@ IMB_BLEND_PINLIGHT
Definition IMB_imbuf.hh:202
@ IMB_BLEND_MIX
Definition IMB_imbuf.hh:187
@ IMB_BLEND_COPY
Definition IMB_imbuf.hh:213
@ IMB_BLEND_INTERPOLATE
Definition IMB_imbuf.hh:211
@ IMB_BLEND_ADD
Definition IMB_imbuf.hh:188
@ IMB_BLEND_SUB
Definition IMB_imbuf.hh:189
@ IMB_BLEND_LINEARBURN
Definition IMB_imbuf.hh:198
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
BLI_INLINE float fb(float length, float L)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define unit_float_to_uchar_clamp(val)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static void rect_realloc_16bytes(void **buf_p, const uint size[2])
Definition rectop.cc:278
void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
Definition rectop.cc:1259
void buf_rectfill_area(uchar *rect, float *rectf, int width, int height, const float col[4], ColorManagedDisplay *display, int x1, int y1, int x2, int y2)
Definition rectop.cc:1130
static void rect_crop_4bytes(void **buf_p, const int size_src[2], const rcti *crop)
Definition rectop.cc:206
static void rect_crop_16bytes(void **buf_p, const int size_src[2], const rcti *crop)
Definition rectop.cc:223
void IMB_rectfill_area_replace(const ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2)
Definition rectop.cc:1083
void IMB_rectfill_area(ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, ColorManagedDisplay *display)
Definition rectop.cc:1241
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:992
void IMB_rect_crop(ImBuf *ibuf, const rcti *crop)
Definition rectop.cc:240
static void rectblend_thread_do(void *data_v, int scanline)
Definition rectop.cc:969
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:494
void(*)(uchar *dst, const uchar *src1, const uchar *src2) IMB_blend_func
Definition rectop.cc:491
void IMB_rectclip(ImBuf *dbuf, const ImBuf *sbuf, int *destx, int *desty, int *srcx, int *srcy, int *width, int *height)
Definition rectop.cc:306
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:368
void IMB_blend_color_byte(uchar dst[4], const uchar src1[4], const uchar src2[4], IMB_BlendMode mode)
Definition rectop.cc:27
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Definition rectop.cc:115
void IMB_rectfill(ImBuf *drect, const float col[4])
Definition rectop.cc:1051
void(*)(float *dst, const float *src1, const float *src2) IMB_blend_func_float
Definition rectop.cc:492
void IMB_rect_size_set(ImBuf *ibuf, const uint size[2])
Definition rectop.cc:287
static void rect_realloc_4bytes(void **buf_p, const uint size[2])
Definition rectop.cc:269
void IMB_rectcpy(ImBuf *dbuf, const ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
Definition rectop.cc:463
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
const ImBuf * sbuf
Definition rectop.cc:959
IMB_BlendMode mode
Definition rectop.cc:965
const ushort * texmask
Definition rectop.cc:961
const ushort * curvemask
Definition rectop.cc:961
const ImBuf * obuf
Definition rectop.cc:959
int ymin
int ymax
int xmin
int xmax