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