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