Fix msvc 2013 compiler errors after the ingenious cleanup in 4ca67869cc7a.
[blender.git] / source / blender / imbuf / intern / rectop.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * allocimbuf.c
27  *
28  */
29
30 /** \file blender/imbuf/intern/rectop.c
31  *  \ingroup imbuf
32  */
33
34 #include <stdlib.h>
35
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"
41
42 #include "imbuf.h"
43 #include "IMB_imbuf_types.h"
44 #include "IMB_imbuf.h"
45
46 #include "IMB_allocimbuf.h"
47 #include "IMB_colormanagement.h"
48
49 void IMB_blend_color_byte(unsigned char dst[4], unsigned char src1[4], unsigned char src2[4], IMB_BlendMode mode)
50 {
51         switch (mode) {
52                 case IMB_BLEND_MIX:
53                         blend_color_mix_byte(dst, src1, src2); break;
54                 case IMB_BLEND_ADD:
55                         blend_color_add_byte(dst, src1, src2); break;
56                 case IMB_BLEND_SUB:
57                         blend_color_sub_byte(dst, src1, src2); break;
58                 case IMB_BLEND_MUL:
59                         blend_color_mul_byte(dst, src1, src2); break;
60                 case IMB_BLEND_LIGHTEN:
61                         blend_color_lighten_byte(dst, src1, src2); break;
62                 case IMB_BLEND_DARKEN:
63                         blend_color_darken_byte(dst, src1, src2); break;
64                 case IMB_BLEND_ERASE_ALPHA:
65                         blend_color_erase_alpha_byte(dst, src1, src2); break;
66                 case IMB_BLEND_ADD_ALPHA:
67                         blend_color_add_alpha_byte(dst, src1, src2); break;
68                 default:
69                         dst[0] = src1[0];
70                         dst[1] = src1[1];
71                         dst[2] = src1[2];
72                         dst[3] = src1[3];
73                         break;
74         }
75 }
76
77 void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_BlendMode mode)
78 {
79         switch (mode) {
80                 case IMB_BLEND_MIX:
81                         blend_color_mix_float(dst, src1, src2); break;
82                 case IMB_BLEND_ADD:
83                         blend_color_add_float(dst, src1, src2); break;
84                 case IMB_BLEND_SUB:
85                         blend_color_sub_float(dst, src1, src2); break;
86                 case IMB_BLEND_MUL:
87                         blend_color_mul_float(dst, src1, src2); break;
88                 case IMB_BLEND_LIGHTEN:
89                         blend_color_lighten_float(dst, src1, src2); break;
90                 case IMB_BLEND_DARKEN:
91                         blend_color_darken_float(dst, src1, src2); break;
92                 case IMB_BLEND_ERASE_ALPHA:
93                         blend_color_erase_alpha_float(dst, src1, src2); break;
94                 case IMB_BLEND_ADD_ALPHA:
95                         blend_color_add_alpha_float(dst, src1, src2); break;
96                 default:
97                         dst[0] = src1[0];
98                         dst[1] = src1[1];
99                         dst[2] = src1[2];
100                         dst[3] = src1[3];
101                         break;
102         }
103 }
104
105 /* clipping */
106
107 void IMB_rectclip(ImBuf *dbuf, ImBuf *sbuf, int *destx, 
108                   int *desty, int *srcx, int *srcy, int *width, int *height)
109 {
110         int tmp;
111
112         if (dbuf == NULL) return;
113         
114         if (*destx < 0) {
115                 *srcx -= *destx;
116                 *width += *destx;
117                 *destx = 0;
118         }
119         if (*srcx < 0) {
120                 *destx -= *srcx;
121                 *width += *srcx;
122                 *srcx = 0;
123         }
124         if (*desty < 0) {
125                 *srcy -= *desty;
126                 *height += *desty;
127                 *desty = 0;
128         }
129         if (*srcy < 0) {
130                 *desty -= *srcy;
131                 *height += *srcy;
132                 *srcy = 0;
133         }
134
135         tmp = dbuf->x - *destx;
136         if (*width > tmp) *width = tmp;
137         tmp = dbuf->y - *desty;
138         if (*height > tmp) *height = tmp;
139
140         if (sbuf) {
141                 tmp = sbuf->x - *srcx;
142                 if (*width > tmp) *width = tmp;
143                 tmp = sbuf->y - *srcy;
144                 if (*height > tmp) *height = tmp;
145         }
146
147         if ((*height <= 0) || (*width <= 0)) {
148                 *width = 0;
149                 *height = 0;
150         }
151 }
152
153 static void imb_rectclip3(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, int *destx, 
154                           int *desty, int *origx, int *origy, int *srcx, int *srcy,
155                           int *width, int *height)
156 {
157         int tmp;
158
159         if (dbuf == NULL) return;
160         
161         if (*destx < 0) {
162                 *srcx -= *destx;
163                 *origx -= *destx;
164                 *width += *destx;
165                 *destx = 0;
166         }
167         if (*origx < 0) {
168                 *destx -= *origx;
169                 *srcx -= *origx;
170                 *width += *origx;
171                 *origx = 0;
172         }
173         if (*srcx < 0) {
174                 *destx -= *srcx;
175                 *origx -= *srcx;
176                 *width += *srcx;
177                 *srcx = 0;
178         }
179
180         if (*desty < 0) {
181                 *srcy -= *desty;
182                 *origy -= *desty;
183                 *height += *desty;
184                 *desty = 0;
185         }
186         if (*origy < 0) {
187                 *desty -= *origy;
188                 *srcy -= *origy;
189                 *height += *origy;
190                 *origy = 0;
191         }
192         if (*srcy < 0) {
193                 *desty -= *srcy;
194                 *origy -= *srcy;
195                 *height += *srcy;
196                 *srcy = 0;
197         }
198
199         tmp = dbuf->x - *destx;
200         if (*width > tmp) *width = tmp;
201         tmp = dbuf->y - *desty;
202         if (*height > tmp) *height = tmp;
203
204         if (obuf) {
205                 tmp = obuf->x - *origx;
206                 if (*width > tmp) *width = tmp;
207                 tmp = obuf->y - *origy;
208                 if (*height > tmp) *height = tmp;
209         }
210
211         if (sbuf) {
212                 tmp = sbuf->x - *srcx;
213                 if (*width > tmp) *width = tmp;
214                 tmp = sbuf->y - *srcy;
215                 if (*height > tmp) *height = tmp;
216         }
217
218         if ((*height <= 0) || (*width <= 0)) {
219                 *width = 0;
220                 *height = 0;
221         }
222 }
223
224 /* copy and blend */
225
226 void IMB_rectcpy(ImBuf *dbuf, ImBuf *sbuf, int destx, 
227                  int desty, int srcx, int srcy, int width, int height)
228 {
229         IMB_rectblend(dbuf, dbuf, sbuf, NULL, NULL, 0, destx, desty, destx, desty, srcx, srcy, width, height, IMB_BLEND_COPY);
230 }
231
232 typedef void (*IMB_blend_func)(unsigned char *dst, const unsigned char *src1, const unsigned char *src2);
233 typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
234
235
236 void IMB_rectblend(ImBuf *dbuf, ImBuf *obuf, ImBuf *sbuf, unsigned short *dmask,
237                    unsigned short *smask, unsigned short mask_max,
238                    int destx,  int desty, int origx, int origy, int srcx, int srcy, int width, int height,
239                    IMB_BlendMode mode)
240 {
241         unsigned int *drect = NULL, *orect, *srect = NULL, *dr, *or, *sr;
242         float *drectf = NULL, *orectf, *srectf = NULL, *drf, *orf, *srf;
243         unsigned short *smaskrect = smask, *smr;
244         unsigned short *dmaskrect = dmask, *dmr;
245         int do_float, do_char, srcskip, destskip, origskip, x;
246         IMB_blend_func func = NULL;
247         IMB_blend_func_float func_float = NULL;
248
249         if (dbuf == NULL || obuf == NULL) return;
250
251         imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height);
252
253         if (width == 0 || height == 0) return;
254         if (sbuf && sbuf->channels != 4) return;
255         if (dbuf->channels != 4) return;
256
257         do_char = (sbuf && sbuf->rect && dbuf->rect && obuf->rect);
258         do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float);
259
260         if (do_char) {
261                 drect = dbuf->rect + desty * dbuf->x + destx;
262                 orect = obuf->rect + origy * obuf->x + origx;
263         }
264         if (do_float) {
265                 drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4;
266                 orectf = obuf->rect_float + (origy * obuf->x + origx) * 4;
267         }
268
269         if (dmaskrect)
270                 dmaskrect += origy * obuf->x + origx;
271
272         destskip = dbuf->x;
273         origskip = obuf->x;
274
275         if (sbuf) {
276                 if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
277                 if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
278                 srcskip = sbuf->x;
279
280                 if (smaskrect)
281                         smaskrect += srcy * sbuf->x + srcx;
282         }
283         else {
284                 srect = drect;
285                 srectf = drectf;
286                 srcskip = destskip;
287         }
288
289         if (mode == IMB_BLEND_COPY) {
290                 /* copy */
291                 for (; height > 0; height--) {
292                         if (do_char) {
293                                 memcpy(drect, srect, width * sizeof(int));
294                                 drect += destskip;
295                                 srect += srcskip;
296                         }
297
298                         if (do_float) {
299                                 memcpy(drectf, srectf, width * sizeof(float) * 4);
300                                 drectf += destskip * 4;
301                                 srectf += srcskip * 4;
302                         }
303                 }
304         }
305         else if (mode == IMB_BLEND_COPY_RGB) {
306                 /* copy rgb only */
307                 for (; height > 0; height--) {
308                         if (do_char) {
309                                 dr = drect;
310                                 sr = srect;
311                                 for (x = width; x > 0; x--, dr++, sr++) {
312                                         ((char *)dr)[0] = ((char *)sr)[0];
313                                         ((char *)dr)[1] = ((char *)sr)[1];
314                                         ((char *)dr)[2] = ((char *)sr)[2];
315                                 }
316                                 drect += destskip;
317                                 srect += srcskip;
318                         }
319
320                         if (do_float) {
321                                 drf = drectf;
322                                 srf = srectf;
323                                 for (x = width; x > 0; x--, drf += 4, srf += 4) {
324                                         float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3];
325
326                                         drf[0] = srf[0] * map_alpha;
327                                         drf[1] = srf[1] * map_alpha;
328                                         drf[2] = srf[2] * map_alpha;
329                                 }
330                                 drectf += destskip * 4;
331                                 srectf += srcskip * 4;
332                         }
333                 }
334         }
335         else if (mode == IMB_BLEND_COPY_ALPHA) {
336                 /* copy alpha only */
337                 for (; height > 0; height--) {
338                         if (do_char) {
339                                 dr = drect;
340                                 sr = srect;
341                                 for (x = width; x > 0; x--, dr++, sr++)
342                                         ((char *)dr)[3] = ((char *)sr)[3];
343                                 drect += destskip;
344                                 srect += srcskip;
345                         }
346
347                         if (do_float) {
348                                 drf = drectf;
349                                 srf = srectf;
350                                 for (x = width; x > 0; x--, drf += 4, srf += 4)
351                                         drf[3] = srf[3];
352                                 drectf += destskip * 4;
353                                 srectf += srcskip * 4;
354                         }
355                 }
356         }
357         else {
358                 switch (mode) {
359                         case IMB_BLEND_MIX:
360                                 func = blend_color_mix_byte;
361                                 func_float = blend_color_mix_float;
362                                 break;
363                         case IMB_BLEND_ADD:
364                                 func = blend_color_add_byte;
365                                 func_float = blend_color_add_float;
366                                 break;
367                         case IMB_BLEND_SUB:
368                                 func = blend_color_sub_byte;
369                                 func_float = blend_color_sub_float;
370                                 break;
371                         case IMB_BLEND_MUL:
372                                 func = blend_color_mul_byte;
373                                 func_float = blend_color_mul_float;
374                                 break;
375                         case IMB_BLEND_LIGHTEN:
376                                 func = blend_color_lighten_byte;
377                                 func_float = blend_color_lighten_float;
378                                 break;
379                         case IMB_BLEND_DARKEN:
380                                 func = blend_color_darken_byte;
381                                 func_float = blend_color_darken_float;
382                                 break;
383                         case IMB_BLEND_ERASE_ALPHA:
384                                 func = blend_color_erase_alpha_byte;
385                                 func_float = blend_color_erase_alpha_float;
386                                 break;
387                         case IMB_BLEND_ADD_ALPHA:
388                                 func = blend_color_add_alpha_byte;
389                                 func_float = blend_color_add_alpha_float;
390                                 break;
391                         default:
392                                 break;
393                 }
394
395                 /* blend */
396                 for (; height > 0; height--) {
397                         if (do_char) {
398                                 dr = drect;
399                                 or = orect;
400                                 sr = srect;
401
402                                 if (dmaskrect && smaskrect) {
403                                         /* mask accumulation for painting */
404                                         dmr = dmaskrect;
405                                         smr = smaskrect;
406
407                                         for (x = width; x > 0; x--, dr++, or++, sr++, dmr++, smr++) {
408                                                 unsigned char *src = (unsigned char *)sr;
409
410                                                 if (src[3] && *smr) {
411                                                         unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
412
413                                                         if (mask > *dmr) {
414                                                                 unsigned char mask_src[4];
415
416                                                                 *dmr = mask;
417
418                                                                 mask_src[0] = src[0];
419                                                                 mask_src[1] = src[1];
420                                                                 mask_src[2] = src[2];
421                                                                 mask_src[3] = divide_round_i(src[3] * mask, 65535);
422
423                                                                 func((unsigned char *)dr, (unsigned char *)or, mask_src);
424                                                         }
425                                                 }
426                                         }
427
428                                         dmaskrect += origskip;
429                                         smaskrect += srcskip;
430                                 }
431                                 else {
432                                         /* regular blending */
433                                         for (x = width; x > 0; x--, dr++, or++, sr++) {
434                                                 if (((unsigned char *)sr)[3])
435                                                         func((unsigned char *)dr, (unsigned char *)or, (unsigned char *)sr);
436                                         }
437                                 }
438
439                                 drect += destskip;
440                                 orect += origskip;
441                                 srect += srcskip;
442                         }
443
444                         if (do_float) {
445                                 drf = drectf;
446                                 orf = orectf;
447                                 srf = srectf;
448
449                                 if (dmaskrect && smaskrect) {
450                                         /* mask accumulation for painting */
451                                         dmr = dmaskrect;
452                                         smr = smaskrect;
453
454                                         for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, smr++) {
455                                                 if (srf[3] != 0 && *smr) {
456                                                         unsigned short mask = *dmr + (((mask_max - *dmr) * (*smr)) / 65535);
457
458                                                         if (mask > *dmr) {
459                                                                 float mask_srf[4];
460
461                                                                 *dmr = mask;
462                                                                 mul_v4_v4fl(mask_srf, srf, mask * (1.0f / 65535.0f));
463
464                                                                 func_float(drf, orf, mask_srf);
465                                                         }
466                                                 }
467                                         }
468
469                                         dmaskrect += origskip;
470                                         smaskrect += srcskip;
471                                 }
472                                 else {
473                                         /* regular blending */
474                                         for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) {
475                                                 if (srf[3] != 0)
476                                                         func_float(drf, orf, srf);
477                                         }
478                                 }
479
480                                 drectf += destskip * 4;
481                                 orectf += origskip * 4;
482                                 srectf += srcskip * 4;
483                         }
484                 }
485         }
486 }
487
488 /* fill */
489
490 void IMB_rectfill(ImBuf *drect, const float col[4])
491 {
492         int num;
493
494         if (drect->rect) {
495                 unsigned int *rrect = drect->rect;
496                 char ccol[4];
497                 
498                 ccol[0] = (int)(col[0] * 255);
499                 ccol[1] = (int)(col[1] * 255);
500                 ccol[2] = (int)(col[2] * 255);
501                 ccol[3] = (int)(col[3] * 255);
502                 
503                 num = drect->x * drect->y;
504                 for (; num > 0; num--)
505                         *rrect++ = *((unsigned int *)ccol);
506         }
507         
508         if (drect->rect_float) {
509                 float *rrectf = drect->rect_float;
510                 
511                 num = drect->x * drect->y;
512                 for (; num > 0; num--) {
513                         *rrectf++ = col[0];
514                         *rrectf++ = col[1];
515                         *rrectf++ = col[2];
516                         *rrectf++ = col[3];
517                 }
518         }
519 }
520
521
522 void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height,
523                        const float col[4], struct ColorManagedDisplay *display,
524                        int x1, int y1, int x2, int y2)
525 {
526         int i, j;
527         float a; /* alpha */
528         float ai; /* alpha inverted */
529         float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
530         if ((!rect && !rectf) || (!col) || col[3] == 0.0f)
531                 return;
532         
533         /* sanity checks for coords */
534         CLAMP(x1, 0, width);
535         CLAMP(x2, 0, width);
536         CLAMP(y1, 0, height);
537         CLAMP(y2, 0, height);
538
539         if (x1 > x2) SWAP(int, x1, x2);
540         if (y1 > y2) SWAP(int, y1, y2);
541         if (x1 == x2 || y1 == y2) return;
542         
543         a = col[3];
544         ai = 1 - a;
545         aich = ai / 255.0f;
546
547         if (rect) {
548                 unsigned char *pixel; 
549                 unsigned char chr = 0, chg = 0, chb = 0;
550                 float fr = 0, fg = 0, fb = 0;
551
552                 const int alphaint = FTOCHAR(a);
553                 
554                 if (a == 1.0f) {
555                         chr = FTOCHAR(col[0]);
556                         chg = FTOCHAR(col[1]);
557                         chb = FTOCHAR(col[2]);
558                 }
559                 else {
560                         fr = col[0] * a;
561                         fg = col[1] * a;
562                         fb = col[2] * a;
563                 }
564                 for (j = 0; j < y2 - y1; j++) {
565                         for (i = 0; i < x2 - x1; i++) {
566                                 pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
567                                 if (pixel >= rect && pixel < rect + (4 * (width * height))) {
568                                         if (a == 1.0f) {
569                                                 pixel[0] = chr;
570                                                 pixel[1] = chg;
571                                                 pixel[2] = chb;
572                                                 pixel[3] = 255;
573                                         }
574                                         else {
575                                                 int alphatest;
576                                                 pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f);
577                                                 pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f);
578                                                 pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f);
579                                                 pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255);
580                                         }
581                                 }
582                         }
583                 }
584         }
585         
586         if (rectf) {
587                 float col_conv[4];
588                 float *pixel;
589
590                 if (display) {
591                         copy_v4_v4(col_conv, col);
592                         IMB_colormanagement_display_to_scene_linear_v3(col_conv, display);
593                 }
594                 else {
595                         srgb_to_linearrgb_v4(col_conv, col);
596                 }
597
598                 for (j = 0; j < y2 - y1; j++) {
599                         for (i = 0; i < x2 - x1; i++) {
600                                 pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
601                                 if (a == 1.0f) {
602                                         pixel[0] = col_conv[0];
603                                         pixel[1] = col_conv[1];
604                                         pixel[2] = col_conv[2];
605                                         pixel[3] = 1.0f;
606                                 }
607                                 else {
608                                         float alphatest;
609                                         pixel[0] = (col_conv[0] * a) + (pixel[0] * ai);
610                                         pixel[1] = (col_conv[1] * a) + (pixel[1] * ai);
611                                         pixel[2] = (col_conv[2] * a) + (pixel[2] * ai);
612                                         pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
613                                 }
614                         }
615                 }
616         }
617 }
618
619 void IMB_rectfill_area(ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, struct ColorManagedDisplay *display)
620 {
621         if (!ibuf) return;
622         buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display,
623                           x1, y1, x2, y2);
624 }
625
626
627 void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
628 {
629         int i;
630
631         if (ibuf->rect_float && (ibuf->channels == 4)) {
632                 float *fbuf = ibuf->rect_float + 3;
633                 for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) { *fbuf = value; }
634         }
635
636         if (ibuf->rect) {
637                 const unsigned char cvalue = value * 255;
638                 unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3;
639                 for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) { *cbuf = cvalue; }
640         }
641 }