Initial revision
[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/BL DUAL 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. The Blender
15  * Foundation also sells licenses for use in proprietary software under
16  * the Blender License.  See http://www.blender.org/BL/ for information
17  * about this.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  *
28  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
29  * All rights reserved.
30  *
31  * The Original Code is: all of this file.
32  *
33  * Contributor(s): none yet.
34  *
35  * ***** END GPL/BL DUAL LICENSE BLOCK *****
36  */
37
38 #include <math.h>
39
40 /* global includes */
41 #include "render.h"
42 #include "render_intern.h"
43
44 /* local includes */
45 #include "vanillaRenderPipe_types.h"
46
47 /* own includes */
48 #include "pixelblending_types.h"
49 #include "pixelblending.h"
50 #include "gammaCorrectionTables.h"
51
52 /* externals */
53
54 /* ------------------------------------------------------------------------- */
55 /* Debug/behaviour defines                                                   */
56 /* if defined: alpha blending with floats clips colour, as with shorts       */
57 /* #define RE_FLOAT_COLOUR_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 /* functions --------------------------------------------------------------- */
64
65 /*
66   One things about key-alpha is that simply dividing by the alpha will
67   sometimes cause 'overflows' in that the pixel colours will be shot
68   way over full colour. This should be caught, and subsequently, the
69   operation will end up modifying the alpha as well.
70
71   Actually, when the starting colour is premul, it shouldn't overflow
72   ever. Strange thing is that colours keep overflowing...
73
74 */
75 void applyKeyAlphaCharCol(char* target) {
76
77         if ((!(target[3] == 0))
78                 || (target[3] == 255)) {
79                 /* else: nothing to do */
80                 /* check whether div-ing is enough */
81                 float cf[4];
82                 cf[0] = target[0]/target[3];
83                 cf[1] = target[1]/target[3];
84                 cf[2] = target[2]/target[3];
85                 if ((cf[0] <= 1.0) && (cf[1] <= 1.0) && (cf[2] <= 1.0)) {
86                         /* all colours remain properly scaled? */
87                         /* scale to alpha */
88                         cf[0] = (float) target[0] * (255.0/ (float)target[3]);
89                         cf[1] = (float) target[1] * (255.0/ (float)target[3]);
90                         cf[2] = (float) target[2] * (255.0/ (float)target[3]);
91
92                         /* Clipping is important. */
93                         target[0] = (cf[0] > 255.0 ? 255 : (char) cf[0]);
94                         target[1] = (cf[1] > 255.0 ? 255 : (char) cf[1]);
95                         target[2] = (cf[2] > 255.0 ? 255 : (char) cf[2]);
96                         
97                 } else {
98                         /* shouldn't happen! we were premul, remember? */
99 /* should go to error handler:                  printf("Non-premul colour detected\n"); */
100                 }
101         }
102
103 } /* end of void applyKeyAlphaCharCol(char* target) */
104
105 /* ------------------------------------------------------------------------- */
106
107 void addAddSampColF(float *sampvec, float *source, int mask, int osaNr, 
108                     char addfac)
109 {
110         int a;
111         
112         for(a=0; a < osaNr; a++) {
113                 if(mask & (1<<a)) addalphaAddfacFloat(sampvec, source, addfac);
114                 sampvec+= 4;
115         }
116 } /* end of void addAddSampColF(float, float, int, int) */
117
118 /* ------------------------------------------------------------------------- */
119
120 void addOverSampColF(float *sampvec, float *source, int mask, int osaNr)
121 {
122         int a;
123         
124         for(a=0; a < osaNr; a++) {
125                 if(mask & (1<<a)) addAlphaOverFloat(sampvec, source);
126                 sampvec+= 4;
127         }
128 } /* end of void addOverSampColF(float, float, int, int) */
129
130 /* ------------------------------------------------------------------------- */
131
132 int addUnderSampColF(float *sampvec, float *source, int mask, int osaNr)
133 {
134         int a, retval = osaNr;
135         
136         for(a=0; a < osaNr; a++) {
137                 if(mask & (1<<a)) addAlphaUnderFloat(sampvec, source);
138                 if(sampvec[3] > RE_FULL_COLOUR_FLOAT) retval--;
139                 sampvec+= 4;
140         }
141         return retval;
142 } /* end of int addToSampColF(float, float, int, int) */
143
144 /* ------------------------------------------------------------------------- */
145
146 int addToSampCol(unsigned short *sampcol, unsigned short *shortcol, int mask, int osaNr)
147 {
148         int a, retval = osaNr;
149         
150         for(a=0; a < osaNr; a++) {
151                 if(mask & (1<<a)) addAlphaUnderShort(sampcol, shortcol);
152                 if(sampcol[3]>0xFFF0) retval--;
153                 sampcol+= 4;
154         }
155         return retval;
156 } /* end of int addToSampCol(unsigned short, uhost, int, int) */
157
158 /* ------------------------------------------------------------------------- */
159
160 int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask)
161 {
162         int a, retval = R.osa;
163         
164         for(a=0; a < R.osa; a++) {
165                 if(mask & (1<<a)) addAlphaUnderShort(sampcol, shortcol);
166                 if(sampcol[3]>0xFFF0) retval--;
167                 sampcol+= 4;
168         }
169         return retval;
170 } /* end of int addtosampcol(unsigned short *sampcol, unsigned short *shortcol, int mask) */
171
172 /* ------------------------------------------------------------------------- */
173
174 void addAlphaOverShort(unsigned short *doel, unsigned short *bron)   /* vult bron over doel in met alpha van bron */
175 {
176         unsigned int c;
177         unsigned int mul;
178
179         if( doel[3]==0 || bron[3]>=0xFFF0) {    /* is getest, scheelt veel */
180                 *((unsigned int *)doel)= *((unsigned int *)bron);
181                 *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
182                 return;
183         }
184
185         mul= 0xFFFF-bron[3];
186
187         c= ((mul*doel[0])>>16)+bron[0];
188         if(c>=0xFFF0) doel[0]=0xFFF0; 
189         else doel[0]= c;
190         c= ((mul*doel[1])>>16)+bron[1];
191         if(c>=0xFFF0) doel[1]=0xFFF0; 
192         else doel[1]= c;
193         c= ((mul*doel[2])>>16)+bron[2];
194         if(c>=0xFFF0) doel[2]=0xFFF0; 
195         else doel[2]= c;
196         c= ((mul*doel[3])>>16)+bron[3];
197         if(c>=0xFFF0) doel[3]=0xFFF0; 
198         else doel[3]= c;
199
200 } /* end of void addAlphaOverShort(unsigned short *doel, unsigned short *bron) */
201
202 /* ------------------------------------------------------------------------- */
203
204 void addAlphaUnderShort(unsigned short *doel, unsigned short *bron)   /* vult bron onder doel in met alpha van doel */
205 {
206         unsigned int c;
207         unsigned int mul;
208
209         if(doel[3]>=0xFFF0) return;
210         if( doel[3]==0 ) {      /* is getest, scheelt veel */
211                 *((unsigned int *)doel)= *((unsigned int *)bron);
212                 *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
213                 return;
214         }
215
216         mul= 0xFFFF-doel[3];
217
218         c= ((mul*bron[0])>>16)+doel[0];
219         if(c>=0xFFF0) doel[0]=0xFFF0; 
220         else doel[0]= c;
221         c= ((mul*bron[1])>>16)+doel[1];
222         if(c>=0xFFF0) doel[1]=0xFFF0; 
223         else doel[1]= c;
224         c= ((mul*bron[2])>>16)+doel[2];
225         if(c>=0xFFF0) doel[2]=0xFFF0;
226         else doel[2]= c;
227         c= ((mul*bron[3])>>16)+doel[3];
228         if(c>=0xFFF0) doel[3]=0xFFF0;
229         else doel[3]= c;
230
231 } /* end of void addAlphaUnderShort(unsigned short *doel, unsigned short *bron) */
232   
233 /* ------------------------------------------------------------------------- */
234
235 void addAlphaOverFloat(float *dest, float *source)
236 {
237     /* d = s + (1-alpha_s)d*/
238     float c;
239     float mul;
240     
241     /* I may want to disable this clipping */
242 #ifdef RE_FLOAT_COLOUR_CLIPPING
243     if( /*  (-RE_FULL_COLOUR_FLOAT < source[3]) */
244 /*          && */ (source[3] >  RE_FULL_COLOUR_FLOAT) ) {       /* is getest, scheelt veel */
245         dest[0] = source[0];
246         dest[1] = source[1];
247         dest[2] = source[2];
248         dest[3] = source[3];
249         return;
250     }
251 #endif
252
253         mul= 1.0 - source[3];
254
255         c= (mul*dest[0]) + source[0];
256 #ifdef RE_FLOAT_COLOUR_CLIPPING
257         if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT; 
258         else 
259 #endif
260        dest[0]= c;
261    
262         c= (mul*dest[1]) + source[1];
263 #ifdef RE_FLOAT_COLOUR_CLIPPING
264         if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT; 
265         else 
266 #endif
267        dest[1]= c;
268
269         c= (mul*dest[2]) + source[2];
270 #ifdef RE_FLOAT_COLOUR_CLIPPING
271         if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT; 
272         else 
273 #endif
274        dest[2]= c;
275
276         c= (mul*dest[3]) + source[3];
277 #ifdef RE_ALPHA_CLIPPING
278         if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT; 
279         else 
280 #endif
281        dest[3]= c;
282
283 } /* end of void addAlphaOverFloat(float *doel, float *bron) */
284
285
286
287 /* ------------------------------------------------------------------------- */
288
289 void addAlphaUnderFloat(float *dest, float *source)
290 {
291     float c;
292     float mul;
293     
294     /* I may want to disable this clipping */
295 #ifdef RE_FLOAT_COLOUR_CLIPPING
296     if( dest[3] >= RE_FULL_COLOUR_FLOAT) return;
297 #endif
298     if( (-RE_EMPTY_COLOUR_FLOAT < dest[3])
299         && (dest[3] <  RE_EMPTY_COLOUR_FLOAT) ) {       /* is getest, scheelt veel */
300         dest[0] = source[0];
301         dest[1] = source[1];
302         dest[2] = source[2];
303         dest[3] = source[3];
304         return;
305     }
306
307         mul= 1.0 - dest[3];
308
309         c= (mul*source[0]) + dest[0];
310 #ifdef RE_FLOAT_COLOUR_CLIPPING
311         if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_UNITY_COLOUR_FLOAT; 
312         else 
313 #endif
314        dest[0]= c;
315    
316         c= (mul*source[1]) + dest[1];
317 #ifdef RE_FLOAT_COLOUR_CLIPPING
318         if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_UNITY_COLOUR_FLOAT; 
319         else 
320 #endif
321        dest[1]= c;
322
323         c= (mul*source[2]) + dest[2];
324 #ifdef RE_FLOAT_COLOUR_CLIPPING
325         if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_UNITY_COLOUR_FLOAT; 
326         else 
327 #endif
328        dest[2]= c;
329
330         c= (mul*source[3]) + dest[3];
331 #ifdef RE_ALPHA_CLIPPING
332         if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_UNITY_COLOUR_FLOAT; 
333         else 
334 #endif
335        dest[3]= c;
336
337 } /* end of void addAlphaUnderFloat(float *doel, float *bron) */
338
339 /* ------------------------------------------------------------------------- */
340
341 void cpShortColV2CharColV(unsigned short *source, char *dest)
342 {
343     dest[0] = source[0]>>8;
344     dest[1] = source[1]>>8;
345     dest[2] = source[2]>>8;
346     dest[3] = source[3]>>8;
347 } /* end of void cpShortColV2CharColV(unsigned short *source, char *dest) */
348 /* ------------------------------------------------------------------------- */
349
350 void cpCharColV2ShortColV(char *source, unsigned short *dest)
351 {
352     dest[0] = source[0]<<8;
353     dest[1] = source[1]<<8;
354     dest[2] = source[2]<<8;
355     dest[3] = source[3]<<8;
356 } /* end of void cpShortColV2CharColV(char *source, unsigned short *dest) */
357
358 /* ------------------------------------------------------------------------- */
359
360 void cpIntColV2CharColV(unsigned int *source, char *dest)
361 {
362     dest[0] = source[0]>>24;
363     dest[1] = source[1]>>24;
364     dest[2] = source[2]>>24;
365     dest[3] = source[3]>>24;
366 } /* end of void cpIntColV2CharColV(unsigned int *source, char *dest) */
367
368 /* ------------------------------------------------------------------------- */
369
370 void cpCharColV2FloatColV(char *source, float *dest)
371 {
372         /* What about endianness? Might be caught at this level :) */
373     dest[0] = source[0]/255.0;  
374     dest[1] = source[1]/255.0;  
375     dest[2] = source[2]/255.0;
376     dest[3] = source[3]/255.0;
377 } /* end of void cpCharColV2FloatColV(char *source, float *dest) */
378 /* ------------------------------------------------------------------------- */
379
380 void cpShortColV2FloatColV(unsigned short *source, float *dest)
381 {
382     dest[0] = source[0]/65535.0;  
383     dest[1] = source[1]/65535.0;  
384     dest[2] = source[2]/65535.0;
385     dest[3] = source[3]/65535.0;
386 } /* end of void cpShortColV2FloatColV(char *source, float *dest) */
387
388 /* ------------------------------------------------------------------------- */
389
390 void cpFloatColV2CharColV(float* source, char *dest)
391 {
392   /* can't this be done more efficient? hope the conversions are correct... */
393   if (source[0] < 0.0)      dest[0] = 0;
394   else if (source[0] > 1.0) dest[0] = 255;
395   else dest[0] = (char) (source[0] * 255.0);
396
397   if (source[1] < 0.0)      dest[1] = 0;
398   else if (source[1] > 1.0) dest[1] = 255;
399   else dest[1] = (char) (source[1] * 255.0);
400
401   if (source[2] < 0.0)      dest[2] = 0;
402   else if (source[2] > 1.0) dest[2] = 255;
403   else dest[2] = (char) (source[2] * 255.0);
404
405   if (source[3] < 0.0)      dest[3] = 0;
406   else if (source[3] > 1.0) dest[3] = 255;
407   else dest[3] = (char) (source[3] * 255.0);
408
409 } /* end of void cpFloatColV2CharColV(float* source, char *dest) */
410
411 /* ------------------------------------------------------------------------- */
412
413 void cpShortColV(unsigned short *source, unsigned short *dest)
414 {
415     dest[0] = source[0];
416     dest[1] = source[1];
417     dest[2] = source[2];
418     dest[3] = source[3];
419 } /* end of void cpShortColV(unsigned short *source, unsigned short *dest) */
420
421 /* ------------------------------------------------------------------------- */
422 void cpFloatColV(float *source, float *dest)
423 {
424     dest[0] = source[0];
425     dest[1] = source[1];
426     dest[2] = source[2];
427     dest[3] = source[3];
428 } /* end of void cpFloatColV(float *source, float *dest) */
429
430 /* ------------------------------------------------------------------------- */
431
432 void cpCharColV(char *source, char *dest)
433 {
434     dest[0] = source[0];
435     dest[1] = source[1];
436     dest[2] = source[2];
437     dest[3] = source[3];
438 } /* end of void cpCharColV(char *source, char *dest) */
439
440 /* ------------------------------------------------------------------------- */
441 void addalphaAddfacFloat(float *dest, float *source, char addfac)
442   /* doel= bron over doel  */
443 {
444     float m; /* weiging factor of destination */
445     float c; /* intermediate colour           */
446
447     /* 1. copy source straight away if dest has zero alpha */
448         /* 2. copy dest straight away if dest has full alpha   */
449         /* I am not sure whether (2) is correct. It seems to   */
450         /* me that this should not happen if float colours     */
451         /* aren't clipped at 1.0 .                             */
452         /* I'll keep the code, but disabled....                */
453     if ( (dest[3] < RE_EMPTY_COLOUR_FLOAT) 
454                 /*   || source[3] > RE_FULL_COLOUR_FLOAT */ ) {
455         dest[0] = source[0];
456         dest[1] = source[1];
457         dest[2] = source[2];
458         dest[3] = source[3];
459         return;
460     }
461
462     /* Addfac is a number between 0 and 1: rescale */
463     /* final target is to diminish the influence of dest when addfac rises */
464     m = 1.0 - ( source[3] * ((255.0 - addfac) / 255.0));
465
466     /* blend colours*/
467     c= (m * dest[0]) + source[0];
468 #ifdef RE_FLOAT_COLOUR_CLIPPING
469     if(c >= RE_FULL_COLOUR_FLOAT) dest[0] = RE_FULL_COLOUR_FLOAT; 
470     else 
471 #endif
472         dest[0]= c;
473    
474     c= (m * dest[1]) + source[1];
475 #ifdef RE_FLOAT_COLOUR_CLIPPING
476     if(c >= RE_FULL_COLOUR_FLOAT) dest[1] = RE_FULL_COLOUR_FLOAT; 
477     else 
478 #endif
479         dest[1]= c;
480     
481     c= (m * dest[2]) + source[2];
482 #ifdef RE_FLOAT_COLOUR_CLIPPING
483     if(c >= RE_FULL_COLOUR_FLOAT) dest[2] = RE_FULL_COLOUR_FLOAT; 
484     else 
485 #endif
486         dest[2]= c;
487
488         c= dest[3] + source[3];
489 #ifdef RE_ALPHA_CLIPPING
490         if(c >= RE_FULL_COLOUR_FLOAT) dest[3] = RE_FULL_COLOUR_FLOAT; 
491         else 
492 #endif
493        dest[3]= c;
494
495 } /* end of void addalphaAddfacFloat(unsigned short *doel, unsigned short *bron, char addfac_help) */
496
497 /* ------------------------------------------------------------------------- */
498
499 void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac)
500   /* doel= bron over doel  */
501 {
502     float m; /* weiging factor of destination */
503     float c; /* intermediate colour           */
504
505     /* 1. copy bron straight away if doel has zero alpha */
506     if( doel[3] == 0) {
507         *((unsigned int *)doel)     = *((unsigned int *)bron);
508         *((unsigned int *)(doel+2)) = *((unsigned int *)(bron+2));
509         return;
510     }
511     
512     /* Addfac is a number between 0 and 1: rescale */
513     /* final target is to diminish the influence of dest when addfac rises */
514     m = 1.0 - ( bron[3] * ((255.0 - addfac) / 255.0));
515
516     /* blend colours*/
517     c = (m * doel[0]) + bron[0];
518     if( c > 65535.0 ) doel[0]=65535; 
519     else doel[0] = floor(c);
520     c = (m * doel[1]) + bron[1];
521     if( c > 65535.0 ) doel[1]=65535; 
522     else doel[1] = floor(c);
523     c = (m * doel[2]) + bron[2];
524     if( c > 65535.0 ) doel[2]=65535; 
525     else doel[2] = floor(c);
526
527     c = doel[3] + bron[3];
528     if(c > 65535.0) doel[3] = 65535; 
529     else doel[3]=  floor(c);
530
531 } /* end of void addalphaAddfacShort(unsigned short *doel, unsigned short *bron, char addfac_help) */
532
533 /* ------------------------------------------------------------------------- */
534
535 void addHaloToHaloShort(unsigned short *d, unsigned short *s)
536 {
537     /*  float m; */ /* weiging factor of destination */
538     float c[4]; /* intermediate colour           */
539     float rescale = 1.0;
540
541     /* 1. copy <s> straight away if <d> has zero alpha */
542     if( d[3] == 0) {
543         *((unsigned int *) d)      = *((unsigned int *) s);
544         *((unsigned int *)(d + 2)) = *((unsigned int *)(s + 2));
545         return;
546     }
547
548     /* 2. halo blending  */
549     /* no blending, just add */
550     c[0] = s[0] + d[0];
551     c[1] = s[1] + d[1];
552     c[2] = s[2] + d[2];
553     c[3] = s[3] + d[3];
554     /* One thing that may happen is that this pixel is over-saturated with light - */
555     /* i.e. too much light comes out, and the pixel is clipped. Currently, this    */
556     /* leads to artifacts such as overproportional undersampling of background     */
557     /* colours.                                                                    */
558     /* Compensating for over-saturation:                                           */
559     /* - increase alpha                                                            */
560     /* - increase alpha and rescale colours                                        */
561
562     /* let's try alpha increase and clipping */
563
564     /* calculate how much rescaling we need */
565     if( c[0] > 65535.0 ) { 
566       rescale *= c[0] /65535.0;
567       d[0] = 65535; 
568     } else d[0] = floor(c[0]);
569     if( c[1] > 65535.0 ) { 
570       rescale *= c[1] /65535.0;
571       d[1] = 65535; 
572     } else d[1] = floor(c[1]);
573     if( c[2] > 65535.0 ) { 
574       rescale *= c[2] /65535.0;
575       d[2] = 65535; 
576     } else d[2] = floor(c[2]);
577
578     /* a bit too hefty I think */
579     c[3] *= rescale;
580
581     if( c[3] > 65535.0 ) d[3] = 65535; else d[3]=  floor(c[3]);
582
583 } /* end of void addHaloToHaloShort(unsigned short *dest, unsigned short *source, char addfac) */
584
585 /* ------------------------------------------------------------------------- */
586
587 void sampleShortColV2ShortColV(unsigned short *sample, unsigned short *dest, int osaNr)
588 {
589     unsigned int intcol[4] = {0};
590     unsigned short *scol = sample; 
591     int a = 0;
592     
593     for(a=0; a < osaNr; a++, scol+=4) {
594         intcol[0]+= scol[0]; intcol[1]+= scol[1];
595         intcol[2]+= scol[2]; intcol[3]+= scol[3];
596     }
597     
598     /* Now normalise the integrated colour. It is guaranteed */
599     /* to be correctly bounded.                              */
600     dest[0]= intcol[0]/osaNr;
601     dest[1]= intcol[1]/osaNr;
602     dest[2]= intcol[2]/osaNr;
603     dest[3]= intcol[3]/osaNr;
604     
605 } /* end of void sampleShortColVToShortColV(unsigned short *sample, unsigned short *dest) */
606
607
608 /* ------------------------------------------------------------------------- */
609
610 void sampleFloatColV2FloatColV(float *sample, float *dest, int osaNr)
611 {
612     float intcol[4] = {0};
613     float *scol = sample; 
614     int   a = 0;
615
616         if (doGamma()) {
617                 /* use a LUT and interpolation to do the gamma correction */
618                 for(a=0; a < osaNr; a++, scol+=4) {
619                         intcol[0] += gammaCorrect(scol[0]); 
620                         intcol[1] += gammaCorrect(scol[1]); 
621                         intcol[2] += gammaCorrect(scol[2]); 
622                         intcol[3] += scol[3];
623                 }
624
625                 /* renormalise */
626                 intcol[0] /= osaNr;
627                 intcol[1] /= osaNr;
628                 intcol[2] /= osaNr;
629                 intcol[3] /= osaNr;
630
631         /* back to pixel values */
632                 dest[0] = invGammaCorrect(intcol[0]);
633                 dest[1] = invGammaCorrect(intcol[1]);
634                 dest[2] = invGammaCorrect(intcol[2]);
635                 dest[3] = intcol[3];
636         } else {
637                 /* no gamma */
638                 for(a=0; a < osaNr; a++, scol+=4) {
639                         intcol[0] += scol[0]; intcol[1] += scol[1];
640                         intcol[2] += scol[2]; intcol[3] += scol[3];
641                 }
642     
643                 dest[0]= intcol[0]/osaNr;
644                 dest[1]= intcol[1]/osaNr;
645                 dest[2]= intcol[2]/osaNr;
646                 dest[3]= intcol[3]/osaNr;
647         }
648         
649 } /* end void sampleFloatColVToFloatColV(unsigned short *, unsigned short *) */
650
651 /* ------------------------------------------------------------------------- */
652 /* The following functions are 'old' blending functions:                     */
653
654 /* ------------------------------------------------------------------------- */
655 void keyalpha(char *doel)   /* maakt premul 255 */
656 {
657         int c;
658         short div;
659         div= doel[3];
660         if (!div)
661         {
662                 doel[0] = (doel[0] ? 255 : 0);
663                 doel[1] = (doel[1] ? 255 : 0);
664                 doel[2] = (doel[2] ? 255 : 0);
665         } else
666         {
667                 c= (doel[0]<<8)/div;
668                 if(c>255) doel[0]=255; 
669                 else doel[0]= c;
670                 c= (doel[1]<<8)/div;
671                 if(c>255) doel[1]=255; 
672                 else doel[1]= c;
673                 c= (doel[2]<<8)/div;
674                 if(c>255) doel[2]=255; 
675                 else doel[2]= c;
676         }
677 }
678
679 /* ------------------------------------------------------------------------- */
680 /* vult bron onder doel in met alpha van doel*/
681 void addalphaUnder(char *doel, char *bron)   
682 {
683         int c;
684         int mul;
685
686         if(doel[3]==255) return;
687         if( doel[3]==0) {       /* is getest, scheelt  */
688                 *((unsigned int *)doel)= *((unsigned int *)bron);
689                 return;
690         }
691
692         mul= 255-doel[3];
693
694         c= doel[0]+ ((mul*bron[0])/255);
695         if(c>255) doel[0]=255; 
696         else doel[0]= c;
697         c= doel[1]+ ((mul*bron[1])/255);
698         if(c>255) doel[1]=255; 
699         else doel[1]= c;
700         c= doel[2]+ ((mul*bron[2])/255);
701         if(c>255) doel[2]=255; 
702         else doel[2]= c;
703         
704         c= doel[3]+ ((mul*bron[3])/255);
705         if(c>255) doel[3]=255; 
706         else doel[3]= c;
707         
708         /* doel[0]= MAX2(doel[0], bron[0]); */
709 }
710
711 /* ------------------------------------------------------------------------- */
712 /* gamma-gecorr: vult bron onder doel in met alpha van doel */
713 void addalphaUnderGamma(char *doel, char *bron)
714 {
715         unsigned int tot;
716         int c, doe, bro;
717         int mul;
718
719         /* hier doel[3]==0 of doel==255 afvangen gebeurt al in skylus */
720         mul= 256-doel[3];
721         
722         doe= igamtab1[(int)doel[0]];
723         bro= igamtab1[(int)bron[0]];
724         tot= (doe+ ((mul*bro)>>8));
725         if(tot>65535) tot=65535;
726         doel[0]= *((gamtab+tot)) >>8;
727         
728         doe= igamtab1[(int)doel[1]];
729         bro= igamtab1[(int)bron[1]];
730         tot= (doe+ ((mul*bro)>>8));
731         if(tot>65535) tot=65535;
732         doel[1]= *((gamtab+tot)) >>8;
733
734         doe= igamtab1[(int)doel[2]];
735         bro= igamtab1[(int)bron[2]];
736         tot= (doe+ ((mul*bro)>>8));
737         if(tot>65535) tot=65535;
738         doel[2]= *((gamtab+tot)) >>8;
739
740         c= doel[3]+ ((mul*bron[3])/255);
741         if(c>255) doel[3]=255; 
742         else doel[3]= c;
743         /* doel[0]= MAX2(doel[0], bron[0]); */
744 }
745
746 /* ------------------------------------------------------------------------- */
747 /* doel= bron over doel  */
748 void addalphaOver(char *doel, char *bron)   
749 {
750         int c;
751         int mul;
752
753         if(bron[3]==0) return;
754         if( bron[3]==255) {     /* is getest, scheelt  */
755                 *((unsigned int *)doel)= *((unsigned int *)bron);
756                 return;
757         }
758
759         mul= 255-bron[3];
760
761         c= ((mul*doel[0])/255)+bron[0];
762         if(c>255) doel[0]=255; 
763         else doel[0]= c;
764         c= ((mul*doel[1])/255)+bron[1];
765         if(c>255) doel[1]=255; 
766         else doel[1]= c;
767         c= ((mul*doel[2])/255)+bron[2];
768         if(c>255) doel[2]=255; 
769         else doel[2]= c;
770         c= ((mul*doel[3])/255)+bron[3];
771         if(c>255) doel[3]=255; 
772         else doel[3]= c;
773 }
774
775 /* ------------------------------------------------------------------------- */
776 void addalphaAdd(char *doel, char *bron)   /* telt bron bij doel */
777 {
778         int c;
779
780         if( doel[3]==0 || bron[3]==255) {       /* is getest, scheelt veel */
781                 *((unsigned int *)doel)= *((unsigned int *)bron);
782                 return;
783         }
784         c= doel[0]+bron[0];
785         if(c>255) doel[0]=255; 
786         else doel[0]= c;
787         c= doel[1]+bron[1];
788         if(c>255) doel[1]=255; 
789         else doel[1]= c;
790         c= doel[2]+bron[2];
791         if(c>255) doel[2]=255; 
792         else doel[2]= c;
793         c= doel[3]+bron[3];
794         if(c>255) doel[3]=255; 
795         else doel[3]= c;
796 }
797 /* ------------------------------------------------------------------------- */
798 void addalphaAddshort(unsigned short *doel, unsigned short *bron)   /* telt bron bij doel */
799 {
800         int c;
801
802         if( doel[3]==0) {
803                 *((unsigned int *)doel)= *((unsigned int *)bron);
804                 *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
805                 return;
806         }
807         c= doel[0]+bron[0];
808         if(c>65535) doel[0]=65535; 
809         else doel[0]= c;
810         c= doel[1]+bron[1];
811         if(c>65535) doel[1]=65535; 
812         else doel[1]= c;
813         c= doel[2]+bron[2];
814         if(c>65535) doel[2]=65535; 
815         else doel[2]= c;
816         c= doel[3]+bron[3];
817         if(c>65535) doel[3]=65535; 
818         else doel[3]= c;
819 }
820
821 /* ------------------------------------------------------------------------- */
822 void addalphaAddFloat(float *dest, float *source)
823 {
824
825         /* Makes me wonder whether this is required... */
826         if( dest[3] < RE_EMPTY_COLOUR_FLOAT) {
827                 dest[0] = source[0];
828                 dest[1] = source[1];
829                 dest[2] = source[2];
830                 dest[3] = source[3];
831                 return;
832         }
833
834         /* no clipping! */
835         dest[0] = dest[0]+source[0];
836         dest[1] = dest[1]+source[1];
837         dest[2] = dest[2]+source[2];
838         dest[3] = dest[3]+source[3];
839
840 }
841
842 /* ALPHADDFAC: 
843  * 
844  *  Z= X alphaover Y:
845  *  Zrgb= (1-Xa)*Yrgb + Xrgb
846  * 
847  *      Om ook de add te doen moet (1-Xa) moduleren met 1 via fac
848  *  (1-fac)*(1-Xa) + fac <=>
849  *  1-Xa-fac+fac*Xa+fac <=> 
850  *  Xa*(fac-1)+1
851  */
852
853
854 /* ------------------------------------------------------------------------- */
855 /* doel= bron over doel  */
856 void RE_addalphaAddfac(char *doel, char *bron, char addfac)
857 {
858         
859         int c, mul;
860
861         if( doel[3]==0) {
862                 *((unsigned int *)doel)= *((unsigned int *)bron);
863                 return;
864         }
865
866         mul= 255 - (bron[3]*(255-addfac))/255;
867
868         c= ((mul*doel[0])/255)+bron[0];
869         if(c>255) doel[0]=255; 
870         else doel[0]= c;
871         c= ((mul*doel[1])/255)+bron[1];
872         if(c>255) doel[1]=255; 
873         else doel[1]= c;
874         c= ((mul*doel[2])/255)+bron[2];
875         if(c>255) doel[2]=255; 
876         else doel[2]= c;
877         
878         /* c= ((mul*doel[3])/255)+bron[3]; */
879         c= doel[3]+bron[3];
880         if(c>255) doel[3]=255; 
881         else doel[3]= c;
882 }
883
884 /* ------------------------------------------------------------------------- */
885 /* doel= bron over doel  */
886 void addalphaAddfacshort(unsigned short *doel,
887                                                  unsigned short *bron,
888                                                  short addfac)    
889 {
890         int c, mul;
891
892         if( doel[3]==0) {
893                 *((unsigned int *)doel)= *((unsigned int *)bron);
894                 *((unsigned int *)(doel+2))= *((unsigned int *)(bron+2));
895                 return;
896         }
897
898         mul= 0xFFFF - (bron[0]*(255-addfac))/255;
899         
900         c= ((mul*doel[0])>>16)+bron[0];
901         if(c>=0xFFF0) doel[0]=0xFFF0; 
902         else doel[0]= c;
903         c= ((mul*doel[1])>>16)+bron[1];
904         if(c>=0xFFF0) doel[1]=0xFFF0; 
905         else doel[1]= c;
906         c= ((mul*doel[2])>>16)+bron[2];
907         if(c>=0xFFF0) doel[2]=0xFFF0; 
908         else doel[2]= c;
909         c= ((mul*doel[3])>>16)+bron[3];
910         if(c>=0xFFF0) doel[3]=0xFFF0; 
911         else doel[3]= c;
912
913 }
914
915 /* ------------------------------------------------------------------------- */
916
917 /* eof pixelblending.c */
918
919