2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
30 /** \file blender/imbuf/intern/rectop.c
36 #include "BLI_utildefines.h"
37 #include "BLI_math_base.h"
38 #include "BLI_math_color.h"
39 #include "BLI_math_color_blend.h"
40 #include "BLI_math_vector.h"
42 #include "IMB_imbuf_types.h"
43 #include "IMB_imbuf.h"
45 #include "IMB_colormanagement.h"
47 void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned char src2[4], IMB_BlendMode mode)
51 blend_color_mix_byte(dst, src1, src2); break;
53 blend_color_add_byte(dst, src1, src2); break;
55 blend_color_sub_byte(dst, src1, src2); break;
57 blend_color_mul_byte(dst, src1, src2); break;
58 case IMB_BLEND_LIGHTEN:
59 blend_color_lighten_byte(dst, src1, src2); break;
60 case IMB_BLEND_DARKEN:
61 blend_color_darken_byte(dst, src1, src2); break;
62 case IMB_BLEND_ERASE_ALPHA:
63 blend_color_erase_alpha_byte(dst, src1, src2); break;
64 case IMB_BLEND_ADD_ALPHA:
65 blend_color_add_alpha_byte(dst, src1, src2); break;
66 case IMB_BLEND_OVERLAY:
67 blend_color_overlay_byte(dst, src1, src2); break;
68 case IMB_BLEND_HARDLIGHT:
69 blend_color_hardlight_byte(dst, src1, src2); break;
70 case IMB_BLEND_COLORBURN:
71 blend_color_burn_byte(dst, src1, src2); break;
72 case IMB_BLEND_LINEARBURN:
73 blend_color_linearburn_byte(dst, src1, src2); break;
74 case IMB_BLEND_COLORDODGE:
75 blend_color_dodge_byte(dst, src1, src2); break;
76 case IMB_BLEND_SCREEN:
77 blend_color_screen_byte(dst, src1, src2); break;
78 case IMB_BLEND_SOFTLIGHT:
79 blend_color_softlight_byte(dst, src1, src2); break;
80 case IMB_BLEND_PINLIGHT:
81 blend_color_pinlight_byte(dst, src1, src2); break;
82 case IMB_BLEND_LINEARLIGHT:
83 blend_color_linearlight_byte(dst, src1, src2); break;
84 case IMB_BLEND_VIVIDLIGHT:
85 blend_color_vividlight_byte(dst, src1, src2); break;
86 case IMB_BLEND_DIFFERENCE:
87 blend_color_difference_byte(dst, src1, src2); break;
88 case IMB_BLEND_EXCLUSION:
89 blend_color_exclusion_byte(dst, src1, src2); break;
91 blend_color_color_byte(dst, src1, src2); break;
93 blend_color_hue_byte(dst, src1, src2); break;
94 case IMB_BLEND_SATURATION:
95 blend_color_saturation_byte(dst, src1, src2); break;
96 case IMB_BLEND_LUMINOSITY:
97 blend_color_luminosity_byte(dst, src1, src2); break;
108 void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_BlendMode mode)
112 blend_color_mix_float(dst, src1, src2); break;
114 blend_color_add_float(dst, src1, src2); break;
116 blend_color_sub_float(dst, src1, src2); break;
118 blend_color_mul_float(dst, src1, src2); break;
119 case IMB_BLEND_LIGHTEN:
120 blend_color_lighten_float(dst, src1, src2); break;
121 case IMB_BLEND_DARKEN:
122 blend_color_darken_float(dst, src1, src2); break;
123 case IMB_BLEND_ERASE_ALPHA:
124 blend_color_erase_alpha_float(dst, src1, src2); break;
125 case IMB_BLEND_ADD_ALPHA:
126 blend_color_add_alpha_float(dst, src1, src2); break;
127 case IMB_BLEND_OVERLAY:
128 blend_color_overlay_float(dst, src1, src2); break;
129 case IMB_BLEND_HARDLIGHT:
130 blend_color_hardlight_float(dst, src1, src2); break;
131 case IMB_BLEND_COLORBURN:
132 blend_color_burn_float(dst, src1, src2); break;
133 case IMB_BLEND_LINEARBURN:
134 blend_color_linearburn_float(dst, src1, src2); break;
135 case IMB_BLEND_COLORDODGE:
136 blend_color_dodge_float(dst, src1, src2); break;
137 case IMB_BLEND_SCREEN:
138 blend_color_screen_float(dst, src1, src2); break;
139 case IMB_BLEND_SOFTLIGHT:
140 blend_color_softlight_float(dst, src1, src2); break;
141 case IMB_BLEND_PINLIGHT:
142 blend_color_pinlight_float(dst, src1, src2); break;
143 case IMB_BLEND_LINEARLIGHT:
144 blend_color_linearlight_float(dst, src1, src2); break;
145 case IMB_BLEND_VIVIDLIGHT:
146 blend_color_vividlight_float(dst, src1, src2); break;
147 case IMB_BLEND_DIFFERENCE:
148 blend_color_difference_float(dst, src1, src2); break;
149 case IMB_BLEND_EXCLUSION:
150 blend_color_exclusion_float(dst, src1, src2); break;
151 case IMB_BLEND_COLOR:
152 blend_color_color_float(dst, src1, src2); break;
154 blend_color_hue_float(dst, src1, src2); break;
155 case IMB_BLEND_SATURATION:
156 blend_color_saturation_float(dst, src1, src2); break;
157 case IMB_BLEND_LUMINOSITY:
158 blend_color_luminosity_float(dst, src1, src2); break;
170 void IMB_rectclip(ImBuf *dbuf, ImBuf *sbuf, int *destx,
171 int *desty, int *srcx, int *srcy, int *width, int *height)
175 if (dbuf == NULL) return;
198 tmp = dbuf->x - *destx;
199 if (*width > tmp) *width = tmp;
200 tmp = dbuf->y - *desty;
201 if (*height > tmp) *height = tmp;
204 tmp = sbuf->x - *srcx;
205 if (*width > tmp) *width = tmp;
206 tmp = sbuf->y - *srcy;
207 if (*height > tmp) *height = tmp;
210 if ((*height <= 0) || (*width <= 0)) {
216 static void imb_rectclip3(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, int *destx,
217 int *desty, int *origx, int *origy, int *srcx, int *srcy,
218 int *width, int *height)
222 if (dbuf == NULL) return;
262 tmp = dbuf->x - *destx;
263 if (*width > tmp) *width = tmp;
264 tmp = dbuf->y - *desty;
265 if (*height > tmp) *height = tmp;
268 tmp = obuf->x - *origx;
269 if (*width > tmp) *width = tmp;
270 tmp = obuf->y - *origy;
271 if (*height > tmp) *height = tmp;
275 tmp = sbuf->x - *srcx;
276 if (*width > tmp) *width = tmp;
277 tmp = sbuf->y - *srcy;
278 if (*height > tmp) *height = tmp;
281 if ((*height <= 0) || (*width <= 0)) {
289 void IMB_rectcpy(ImBuf *dbuf, ImBuf *sbuf, int destx,
290 int desty, int srcx, int srcy, int width, int height)
292 IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY, false);
295 typedef void (*IMB_blend_func)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2);
296 typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
299 void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask, unsigned short *curvemask,
300 unsigned short *texmask, float mask_max,
301 int destx, int desty, int origx, int origy, int srcx, int srcy, int width, int height,
302 IMB_BlendMode mode, bool accumulate)
304 unsigned int *drect = NULL, *orect, *srect = NULL, *dr, *or, *sr;
305 float *drectf = NULL, *orectf, *srectf = NULL, *drf, *orf, *srf;
306 unsigned short *cmaskrect = curvemask, *cmr;
307 unsigned short *dmaskrect = dmask, *dmr;
308 unsigned short *texmaskrect = texmask, *tmr;
309 int do_float, do_char, srcskip, destskip, origskip, x;
310 IMB_blend_func func = NULL;
311 IMB_blend_func_float func_float = NULL;
313 if (dbuf == NULL || obuf == NULL) return;
315 imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height);
317 if (width == 0 || height == 0) return;
318 if (sbuf && sbuf->channels != 4) return;
319 if (dbuf->channels != 4) return;
321 do_char = (sbuf && sbuf->rect && dbuf->rect && obuf->rect);
322 do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float);
325 drect = dbuf->rect + desty * dbuf->x + destx;
326 orect = obuf->rect + origy * obuf->x + origx;
329 drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4;
330 orectf = obuf->rect_float + (origy * obuf->x + origx) * 4;
334 dmaskrect += origy * obuf->x + origx;
340 if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
341 if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
345 cmaskrect += srcy * sbuf->x + srcx;
348 texmaskrect += srcy * sbuf->x + srcx;
356 if (mode == IMB_BLEND_COPY) {
358 for (; height > 0; height--) {
360 memcpy(drect, srect, width * sizeof(int));
366 memcpy(drectf, srectf, width * sizeof(float) * 4);
367 drectf += destskip * 4;
368 srectf += srcskip * 4;
372 else if (mode == IMB_BLEND_COPY_RGB) {
374 for (; height > 0; height--) {
378 for (x = width; x > 0; x--, dr++, sr++) {
379 ((char *)dr)[0] = ((char *)sr)[0];
380 ((char *)dr)[1] = ((char *)sr)[1];
381 ((char *)dr)[2] = ((char *)sr)[2];
390 for (x = width; x > 0; x--, drf += 4, srf += 4) {
391 float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3];
393 drf[0] = srf[0] * map_alpha;
394 drf[1] = srf[1] * map_alpha;
395 drf[2] = srf[2] * map_alpha;
397 drectf += destskip * 4;
398 srectf += srcskip * 4;
402 else if (mode == IMB_BLEND_COPY_ALPHA) {
403 /* copy alpha only */
404 for (; height > 0; height--) {
408 for (x = width; x > 0; x--, dr++, sr++)
409 ((char *)dr)[3] = ((char *)sr)[3];
417 for (x = width; x > 0; x--, drf += 4, srf += 4)
419 drectf += destskip * 4;
420 srectf += srcskip * 4;
427 func = blend_color_mix_byte;
428 func_float = blend_color_mix_float;
431 func = blend_color_add_byte;
432 func_float = blend_color_add_float;
435 func = blend_color_sub_byte;
436 func_float = blend_color_sub_float;
439 func = blend_color_mul_byte;
440 func_float = blend_color_mul_float;
442 case IMB_BLEND_LIGHTEN:
443 func = blend_color_lighten_byte;
444 func_float = blend_color_lighten_float;
446 case IMB_BLEND_DARKEN:
447 func = blend_color_darken_byte;
448 func_float = blend_color_darken_float;
450 case IMB_BLEND_ERASE_ALPHA:
451 func = blend_color_erase_alpha_byte;
452 func_float = blend_color_erase_alpha_float;
454 case IMB_BLEND_ADD_ALPHA:
455 func = blend_color_add_alpha_byte;
456 func_float = blend_color_add_alpha_float;
458 case IMB_BLEND_OVERLAY:
459 func = blend_color_overlay_byte;
460 func_float = blend_color_overlay_float;
462 case IMB_BLEND_HARDLIGHT:
463 func = blend_color_hardlight_byte;
464 func_float = blend_color_hardlight_float;
466 case IMB_BLEND_COLORBURN:
467 func = blend_color_burn_byte;
468 func_float = blend_color_burn_float;
470 case IMB_BLEND_LINEARBURN:
471 func = blend_color_linearburn_byte;
472 func_float = blend_color_linearburn_float;
474 case IMB_BLEND_COLORDODGE:
475 func = blend_color_dodge_byte;
476 func_float = blend_color_dodge_float;
478 case IMB_BLEND_SCREEN:
479 func = blend_color_screen_byte;
480 func_float = blend_color_screen_float;
482 case IMB_BLEND_SOFTLIGHT:
483 func = blend_color_softlight_byte;
484 func_float = blend_color_softlight_float;
486 case IMB_BLEND_PINLIGHT:
487 func = blend_color_pinlight_byte;
488 func_float = blend_color_pinlight_float;
490 case IMB_BLEND_LINEARLIGHT:
491 func = blend_color_linearlight_byte;
492 func_float = blend_color_linearlight_float;
494 case IMB_BLEND_VIVIDLIGHT:
495 func = blend_color_vividlight_byte;
496 func_float = blend_color_vividlight_float;
498 case IMB_BLEND_DIFFERENCE:
499 func = blend_color_difference_byte;
500 func_float = blend_color_difference_float;
502 case IMB_BLEND_EXCLUSION:
503 func = blend_color_exclusion_byte;
504 func_float = blend_color_exclusion_float;
506 case IMB_BLEND_COLOR:
507 func = blend_color_color_byte;
508 func_float = blend_color_color_float;
511 func = blend_color_hue_byte;
512 func_float = blend_color_hue_float;
514 case IMB_BLEND_SATURATION:
515 func = blend_color_saturation_byte;
516 func_float = blend_color_saturation_float;
518 case IMB_BLEND_LUMINOSITY:
519 func = blend_color_luminosity_byte;
520 func_float = blend_color_luminosity_float;
527 for (; height > 0; height--) {
534 /* mask accumulation for painting */
538 /* destination mask present, do max alpha masking */
541 for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, cmr++) {
542 unsigned char *src = (unsigned char *)sr;
543 float mask_lim = mask_max * (*cmr);
546 mask_lim *= ((*tmr++) / 65535.0f);
548 if (src[3] && mask_lim) {
552 mask = *dmr + mask_lim;
554 mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
556 mask = min_ff(mask, 65535.0);
559 unsigned char mask_src[4];
563 mask_src[0] = src[0];
564 mask_src[1] = src[1];
565 mask_src[2] = src[2];
566 mask_src[3] = divide_round_i(src[3] * mask, 65535);
568 func((unsigned char *)dr, (unsigned char *)or, mask_src);
572 dmaskrect += origskip;
574 /* no destination mask buffer, do regular blend with masktexture if present */
576 for (x = width; x > 0; x--, dr++, or++, sr++, cmr++) {
577 unsigned char *src = (unsigned char *)sr;
578 float mask = (float)mask_max * ((float)(*cmr));
581 mask *= ((float)(*tmr++) / 65535.0f);
583 mask = min_ff(mask, 65535.0);
585 if (src[3] && (mask > 0.0f)) {
586 unsigned char mask_src[4];
588 mask_src[0] = src[0];
589 mask_src[1] = src[1];
590 mask_src[2] = src[2];
591 mask_src[3] = divide_round_i(src[3] * mask, 65535);
593 func((unsigned char *)dr, (unsigned char *)or, mask_src);
598 cmaskrect += srcskip;
600 texmaskrect += srcskip;
603 /* regular blending */
604 for (x = width; x > 0; x--, dr++, or++, sr++) {
605 if (((unsigned char *)sr)[3])
606 func((unsigned char *)dr, (unsigned char *)or, (unsigned char *)sr);
621 /* mask accumulation for painting */
625 /* destination mask present, do max alpha masking */
628 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
629 float mask_lim = mask_max * (*cmr);
632 mask_lim *= ((*tmr++) / 65535.0f);
634 if (srf[3] && mask_lim) {
638 mask = min_ff(*dmr + mask_lim, 65535.0);
640 mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
642 mask = min_ff(mask, 65535.0);
648 mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
650 func_float(drf, orf, mask_srf);
654 dmaskrect += origskip;
656 /* no destination mask buffer, do regular blend with masktexture if present */
658 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
659 float mask = (float)mask_max * ((float)(*cmr));
662 mask *= ((float)(*tmr++) / 65535.0f);
664 mask = min_ff(mask, 65535.0);
666 if (srf[3] && (mask > 0.0f)) {
669 mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
671 func_float(drf, orf, mask_srf);
676 cmaskrect += srcskip;
678 texmaskrect += srcskip;
681 /* regular blending */
682 for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) {
684 func_float(drf, orf, srf);
688 drectf += destskip * 4;
689 orectf += origskip * 4;
690 srectf += srcskip * 4;
698 void IMB_rectfill(ImBuf *drect, const float col[4])
703 unsigned int *rrect = drect->rect;
706 ccol[0] = (int)(col[0] * 255);
707 ccol[1] = (int)(col[1] * 255);
708 ccol[2] = (int)(col[2] * 255);
709 ccol[3] = (int)(col[3] * 255);
711 num = drect->x * drect->y;
712 for (; num > 0; num--)
713 *rrect++ = *((unsigned int *)ccol);
716 if (drect->rect_float) {
717 float *rrectf = drect->rect_float;
719 num = drect->x * drect->y;
720 for (; num > 0; num--) {
730 void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
731 const float col[4], struct ColorManagedDisplay *display,
732 int x1, int y1, int x2, int y2)
736 float ai; /* alpha inverted */
737 float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
738 if ((!rect && !rectf) || (!col) || col[3] == 0.0f)
741 /* sanity checks for coords */
744 CLAMP(y1, 0, height);
745 CLAMP(y2, 0, height);
747 if (x1 > x2) SWAP(int, x1, x2);
748 if (y1 > y2) SWAP(int, y1, y2);
749 if (x1 == x2 || y1 == y2) return;
756 unsigned char *pixel;
757 unsigned char chr = 0, chg = 0, chb = 0;
758 float fr = 0, fg = 0, fb = 0;
760 const int alphaint = FTOCHAR(a);
763 chr = FTOCHAR(col[0]);
764 chg = FTOCHAR(col[1]);
765 chb = FTOCHAR(col[2]);
772 for (j = 0; j < y2 - y1; j++) {
773 for (i = 0; i < x2 - x1; i++) {
774 pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
775 if (pixel >= rect && pixel < rect + (4 * (width * height))) {
784 pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f);
785 pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f);
786 pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f);
787 pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255);
799 copy_v4_v4(col_conv, col);
800 IMB_colormanagement_display_to_scene_linear_v3(col_conv, display);
803 srgb_to_linearrgb_v4(col_conv, col);
806 for (j = 0; j < y2 - y1; j++) {
807 for (i = 0; i < x2 - x1; i++) {
808 pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
810 pixel[0] = col_conv[0];
811 pixel[1] = col_conv[1];
812 pixel[2] = col_conv[2];
817 pixel[0] = (col_conv[0] * a) + (pixel[0] * ai);
818 pixel[1] = (col_conv[1] * a) + (pixel[1] * ai);
819 pixel[2] = (col_conv[2] * a) + (pixel[2] * ai);
820 pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
827 void IMB_rectfill_area(ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display)
830 buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display,
835 void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
839 if (ibuf->rect_float && (ibuf->channels == 4)) {
840 float *fbuf = ibuf->rect_float + 3;
841 for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) { *fbuf = value; }
845 const unsigned char cvalue = value * 255;
846 unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3;
847 for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) { *cbuf = cvalue; }