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