style cleanup: spaces -> tabs
[blender.git] / source / blender / render / intern / source / pixelblending.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  * Contributor(s): Full recode, 2004-2006 Blender Foundation
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/render/intern/source/pixelblending.c
27  *  \ingroup render
28  *
29  * Functions to blend pixels with or without alpha, in various formats
30  * nzc - June 2000
31  */
32
33
34 #include <math.h>
35 #include <string.h>
36
37 /* global includes */
38 #include "BLI_math.h"
39 #include "BLI_rand.h"
40
41 /* own includes */
42 #include "render_types.h"
43 #include "renderpipeline.h"
44 #include "pixelblending.h"
45 #include "gammaCorrectionTables.h"
46
47 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
48 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
49 /* only to be used here in this file, it's for speed */
50 extern struct Render R;
51 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
52
53
54 /* ------------------------------------------------------------------------- */
55 /* Debug/behavior defines                                                   */
56 /* if defined: alpha blending with floats clips color, as with shorts       */
57 /* #define RE_FLOAT_COLOR_CLIPPING  */
58 /* if defined: alpha values are clipped                                      */
59 /* For now, we just keep alpha clipping. We run into thresholding and        */
60 /* blending difficulties otherwise. Be careful here.                         */
61 #define RE_ALPHA_CLIPPING
62
63
64
65 /* Threshold for a 'full' pixel: pixels with alpha above this level are      */
66 /* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF           */
67 #define RE_FULL_COLOR_FLOAT 0.9998f
68 /* Threshold for an 'empty' pixel: pixels with alpha above this level are    */
69 /* considered completely transparent. This is the decimal value              */
70 /* for 0x000F / 0xFFFF                                                       */
71 #define RE_EMPTY_COLOR_FLOAT 0.0002f
72
73
74 /* ------------------------------------------------------------------------- */
75
76 void addAlphaOverFloat(float dest[4], const float source[4])
77 {
78         /* d = s + (1-alpha_s)d*/
79         float mul;
80
81         mul = 1.0f - source[3];
82
83         dest[0] = (mul * dest[0]) + source[0];
84         dest[1] = (mul * dest[1]) + source[1];
85         dest[2] = (mul * dest[2]) + source[2];
86         dest[3] = (mul * dest[3]) + source[3];
87
88 }
89
90
91 /* ------------------------------------------------------------------------- */
92
93 void addAlphaUnderFloat(float dest[4], const float source[4])
94 {
95         float mul;
96
97         mul = 1.0f - dest[3];
98
99         dest[0] += (mul * source[0]);
100         dest[1] += (mul * source[1]);
101         dest[2] += (mul * source[2]);
102         dest[3] += (mul * source[3]);
103
104
105
106 /* ------------------------------------------------------------------------- */
107 void addalphaAddfacFloat(float dest[4], const float source[4], char addfac)
108 {
109         float m; /* weiging factor of destination */
110         float c; /* intermediate color           */
111
112         /* Addfac is a number between 0 and 1: rescale */
113         /* final target is to diminish the influence of dest when addfac rises */
114         m = 1.0f - (source[3] * ((255 - addfac) / 255.0f));
115
116         /* blend colors*/
117         c = (m * dest[0]) + source[0];
118 #ifdef RE_FLOAT_COLOR_CLIPPING
119         if (c >= RE_FULL_COLOR_FLOAT) dest[0] = RE_FULL_COLOR_FLOAT; 
120         else 
121 #endif
122         dest[0] = c;
123
124         c = (m * dest[1]) + source[1];
125 #ifdef RE_FLOAT_COLOR_CLIPPING
126         if (c >= RE_FULL_COLOR_FLOAT) dest[1] = RE_FULL_COLOR_FLOAT; 
127         else 
128 #endif
129         dest[1] = c;
130
131         c = (m * dest[2]) + source[2];
132 #ifdef RE_FLOAT_COLOR_CLIPPING
133         if (c >= RE_FULL_COLOR_FLOAT) dest[2] = RE_FULL_COLOR_FLOAT; 
134         else 
135 #endif
136         dest[2] = c;
137
138         c = (m * dest[3]) + source[3];
139 #ifdef RE_ALPHA_CLIPPING
140         if (c >= RE_FULL_COLOR_FLOAT) dest[3] = RE_FULL_COLOR_FLOAT; 
141         else 
142 #endif
143         dest[3] = c;
144
145 }
146
147
148 /* ------------------------------------------------------------------------- */
149
150 /* filtered adding to scanlines */
151 void add_filt_fmask(unsigned int mask, const float col[4], float *rowbuf, int row_w)
152 {
153         /* calc the value of mask */
154         float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2;
155         float *rb1, *rb2, *rb3;
156         float val, r, g, b, al;
157         unsigned int a, maskand, maskshift;
158         int j;
159         
160         r = col[0];
161         g = col[1];
162         b = col[2];
163         al = col[3];
164
165         rb2 = rowbuf - 4;
166         rb3 = rb2 - 4 * row_w;
167         rb1 = rb2 + 4 * row_w;
168
169         maskand = (mask & 255);
170         maskshift = (mask >> 8);
171
172         for (j = 2; j >= 0; j--) {
173
174                 a = j;
175
176                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
177                 if (val != 0.0f) {
178                         rb1[0] += val * r;
179                         rb1[1] += val * g;
180                         rb1[2] += val * b;
181                         rb1[3] += val * al;
182                 }
183                 a += 3;
184                 
185                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
186                 if (val != 0.0f) {
187                         rb2[0] += val * r;
188                         rb2[1] += val * g;
189                         rb2[2] += val * b;
190                         rb2[3] += val * al;
191                 }
192                 a += 3;
193                 
194                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
195                 if (val != 0.0f) {
196                         rb3[0] += val * r;
197                         rb3[1] += val * g;
198                         rb3[2] += val * b;
199                         rb3[3] += val * al;
200                 }
201                 
202                 rb1 += 4;
203                 rb2 += 4;
204                 rb3 += 4;
205         }
206 }
207
208
209 void mask_array(unsigned int mask, float filt[3][3])
210 {
211         float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2;
212         unsigned int maskand = (mask & 255);
213         unsigned int maskshift = (mask >> 8);
214         int a, j;
215         
216         for (j = 2; j >= 0; j--) {
217                 
218                 a = j;
219                 
220                 filt[2][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
221
222                 a += 3;
223                 
224                 filt[1][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
225                 
226                 a += 3;
227                 
228                 filt[0][2 - j] = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
229         }
230 }
231
232
233 /**
234  * Index ordering, scanline based:
235  *
236  * <pre>
237  *      ---    ---   ---
238  *     | 2,0 | 2,1 | 2,2 |
239  *      ---    ---   ---
240  *     | 1,0 | 1,1 | 1,2 |
241  *      ---    ---   ---
242  *     | 0,0 | 0,1 | 0,2 |
243  *      ---    ---   ---
244  * </pre>
245  */
246
247 void add_filt_fmask_coord(float filt[3][3], const float col[4], float *rowbuf, int row_w, int col_h, int x, int y)
248 {
249         float *fpoin[3][3];
250         float val, r, g, b, al, lfilt[3][3];
251         
252         r = col[0];
253         g = col[1];
254         b = col[2];
255         al = col[3];
256         
257         memcpy(lfilt, filt, sizeof(lfilt));
258         
259         fpoin[0][1] = rowbuf - 4 * row_w;
260         fpoin[1][1] = rowbuf;
261         fpoin[2][1] = rowbuf + 4 * row_w;
262
263         fpoin[0][0] = fpoin[0][1] - 4;
264         fpoin[1][0] = fpoin[1][1] - 4;
265         fpoin[2][0] = fpoin[2][1] - 4;
266
267         fpoin[0][2] = fpoin[0][1] + 4;
268         fpoin[1][2] = fpoin[1][1] + 4;
269         fpoin[2][2] = fpoin[2][1] + 4;
270
271         if (y == 0) {
272                 fpoin[0][0] = fpoin[1][0];
273                 fpoin[0][1] = fpoin[1][1];
274                 fpoin[0][2] = fpoin[1][2];
275                 /* filter needs the opposite value yes! */
276                 lfilt[0][0] = filt[2][0];
277                 lfilt[0][1] = filt[2][1];
278                 lfilt[0][2] = filt[2][2];
279         }
280         else if (y == col_h - 1) {
281                 fpoin[2][0] = fpoin[1][0];
282                 fpoin[2][1] = fpoin[1][1];
283                 fpoin[2][2] = fpoin[1][2];
284
285                 lfilt[2][0] = filt[0][0];
286                 lfilt[2][1] = filt[0][1];
287                 lfilt[2][2] = filt[0][2];
288         }
289         
290         if (x == 0) {
291                 fpoin[2][0] = fpoin[2][1];
292                 fpoin[1][0] = fpoin[1][1];
293                 fpoin[0][0] = fpoin[0][1];
294
295                 lfilt[2][0] = filt[2][2];
296                 lfilt[1][0] = filt[1][2];
297                 lfilt[0][0] = filt[0][2];
298         }
299         else if (x == row_w - 1) {
300                 fpoin[2][2] = fpoin[2][1];
301                 fpoin[1][2] = fpoin[1][1];
302                 fpoin[0][2] = fpoin[0][1];
303
304                 lfilt[2][2] = filt[2][0];
305                 lfilt[1][2] = filt[1][0];
306                 lfilt[0][2] = filt[0][0];
307         }
308         
309         
310         /* loop unroll */
311 #define MASKFILT(i, j)                                                        \
312         val = lfilt[i][j];                                                        \
313         if (val != 0.0f) {                                                        \
314                 float *fp = fpoin[i][j];                                              \
315                 fp[0] += val * r;                                                     \
316                 fp[1] += val * g;                                                     \
317                 fp[2] += val * b;                                                     \
318                 fp[3] += val * al;                                                    \
319         } (void)0
320         
321         MASKFILT(0, 0);
322         MASKFILT(0, 1);
323         MASKFILT(0, 2);
324         MASKFILT(1, 0);
325         MASKFILT(1, 1);
326         MASKFILT(1, 2);
327         MASKFILT(2, 0);
328         MASKFILT(2, 1);
329         MASKFILT(2, 2);
330
331 #undef MASKFILT
332 }
333
334 void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize)
335 {
336         /* calc the value of mask */
337         float **fmask1 = R.samples->fmask1, **fmask2 = R.samples->fmask2;
338         float *rb1, *rb2, *rb3;
339         float val;
340         unsigned int a, maskand, maskshift;
341         int i, j;
342         
343         rb2 = rowbuf - pixsize;
344         rb3 = rb2 - pixsize * row_w;
345         rb1 = rb2 + pixsize * row_w;
346         
347         maskand = (mask & 255);
348         maskshift = (mask >> 8);
349         
350         for (j = 2; j >= 0; j--) {
351                 
352                 a = j;
353                 
354                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
355                 if (val != 0.0f) {
356                         for (i = 0; i < pixsize; i++)
357                                 rb1[i] += val * in[i];
358                 }
359                 a += 3;
360                 
361                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
362                 if (val != 0.0f) {
363                         for (i = 0; i < pixsize; i++)
364                                 rb2[i] += val * in[i];
365                 }
366                 a += 3;
367                 
368                 val = *(fmask1[a] + maskand) + *(fmask2[a] + maskshift);
369                 if (val != 0.0f) {
370                         for (i = 0; i < pixsize; i++)
371                                 rb3[i] += val * in[i];
372                 }
373                 
374                 rb1 += pixsize;
375                 rb2 += pixsize;
376                 rb3 += pixsize;
377         }
378 }
379
380 /* ------------------------------------------------------------------------- */
381 void addalphaAddFloat(float dest[4], const float source[4])
382 {
383
384         /* Makes me wonder whether this is required... */
385         if (dest[3] < RE_EMPTY_COLOR_FLOAT) {
386                 dest[0] = source[0];
387                 dest[1] = source[1];
388                 dest[2] = source[2];
389                 dest[3] = source[3];
390                 return;
391         }
392
393         /* no clipping! */
394         dest[0] = dest[0] + source[0];
395         dest[1] = dest[1] + source[1];
396         dest[2] = dest[2] + source[2];
397         dest[3] = dest[3] + source[3];
398
399 }
400
401
402 /* ---------------------------------------------------------------------------- */