style cleanup
[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
35 #include "BLI_blenlib.h"
36 #include "BLI_utildefines.h"
37
38 #include "imbuf.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41
42 #include "IMB_allocimbuf.h"
43
44
45 /* blend modes */
46
47 static void blend_color_mix(char *cp, char *cp1, char *cp2, int fac)
48 {
49         /* this and other blending modes previously used >>8 instead of /255. both
50          * are not equivalent (>>8 is /256), and the former results in rounding
51          * errors that can turn colors black fast after repeated blending */
52         int mfac = 255 - fac;
53
54         cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255;
55         cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255;
56         cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255;
57 }
58
59 static void blend_color_add(char *cp, char *cp1, char *cp2, int fac)
60 {
61         int temp;
62
63         temp = cp1[0] + ((fac * cp2[0]) / 255);
64         if (temp > 254) cp[0] = 255; else cp[0] = temp;
65         temp = cp1[1] + ((fac * cp2[1]) / 255);
66         if (temp > 254) cp[1] = 255; else cp[1] = temp;
67         temp = cp1[2] + ((fac * cp2[2]) / 255);
68         if (temp > 254) cp[2] = 255; else cp[2] = temp;
69 }
70
71 static void blend_color_sub(char *cp, char *cp1, char *cp2, int fac)
72 {
73         int temp;
74
75         temp = cp1[0] - ((fac * cp2[0]) / 255);
76         if (temp < 0) cp[0] = 0; else cp[0] = temp;
77         temp = cp1[1] - ((fac * cp2[1]) / 255);
78         if (temp < 0) cp[1] = 0; else cp[1] = temp;
79         temp = cp1[2] - ((fac * cp2[2]) / 255);
80         if (temp < 0) cp[2] = 0; else cp[2] = temp;
81 }
82
83 static void blend_color_mul(char *cp, char *cp1, char *cp2, int fac)
84 {
85         int mfac = 255 - fac;
86         
87         /* first mul, then blend the fac */
88         cp[0] = (mfac * cp1[0] + fac * ((cp1[0] * cp2[0]) / 255)) / 255;
89         cp[1] = (mfac * cp1[1] + fac * ((cp1[1] * cp2[1]) / 255)) / 255;
90         cp[2] = (mfac * cp1[2] + fac * ((cp1[2] * cp2[2]) / 255)) / 255;
91 }
92
93 static void blend_color_lighten(char *cp, char *cp1, char *cp2, int fac)
94 {
95         /* See if are lighter, if so mix, else don't do anything.
96          * if the paint col is darker then the original, then ignore */
97         if (cp1[0] + cp1[1] + cp1[2] > cp2[0] + cp2[1] + cp2[2]) {
98                 cp[0] = cp1[0];
99                 cp[1] = cp1[1];
100                 cp[2] = cp1[2];
101         }
102         else
103                 blend_color_mix(cp, cp1, cp2, fac);
104 }
105
106 static void blend_color_darken(char *cp, char *cp1, char *cp2, int fac)
107 {
108         /* See if were darker, if so mix, else don't do anything.
109          * if the paint col is brighter then the original, then ignore */
110         if (cp1[0] + cp1[1] + cp1[2] < cp2[0] + cp2[1] + cp2[2]) {
111                 cp[0] = cp1[0];
112                 cp[1] = cp1[1];
113                 cp[2] = cp1[2];
114         }
115         else
116                 blend_color_mix(cp, cp1, cp2, fac);
117 }
118
119 unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode)
120 {
121         unsigned int dst;
122         int temp;
123         char *cp, *cp1, *cp2;
124
125         if (fac == 0)
126                 return src1;
127
128         cp = (char *)&dst;
129         cp1 = (char *)&src1;
130         cp2 = (char *)&src2;
131
132         switch (mode) {
133                 case IMB_BLEND_MIX:
134                         blend_color_mix(cp, cp1, cp2, fac); break;
135                 case IMB_BLEND_ADD:
136                         blend_color_add(cp, cp1, cp2, fac); break;
137                 case IMB_BLEND_SUB:
138                         blend_color_sub(cp, cp1, cp2, fac); break;
139                 case IMB_BLEND_MUL:
140                         blend_color_mul(cp, cp1, cp2, fac); break;
141                 case IMB_BLEND_LIGHTEN:
142                         blend_color_lighten(cp, cp1, cp2, fac); break;
143                 case IMB_BLEND_DARKEN:
144                         blend_color_darken(cp, cp1, cp2, fac); break;
145                 default:
146                         cp[0] = cp1[0];
147                         cp[1] = cp1[1];
148                         cp[2] = cp1[2];
149         }
150
151         if (mode == IMB_BLEND_ERASE_ALPHA) {
152                 temp = (cp1[3] - fac * cp2[3] / 255);
153                 cp[3] = (temp < 0) ? 0 : temp;
154         }
155         else { /* this does ADD_ALPHA also */
156                 temp = (cp1[3] + fac * cp2[3] / 255);
157                 cp[3] = (temp > 255) ? 255 : temp;
158         }
159
160         return dst;
161 }
162
163 static void blend_color_mix_float(float *cp, float *cp1, float *cp2, float fac)
164 {
165         float mfac = 1.0f - fac;
166         cp[0] = mfac * cp1[0] + fac * cp2[0];
167         cp[1] = mfac * cp1[1] + fac * cp2[1];
168         cp[2] = mfac * cp1[2] + fac * cp2[2];
169 }
170
171 static void blend_color_add_float(float *cp, float *cp1, float *cp2, float fac)
172 {
173         cp[0] = cp1[0] + fac * cp2[0];
174         cp[1] = cp1[1] + fac * cp2[1];
175         cp[2] = cp1[2] + fac * cp2[2];
176
177         if (cp[0] > 1.0f) cp[0] = 1.0f;
178         if (cp[1] > 1.0f) cp[1] = 1.0f;
179         if (cp[2] > 1.0f) cp[2] = 1.0f;
180 }
181
182 static void blend_color_sub_float(float *cp, float *cp1, float *cp2, float fac)
183 {
184         cp[0] = cp1[0] - fac * cp2[0];
185         cp[1] = cp1[1] - fac * cp2[1];
186         cp[2] = cp1[2] - fac * cp2[2];
187
188         if (cp[0] < 0.0f) cp[0] = 0.0f;
189         if (cp[1] < 0.0f) cp[1] = 0.0f;
190         if (cp[2] < 0.0f) cp[2] = 0.0f;
191 }
192
193 static void blend_color_mul_float(float *cp, float *cp1, float *cp2, float fac)
194 {
195         float mfac = 1.0f - fac;
196         
197         cp[0] = mfac * cp1[0] + fac * (cp1[0] * cp2[0]);
198         cp[1] = mfac * cp1[1] + fac * (cp1[1] * cp2[1]);
199         cp[2] = mfac * cp1[2] + fac * (cp1[2] * cp2[2]);
200 }
201
202 static void blend_color_lighten_float(float *cp, float *cp1, float *cp2, float fac)
203 {
204         /* See if are lighter, if so mix, else don't do anything.
205          * if the pafloat col is darker then the original, then ignore */
206         if (cp1[0] + cp1[1] + cp1[2] > cp2[0] + cp2[1] + cp2[2]) {
207                 cp[0] = cp1[0];
208                 cp[1] = cp1[1];
209                 cp[2] = cp1[2];
210         }
211         else
212                 blend_color_mix_float(cp, cp1, cp2, fac);
213 }
214
215 static void blend_color_darken_float(float *cp, float *cp1, float *cp2, float fac)
216 {
217         /* See if were darker, if so mix, else don't do anything.
218          * if the pafloat col is brighter then the original, then ignore */
219         if (cp1[0] + cp1[1] + cp1[2] < cp2[0] + cp2[1] + cp2[2]) {
220                 cp[0] = cp1[0];
221                 cp[1] = cp1[1];
222                 cp[2] = cp1[2];
223         }
224         else
225                 blend_color_mix_float(cp, cp1, cp2, fac);
226 }
227
228 void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_BlendMode mode)
229 {
230         if (fac == 0) {
231                 dst[0] = src1[0];
232                 dst[1] = src1[1];
233                 dst[2] = src1[2];
234                 dst[3] = src1[3];
235                 return;
236         }
237
238         switch (mode) {
239                 case IMB_BLEND_MIX:
240                         blend_color_mix_float(dst, src1, src2, fac); break;
241                 case IMB_BLEND_ADD:
242                         blend_color_add_float(dst, src1, src2, fac); break;
243                 case IMB_BLEND_SUB:
244                         blend_color_sub_float(dst, src1, src2, fac); break;
245                 case IMB_BLEND_MUL:
246                         blend_color_mul_float(dst, src1, src2, fac); break;
247                 case IMB_BLEND_LIGHTEN:
248                         blend_color_lighten_float(dst, src1, src2, fac); break;
249                 case IMB_BLEND_DARKEN:
250                         blend_color_darken_float(dst, src1, src2, fac); break;
251                 default:
252                         dst[0] = src1[0];
253                         dst[1] = src1[1];
254                         dst[2] = src1[2];
255         }
256
257         if (mode == IMB_BLEND_ERASE_ALPHA) {
258                 dst[3] = (src1[3] - fac * src2[3]);
259                 if (dst[3] < 0.0f) dst[3] = 0.0f;
260         }
261         else { /* this does ADD_ALPHA also */
262                 dst[3] = (src1[3] + fac * src2[3]);
263                 if (dst[3] > 1.0f) dst[3] = 1.0f;
264         }
265 }
266
267 /* clipping */
268
269 void IMB_rectclip(struct ImBuf *dbuf, struct ImBuf *sbuf, int *destx, 
270                   int *desty, int *srcx, int *srcy, int *width, int *height)
271 {
272         int tmp;
273
274         if (dbuf == NULL) return;
275         
276         if (*destx < 0) {
277                 *srcx -= *destx;
278                 *width += *destx;
279                 *destx = 0;
280         }
281         if (*srcx < 0) {
282                 *destx -= *srcx;
283                 *width += *srcx;
284                 *srcx = 0;
285         }
286         if (*desty < 0) {
287                 *srcy -= *desty;
288                 *height += *desty;
289                 *desty = 0;
290         }
291         if (*srcy < 0) {
292                 *desty -= *srcy;
293                 *height += *srcy;
294                 *srcy = 0;
295         }
296
297         tmp = dbuf->x - *destx;
298         if (*width > tmp) *width = tmp;
299         tmp = dbuf->y - *desty;
300         if (*height > tmp) *height = tmp;
301
302         if (sbuf) {
303                 tmp = sbuf->x - *srcx;
304                 if (*width > tmp) *width = tmp;
305                 tmp = sbuf->y - *srcy;
306                 if (*height > tmp) *height = tmp;
307         }
308
309         if ((*height <= 0) || (*width <= 0)) {
310                 *width = 0;
311                 *height = 0;
312         }
313 }
314
315 /* copy and blend */
316
317 void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, 
318                  int desty, int srcx, int srcy, int width, int height)
319 {
320         IMB_rectblend(dbuf, sbuf, destx, desty, srcx, srcy, width, height,
321                       IMB_BLEND_COPY);
322 }
323
324 void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, 
325                    int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode)
326 {
327         unsigned int *drect = NULL, *srect = NULL, *dr, *sr;
328         float *drectf = NULL, *srectf = NULL, *drf, *srf;
329         int do_float, do_char, srcskip, destskip, x;
330
331         if (dbuf == NULL) return;
332
333         IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &width, &height);
334
335         if (width == 0 || height == 0) return;
336         if (sbuf && sbuf->channels != 4) return;
337         if (dbuf->channels != 4) return;
338         
339         do_char = (sbuf && sbuf->rect && dbuf->rect);
340         do_float = (sbuf && sbuf->rect_float && dbuf->rect_float);
341
342         if (do_char) drect = dbuf->rect + desty * dbuf->x + destx;
343         if (do_float) drectf = dbuf->rect_float + (desty * dbuf->x + destx) * 4;
344
345         destskip = dbuf->x;
346
347         if (sbuf) {
348                 if (do_char) srect = sbuf->rect + srcy * sbuf->x + srcx;
349                 if (do_float) srectf = sbuf->rect_float + (srcy * sbuf->x + srcx) * 4;
350                 srcskip = sbuf->x;
351         }
352         else {
353                 srect = drect;
354                 srectf = drectf;
355                 srcskip = destskip;
356         }
357
358         if (mode == IMB_BLEND_COPY) {
359                 /* copy */
360                 for (; height > 0; height--) {
361                         if (do_char) {
362                                 memcpy(drect, srect, width * sizeof(int));
363                                 drect += destskip;
364                                 srect += srcskip;
365                         }
366
367                         if (do_float) {
368                                 memcpy(drectf, srectf, width * sizeof(float) * 4);
369                                 drectf += destskip * 4;
370                                 srectf += srcskip * 4;
371                         }
372                 }
373         }
374         else if (mode == IMB_BLEND_COPY_RGB) {
375                 /* copy rgb only */
376                 for (; height > 0; height--) {
377                         if (do_char) {
378                                 dr = drect;
379                                 sr = srect;
380                                 for (x = width; x > 0; x--, dr++, sr++) {
381                                         ((char *)dr)[0] = ((char *)sr)[0];
382                                         ((char *)dr)[1] = ((char *)sr)[1];
383                                         ((char *)dr)[2] = ((char *)sr)[2];
384                                 }
385                                 drect += destskip;
386                                 srect += srcskip;
387                         }
388
389                         if (do_float) {
390                                 drf = drectf;
391                                 srf = srectf;
392                                 for (x = width; x > 0; x--, drf += 4, srf += 4) {
393                                         drf[0] = srf[0];
394                                         drf[1] = srf[1];
395                                         drf[2] = srf[2];
396                                 }
397                                 drectf += destskip * 4;
398                                 srectf += srcskip * 4;
399                         }
400                 }
401         }
402         else if (mode == IMB_BLEND_COPY_ALPHA) {
403                 /* copy alpha only */
404                 for (; height > 0; height--) {
405                         if (do_char) {
406                                 dr = drect;
407                                 sr = srect;
408                                 for (x = width; x > 0; x--, dr++, sr++)
409                                         ((char *)dr)[3] = ((char *)sr)[3];
410                                 drect += destskip;
411                                 srect += srcskip;
412                         }
413
414                         if (do_float) {
415                                 drf = drectf;
416                                 srf = srectf;
417                                 for (x = width; x > 0; x--, drf += 4, srf += 4)
418                                         drf[3] = srf[3];
419                                 drectf += destskip * 4;
420                                 srectf += srcskip * 4;
421                         }
422                 }
423         }
424         else {
425                 /* blend */
426                 for (; height > 0; height--) {
427                         if (do_char) {
428                                 dr = drect;
429                                 sr = srect;
430                                 for (x = width; x > 0; x--, dr++, sr++)
431                                         *dr = IMB_blend_color(*dr, *sr, ((char *)sr)[3], mode);
432
433                                 drect += destskip;
434                                 srect += srcskip;
435                         }
436
437                         if (do_float) {
438                                 drf = drectf;
439                                 srf = srectf;
440                                 for (x = width; x > 0; x--, drf += 4, srf += 4)
441                                         IMB_blend_color_float(drf, drf, srf, srf[3], mode);
442
443                                 drectf += destskip * 4;
444                                 srectf += srcskip * 4;
445                         }               
446                 }
447         }
448 }
449
450 /* fill */
451
452 void IMB_rectfill(struct ImBuf *drect, const float col[4])
453 {
454         int num;
455
456         if (drect->rect) {
457                 unsigned int *rrect = drect->rect;
458                 char ccol[4];
459                 
460                 ccol[0] = (int)(col[0] * 255);
461                 ccol[1] = (int)(col[1] * 255);
462                 ccol[2] = (int)(col[2] * 255);
463                 ccol[3] = (int)(col[3] * 255);
464                 
465                 num = drect->x * drect->y;
466                 for (; num > 0; num--)
467                         *rrect++ = *((unsigned int *)ccol);
468         }
469         
470         if (drect->rect_float) {
471                 float *rrectf = drect->rect_float;
472                 
473                 num = drect->x * drect->y;
474                 for (; num > 0; num--) {
475                         *rrectf++ = col[0];
476                         *rrectf++ = col[1];
477                         *rrectf++ = col[2];
478                         *rrectf++ = col[3];
479                 }
480         }       
481 }
482
483
484 void buf_rectfill_area(unsigned char *rect, float *rectf, int width, int height, const float col[4],
485                                            int x1, int y1, int x2, int y2)
486 {
487         int i, j;
488         float a; /* alpha */
489         float ai; /* alpha inverted */
490         float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
491         if ((!rect && !rectf) || (!col) || col[3] == 0.0f)
492                 return;
493         
494         /* sanity checks for coords */
495         CLAMP(x1, 0, width);
496         CLAMP(x2, 0, width);
497         CLAMP(y1, 0, height);
498         CLAMP(y2, 0, height);
499
500         if (x1 > x2) SWAP(int, x1, x2);
501         if (y1 > y2) SWAP(int, y1, y2);
502         if (x1 == x2 || y1 == y2) return;
503         
504         a = col[3];
505         ai = 1 - a;
506         aich = ai / 255.0f;
507
508         if (rect) {
509                 unsigned char *pixel; 
510                 unsigned char chr = 0, chg = 0, chb = 0;
511                 float fr = 0, fg = 0, fb = 0;
512
513                 const int alphaint = FTOCHAR(a);
514                 
515                 if (a == 1.0f) {
516                         chr = FTOCHAR(col[0]);
517                         chg = FTOCHAR(col[1]);
518                         chb = FTOCHAR(col[2]);
519                 }
520                 else {
521                         fr = col[0] * a;
522                         fg = col[1] * a;
523                         fb = col[2] * a;
524                 }
525                 for (j = 0; j < y2 - y1; j++) {
526                         for (i = 0; i < x2 - x1; i++) {
527                                 pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
528                                 if (pixel >= rect && pixel < rect + (4 * (width * height))) {
529                                         if (a == 1.0f) {
530                                                 pixel[0] = chr;
531                                                 pixel[1] = chg;
532                                                 pixel[2] = chb;
533                                                 pixel[3] = 255;
534                                         }
535                                         else {
536                                                 int alphatest;
537                                                 pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f);
538                                                 pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f);
539                                                 pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f);
540                                                 pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255);
541                                         }
542                                 }
543                         }
544                 }
545         }
546         
547         if (rectf) {
548                 float *pixel;
549                 for (j = 0; j < y2 - y1; j++) {
550                         for (i = 0; i < x2 - x1; i++) {
551                                 pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
552                                 if (a == 1.0f) {
553                                         pixel[0] = col[0];
554                                         pixel[1] = col[1];
555                                         pixel[2] = col[2];
556                                         pixel[3] = 1.0f;
557                                 }
558                                 else {
559                                         float alphatest;
560                                         pixel[0] = (col[0] * a) + (pixel[0] * ai);
561                                         pixel[1] = (col[1] * a) + (pixel[1] * ai);
562                                         pixel[2] = (col[2] * a) + (pixel[2] * ai);
563                                         pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
564                                 }
565                         }
566                 }
567         }
568 }
569
570 void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2)
571 {
572         if (!ibuf) return;
573         buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, x1, y1, x2, y2);
574 }
575
576
577 void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
578 {
579         int i;
580         if (ibuf->rect_float) {
581                 float *fbuf = ibuf->rect_float + 3;
582                 for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) { *fbuf = value; }
583         }
584         else {
585                 const unsigned char cvalue = value * 255;
586                 unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3;
587                 for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) { *cbuf = cvalue; }
588         }
589 }