Spelling Cleanup
[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  *
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
238 index ordering, scanline based:
239
240  ---    ---   ---  
241 | 2,0 | 2,1 | 2,2 |
242  ---    ---   ---  
243 | 1,0 | 1,1 | 1,2 |
244  ---    ---   ---  
245 | 0,0 | 0,1 | 0,2 |
246  ---    ---   ---  
247 */
248
249 void add_filt_fmask_coord(float filt[][3], float *col, float *rowbuf, int row_w, int col_h, int x, int y)
250 {
251         float *fpoin[3][3];
252         float val, r, g, b, al, lfilt[3][3];
253         
254         r= col[0];
255         g= col[1];
256         b= col[2];
257         al= col[3];
258         
259         memcpy(lfilt, filt, sizeof(lfilt));
260         
261         fpoin[0][1]= rowbuf-4*row_w;
262         fpoin[1][1]= rowbuf;
263         fpoin[2][1]= rowbuf+4*row_w;
264         
265         fpoin[0][0]= fpoin[0][1] - 4;
266         fpoin[1][0]= fpoin[1][1] - 4;
267         fpoin[2][0]= fpoin[2][1] - 4;
268         
269         fpoin[0][2]= fpoin[0][1] + 4;
270         fpoin[1][2]= fpoin[1][1] + 4;
271         fpoin[2][2]= fpoin[2][1] + 4;
272         
273         if(y==0) {
274                 fpoin[0][0]= fpoin[1][0];
275                 fpoin[0][1]= fpoin[1][1];
276                 fpoin[0][2]= fpoin[1][2];
277                 /* filter needs the opposite value yes! */
278                 lfilt[0][0]= filt[2][0];
279                 lfilt[0][1]= filt[2][1];
280                 lfilt[0][2]= filt[2][2];
281         }
282         else if(y==col_h-1) {
283                 fpoin[2][0]= fpoin[1][0];
284                 fpoin[2][1]= fpoin[1][1];
285                 fpoin[2][2]= fpoin[1][2];
286                 
287                 lfilt[2][0]= filt[0][0];
288                 lfilt[2][1]= filt[0][1];
289                 lfilt[2][2]= filt[0][2];
290         }
291         
292         if(x==0) {
293                 fpoin[2][0]= fpoin[2][1];
294                 fpoin[1][0]= fpoin[1][1];
295                 fpoin[0][0]= fpoin[0][1];
296                 
297                 lfilt[2][0]= filt[2][2];
298                 lfilt[1][0]= filt[1][2];
299                 lfilt[0][0]= filt[0][2];
300         }
301         else if(x==row_w-1) {
302                 fpoin[2][2]= fpoin[2][1];
303                 fpoin[1][2]= fpoin[1][1];
304                 fpoin[0][2]= fpoin[0][1];
305                 
306                 lfilt[2][2]= filt[2][0];
307                 lfilt[1][2]= filt[1][0];
308                 lfilt[0][2]= filt[0][0];
309         }
310         
311         
312         /* loop unroll */
313 #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; }
314         
315         MASKFILT(0, 0)
316         MASKFILT(0, 1)
317         MASKFILT(0, 2)
318         MASKFILT(1, 0)
319         MASKFILT(1, 1)
320         MASKFILT(1, 2)
321         MASKFILT(2, 0)
322         MASKFILT(2, 1)
323         MASKFILT(2, 2)
324 }
325
326 void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize)
327 {
328         /* calc the value of mask */
329         float **fmask1= R.samples->fmask1, **fmask2=R.samples->fmask2;
330         float *rb1, *rb2, *rb3;
331         float val;
332         unsigned int a, maskand, maskshift;
333         int i, j;
334         
335         rb2= rowbuf-pixsize;
336         rb3= rb2-pixsize*row_w;
337         rb1= rb2+pixsize*row_w;
338         
339         maskand= (mask & 255);
340         maskshift= (mask >>8);
341         
342         for(j=2; j>=0; j--) {
343                 
344                 a= j;
345                 
346                 val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
347                 if(val!=0.0f) {
348                         for(i= 0; i<pixsize; i++)
349                                 rb1[i]+= val*in[i];
350                 }
351                 a+=3;
352                 
353                 val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
354                 if(val!=0.0f) {
355                         for(i= 0; i<pixsize; i++)
356                                 rb2[i]+= val*in[i];
357                 }
358                 a+=3;
359                 
360                 val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
361                 if(val!=0.0f) {
362                         for(i= 0; i<pixsize; i++)
363                                 rb3[i]+= val*in[i];
364                 }
365                 
366                 rb1+= pixsize;
367                 rb2+= pixsize;
368                 rb3+= pixsize;
369         }
370 }
371
372 /* ------------------------------------------------------------------------- */
373 void addalphaAddFloat(float *dest, float *source)
374 {
375
376         /* Makes me wonder whether this is required... */
377         if( dest[3] < RE_EMPTY_COLOR_FLOAT) {
378                 dest[0] = source[0];
379                 dest[1] = source[1];
380                 dest[2] = source[2];
381                 dest[3] = source[3];
382                 return;
383         }
384
385         /* no clipping! */
386         dest[0] = dest[0]+source[0];
387         dest[1] = dest[1]+source[1];
388         dest[2] = dest[2]+source[2];
389         dest[3] = dest[3]+source[3];
390
391 }
392
393
394 /* ---------------------------------------------------------------------------- */
395
396
397 /* eof pixelblending.c */