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