Blender V2.61 - r43446
|
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 */