Blender V2.61 - r43446

pixelblending.c

Go to the documentation of this file.
00001 /*
00002  * pixelblending.c
00003  *
00004  * Functions to blend pixels with or without alpha, in various formats
00005  * nzc - June 2000
00006  *
00007  *
00008  * ***** BEGIN GPL LICENSE BLOCK *****
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU General Public License
00012  * as published by the Free Software Foundation; either version 2
00013  * of the License, or (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00025  * All rights reserved.
00026  *
00027  * Contributor(s): Full recode, 2004-2006 Blender Foundation
00028  *
00029  * ***** END GPL LICENSE BLOCK *****
00030  */
00031 
00037 #include <math.h>
00038 #include <string.h>
00039 
00040 /* global includes */
00041 #include "BLI_math.h"
00042 #include "BLI_rand.h"
00043 
00044 /* own includes */
00045 #include "render_types.h"
00046 #include "renderpipeline.h"
00047 #include "pixelblending.h"
00048 #include "gammaCorrectionTables.h"
00049 
00050 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00051 /* defined in pipeline.c, is hardcopy of active dynamic allocated Render */
00052 /* only to be used here in this file, it's for speed */
00053 extern struct Render R;
00054 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
00055 
00056 
00057 /* ------------------------------------------------------------------------- */
00058 /* Debug/behaviour defines                                                   */
00059 /* if defined: alpha blending with floats clips color, as with shorts       */
00060 /* #define RE_FLOAT_COLOR_CLIPPING  */
00061 /* if defined: alpha values are clipped                                      */
00062 /* For now, we just keep alpha clipping. We run into thresholding and        */
00063 /* blending difficulties otherwise. Be careful here.                         */
00064 #define RE_ALPHA_CLIPPING
00065 
00066 
00067 
00068 /* Threshold for a 'full' pixel: pixels with alpha above this level are      */
00069 /* considered opaque This is the decimal value for 0xFFF0 / 0xFFFF           */
00070 #define RE_FULL_COLOR_FLOAT 0.9998f
00071 /* Threshold for an 'empty' pixel: pixels with alpha above this level are    */
00072 /* considered completely transparent. This is the decimal value              */
00073 /* for 0x000F / 0xFFFF                                                       */
00074 #define RE_EMPTY_COLOR_FLOAT 0.0002f
00075 
00076 
00077 /* ------------------------------------------------------------------------- */
00078 
00079 void addAlphaOverFloat(float *dest, float *source)
00080 {
00081     /* d = s + (1-alpha_s)d*/
00082     float mul;
00083 
00084     mul= 1.0f - source[3];
00085 
00086     dest[0]= (mul*dest[0]) + source[0];
00087     dest[1]= (mul*dest[1]) + source[1];
00088     dest[2]= (mul*dest[2]) + source[2];
00089     dest[3]= (mul*dest[3]) + source[3];
00090 
00091 }
00092 
00093 
00094 /* ------------------------------------------------------------------------- */
00095 
00096 void addAlphaUnderFloat(float *dest, float *source)
00097 {
00098     float mul;
00099 
00100     mul= 1.0f - dest[3];
00101 
00102     dest[0]+= (mul*source[0]);
00103     dest[1]+= (mul*source[1]);
00104     dest[2]+= (mul*source[2]);
00105     dest[3]+= (mul*source[3]);
00106 } 
00107 
00108 
00109 /* ------------------------------------------------------------------------- */
00110 void addalphaAddfacFloat(float *dest, float *source, char addfac)
00111 {
00112     float m; /* weiging factor of destination */
00113     float c; /* intermediate color           */
00114 
00115     /* Addfac is a number between 0 and 1: rescale */
00116     /* final target is to diminish the influence of dest when addfac rises */
00117     m = 1.0f - ( source[3] * ((255 - addfac) / 255.0f));
00118 
00119     /* blend colors*/
00120     c= (m * dest[0]) + source[0];
00121 #ifdef RE_FLOAT_COLOR_CLIPPING
00122     if(c >= RE_FULL_COLOR_FLOAT) dest[0] = RE_FULL_COLOR_FLOAT; 
00123     else 
00124 #endif
00125         dest[0]= c;
00126    
00127     c= (m * dest[1]) + source[1];
00128 #ifdef RE_FLOAT_COLOR_CLIPPING
00129     if(c >= RE_FULL_COLOR_FLOAT) dest[1] = RE_FULL_COLOR_FLOAT; 
00130     else 
00131 #endif
00132         dest[1]= c;
00133 
00134     c= (m * dest[2]) + source[2];
00135 #ifdef RE_FLOAT_COLOR_CLIPPING
00136     if(c >= RE_FULL_COLOR_FLOAT) dest[2] = RE_FULL_COLOR_FLOAT; 
00137     else 
00138 #endif
00139         dest[2]= c;
00140 
00141     c= (m * dest[3]) + source[3];
00142 #ifdef RE_ALPHA_CLIPPING
00143     if(c >= RE_FULL_COLOR_FLOAT) dest[3] = RE_FULL_COLOR_FLOAT; 
00144     else 
00145 #endif
00146     dest[3]= c;
00147 
00148 }
00149 
00150 
00151 /* ------------------------------------------------------------------------- */
00152 
00153 /* filtered adding to scanlines */
00154 void add_filt_fmask(unsigned int mask, float *col, float *rowbuf, int row_w)
00155 {
00156     /* calc the value of mask */
00157     float **fmask1= R.samples->fmask1, **fmask2=R.samples->fmask2;
00158     float *rb1, *rb2, *rb3;
00159     float val, r, g, b, al;
00160     unsigned int a, maskand, maskshift;
00161     int j;
00162     
00163     r= col[0];
00164     g= col[1];
00165     b= col[2];
00166     al= col[3];
00167     
00168     rb2= rowbuf-4;
00169     rb3= rb2-4*row_w;
00170     rb1= rb2+4*row_w;
00171     
00172     maskand= (mask & 255);
00173     maskshift= (mask >>8);
00174     
00175     for(j=2; j>=0; j--) {
00176         
00177         a= j;
00178         
00179         val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00180         if(val!=0.0f) {
00181             rb1[0]+= val*r;
00182             rb1[1]+= val*g;
00183             rb1[2]+= val*b;
00184             rb1[3]+= val*al;
00185         }
00186         a+=3;
00187         
00188         val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00189         if(val!=0.0f) {
00190             rb2[0]+= val*r;
00191             rb2[1]+= val*g;
00192             rb2[2]+= val*b;
00193             rb2[3]+= val*al;
00194         }
00195         a+=3;
00196         
00197         val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00198         if(val!=0.0f) {
00199             rb3[0]+= val*r;
00200             rb3[1]+= val*g;
00201             rb3[2]+= val*b;
00202             rb3[3]+= val*al;
00203         }
00204         
00205         rb1+= 4;
00206         rb2+= 4;
00207         rb3+= 4;
00208     }
00209 }
00210 
00211 
00212 void mask_array(unsigned int mask, float filt[][3])
00213 {
00214     float **fmask1= R.samples->fmask1, **fmask2=R.samples->fmask2;
00215     unsigned int maskand= (mask & 255);
00216     unsigned int maskshift= (mask >>8);
00217     int a, j;
00218     
00219     for(j=2; j>=0; j--) {
00220         
00221         a= j;
00222         
00223         filt[2][2-j]= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00224 
00225         a+=3;
00226         
00227         filt[1][2-j]= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00228         
00229         a+=3;
00230         
00231         filt[0][2-j]= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00232     }
00233 }
00234 
00235 
00236 /* 
00237 
00238 index ordering, scanline based:
00239 
00240  ---    ---   ---  
00241 | 2,0 | 2,1 | 2,2 |
00242  ---    ---   ---  
00243 | 1,0 | 1,1 | 1,2 |
00244  ---    ---   ---  
00245 | 0,0 | 0,1 | 0,2 |
00246  ---    ---   ---  
00247 */
00248 
00249 void add_filt_fmask_coord(float filt[][3], float *col, float *rowbuf, int row_w, int col_h, int x, int y)
00250 {
00251     float *fpoin[3][3];
00252     float val, r, g, b, al, lfilt[3][3];
00253     
00254     r= col[0];
00255     g= col[1];
00256     b= col[2];
00257     al= col[3];
00258     
00259     memcpy(lfilt, filt, sizeof(lfilt));
00260     
00261     fpoin[0][1]= rowbuf-4*row_w;
00262     fpoin[1][1]= rowbuf;
00263     fpoin[2][1]= rowbuf+4*row_w;
00264     
00265     fpoin[0][0]= fpoin[0][1] - 4;
00266     fpoin[1][0]= fpoin[1][1] - 4;
00267     fpoin[2][0]= fpoin[2][1] - 4;
00268     
00269     fpoin[0][2]= fpoin[0][1] + 4;
00270     fpoin[1][2]= fpoin[1][1] + 4;
00271     fpoin[2][2]= fpoin[2][1] + 4;
00272     
00273     if(y==0) {
00274         fpoin[0][0]= fpoin[1][0];
00275         fpoin[0][1]= fpoin[1][1];
00276         fpoin[0][2]= fpoin[1][2];
00277         /* filter needs the opposite value yes! */
00278         lfilt[0][0]= filt[2][0];
00279         lfilt[0][1]= filt[2][1];
00280         lfilt[0][2]= filt[2][2];
00281     }
00282     else if(y==col_h-1) {
00283         fpoin[2][0]= fpoin[1][0];
00284         fpoin[2][1]= fpoin[1][1];
00285         fpoin[2][2]= fpoin[1][2];
00286         
00287         lfilt[2][0]= filt[0][0];
00288         lfilt[2][1]= filt[0][1];
00289         lfilt[2][2]= filt[0][2];
00290     }
00291     
00292     if(x==0) {
00293         fpoin[2][0]= fpoin[2][1];
00294         fpoin[1][0]= fpoin[1][1];
00295         fpoin[0][0]= fpoin[0][1];
00296         
00297         lfilt[2][0]= filt[2][2];
00298         lfilt[1][0]= filt[1][2];
00299         lfilt[0][0]= filt[0][2];
00300     }
00301     else if(x==row_w-1) {
00302         fpoin[2][2]= fpoin[2][1];
00303         fpoin[1][2]= fpoin[1][1];
00304         fpoin[0][2]= fpoin[0][1];
00305         
00306         lfilt[2][2]= filt[2][0];
00307         lfilt[1][2]= filt[1][0];
00308         lfilt[0][2]= filt[0][0];
00309     }
00310     
00311     
00312     /* loop unroll */
00313 #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; }
00314     
00315     MASKFILT(0, 0)
00316     MASKFILT(0, 1)
00317     MASKFILT(0, 2)
00318     MASKFILT(1, 0)
00319     MASKFILT(1, 1)
00320     MASKFILT(1, 2)
00321     MASKFILT(2, 0)
00322     MASKFILT(2, 1)
00323     MASKFILT(2, 2)
00324 }
00325 
00326 void add_filt_fmask_pixsize(unsigned int mask, float *in, float *rowbuf, int row_w, int pixsize)
00327 {
00328     /* calc the value of mask */
00329     float **fmask1= R.samples->fmask1, **fmask2=R.samples->fmask2;
00330     float *rb1, *rb2, *rb3;
00331     float val;
00332     unsigned int a, maskand, maskshift;
00333     int i, j;
00334     
00335     rb2= rowbuf-pixsize;
00336     rb3= rb2-pixsize*row_w;
00337     rb1= rb2+pixsize*row_w;
00338     
00339     maskand= (mask & 255);
00340     maskshift= (mask >>8);
00341     
00342     for(j=2; j>=0; j--) {
00343         
00344         a= j;
00345         
00346         val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00347         if(val!=0.0f) {
00348             for(i= 0; i<pixsize; i++)
00349                 rb1[i]+= val*in[i];
00350         }
00351         a+=3;
00352         
00353         val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00354         if(val!=0.0f) {
00355             for(i= 0; i<pixsize; i++)
00356                 rb2[i]+= val*in[i];
00357         }
00358         a+=3;
00359         
00360         val= *(fmask1[a] +maskand) + *(fmask2[a] +maskshift);
00361         if(val!=0.0f) {
00362             for(i= 0; i<pixsize; i++)
00363                 rb3[i]+= val*in[i];
00364         }
00365         
00366         rb1+= pixsize;
00367         rb2+= pixsize;
00368         rb3+= pixsize;
00369     }
00370 }
00371 
00372 /* ------------------------------------------------------------------------- */
00373 void addalphaAddFloat(float *dest, float *source)
00374 {
00375 
00376     /* Makes me wonder whether this is required... */
00377     if( dest[3] < RE_EMPTY_COLOR_FLOAT) {
00378         dest[0] = source[0];
00379         dest[1] = source[1];
00380         dest[2] = source[2];
00381         dest[3] = source[3];
00382         return;
00383     }
00384 
00385     /* no clipping! */
00386     dest[0] = dest[0]+source[0];
00387     dest[1] = dest[1]+source[1];
00388     dest[2] = dest[2]+source[2];
00389     dest[3] = dest[3]+source[3];
00390 
00391 }
00392 
00393 
00394 /* ---------------------------------------------------------------------------- */
00395 
00396 
00397 /* eof pixelblending.c */