Blender  V2.59
CMP_colorSpill.c
Go to the documentation of this file.
00001 /*
00002  * $Id: CMP_colorSpill.c 36276 2011-04-21 15:53:30Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2006 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): Bob Holcomb, Xavier Thomas
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00036 #include "../CMP_util.h"
00037 
00038 #define avg(a,b) ((a+b)/2)
00039 
00040 /* ******************* Color Spill Supression ********************************* */
00041 static bNodeSocketType cmp_node_color_spill_in[]={
00042         {SOCK_RGBA,1,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
00043         {SOCK_VALUE, 1, "Fac",  1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
00044         {-1,0,""}
00045 };
00046 
00047 static bNodeSocketType cmp_node_color_spill_out[]={
00048         {SOCK_RGBA,0,"Image", 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
00049         {-1,0,""}
00050 };
00051 
00052 static void do_simple_spillmap_red(bNode *node, float* out, float *in)
00053 {
00054         NodeColorspill *ncs;
00055         ncs=node->storage;
00056         out[0]=in[0]-( ncs->limscale * in[ncs->limchan] );
00057 }
00058 
00059 static void do_simple_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
00060 {
00061         NodeColorspill *ncs;
00062         ncs=node->storage;
00063 
00064         out[0] = *fac * (in[0]-( ncs->limscale * in[ncs->limchan]));
00065 }
00066 
00067 static void do_simple_spillmap_green(bNode *node, float* out, float *in)
00068 {
00069         NodeColorspill *ncs;
00070         ncs=node->storage;
00071         out[0]=in[1]-( ncs->limscale * in[ncs->limchan] );
00072 }
00073 
00074 static void do_simple_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
00075 {
00076         NodeColorspill *ncs;
00077         ncs=node->storage;
00078 
00079         out[0] = *fac * (in[1]-( ncs->limscale * in[ncs->limchan]));
00080 }
00081 
00082 static void do_simple_spillmap_blue(bNode *node, float* out, float *in)
00083 {
00084         NodeColorspill *ncs;
00085         ncs=node->storage;
00086         out[0]=in[2]-( ncs->limscale * in[ncs->limchan] );
00087 }
00088 
00089 static void do_simple_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
00090 {
00091         NodeColorspill *ncs;
00092         ncs=node->storage;
00093 
00094         out[0] = *fac * (in[2]-( ncs->limscale * in[ncs->limchan]));
00095 }
00096 
00097 static void do_average_spillmap_red(bNode *node, float* out, float *in)
00098 {
00099         NodeColorspill *ncs;
00100         ncs=node->storage;
00101         out[0]=in[0]-(ncs->limscale * avg(in[1], in[2]) );
00102 }
00103 
00104 static void do_average_spillmap_red_fac(bNode *node, float* out, float *in, float *fac)
00105 {
00106         NodeColorspill *ncs;
00107         ncs=node->storage;
00108 
00109         out[0] = *fac * (in[0]-(ncs->limscale * avg(in[1], in[2]) ));
00110 }
00111 
00112 static void do_average_spillmap_green(bNode *node, float* out, float *in)
00113 {
00114         NodeColorspill *ncs;
00115         ncs=node->storage;
00116         out[0]=in[1]-(ncs->limscale * avg(in[0], in[2]) );
00117 }
00118 
00119 static void do_average_spillmap_green_fac(bNode *node, float* out, float *in, float *fac)
00120 {
00121         NodeColorspill *ncs;
00122         ncs=node->storage;
00123 
00124         out[0] = *fac * (in[0]-(ncs->limscale * avg(in[0], in[2]) ));
00125 }
00126 
00127 static void do_average_spillmap_blue(bNode *node, float* out, float *in)
00128 {
00129         NodeColorspill *ncs;
00130         ncs=node->storage;
00131         out[0]=in[2]-(ncs->limscale * avg(in[0], in[1]) );
00132 }
00133 
00134 static void do_average_spillmap_blue_fac(bNode *node, float* out, float *in, float *fac)
00135 {
00136         NodeColorspill *ncs;
00137         ncs=node->storage;
00138 
00139         out[0] = *fac * (in[0]-(ncs->limscale * avg(in[0], in[1]) ));
00140 }
00141 
00142 static void do_apply_spillmap_red(bNode *node, float* out, float *in, float *map)
00143 {       
00144         NodeColorspill *ncs;
00145         ncs=node->storage;
00146         if(map[0]>0) {
00147                 out[0]=in[0]-(ncs->uspillr*map[0]);
00148                 out[1]=in[1]+(ncs->uspillg*map[0]);
00149                 out[2]=in[2]+(ncs->uspillb*map[0]);
00150         }
00151         else {
00152                 out[0]=in[0];
00153                 out[1]=in[1];
00154                 out[2]=in[2];
00155         }
00156 }
00157 
00158 static void do_apply_spillmap_green(bNode *node, float* out, float *in, float *map)
00159 {
00160         NodeColorspill *ncs;
00161         ncs=node->storage;
00162         if(map[0]>0) {
00163                 out[0]=in[0]+(ncs->uspillr*map[0]);
00164                 out[1]=in[1]-(ncs->uspillg*map[0]);
00165                 out[2]=in[2]+(ncs->uspillb*map[0]);
00166    }
00167         else {
00168                 out[0]=in[0];
00169                 out[1]=in[1];
00170                 out[2]=in[2];
00171         }
00172 }
00173 
00174 static void do_apply_spillmap_blue(bNode *node, float* out, float *in, float *map)
00175 {
00176         NodeColorspill *ncs;
00177         ncs=node->storage;
00178         if(map[0]>0) {
00179                 out[0]=in[0]+(ncs->uspillr*map[0]);
00180                 out[1]=in[1]+(ncs->uspillg*map[0]);
00181                 out[2]=in[2]-(ncs->uspillb*map[0]);
00182    }
00183         else {
00184                 out[0]=in[0];
00185                 out[1]=in[1];
00186                 out[2]=in[2];
00187         }
00188 }
00189 
00190 static void node_composit_exec_color_spill(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
00191 {
00192         /* Originally based on the information from the book "The Art and Science of Digital Composition" and
00193          * discussions from vfxtalk.com .*/
00194         CompBuf *cbuf;
00195         CompBuf *mask;
00196         CompBuf *rgbbuf;
00197         CompBuf *spillmap;
00198         NodeColorspill *ncs;
00199         ncs=node->storage;
00200 
00201         /* early out for missing connections */
00202         if(out[0]->hasoutput==0 ) return;
00203         if(in[0]->hasinput==0) return;
00204         if(in[0]->data==NULL) return;
00205         
00206         cbuf=typecheck_compbuf(in[0]->data, CB_RGBA);
00207         mask=typecheck_compbuf(in[1]->data, CB_VAL);
00208         spillmap=alloc_compbuf(cbuf->x, cbuf->y, CB_VAL, 1);
00209         rgbbuf=dupalloc_compbuf(cbuf);
00210 
00211         switch(node->custom1)
00212         {
00213                 case 1:  /*red spill*/
00214                 {
00215                         switch(node->custom2)
00216                         {
00217                                 case 0: /* simple limit */
00218                                 {
00219                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
00220                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_red, CB_RGBA);
00221                                         } else {
00222                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_red_fac, CB_RGBA,  CB_VAL);
00223                                         }
00224                                         break;
00225                                 }
00226                                 case 1: /* average limit */
00227                                 {
00228                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
00229                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_red, CB_RGBA);
00230                                         } else {
00231                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_red_fac, CB_RGBA,  CB_VAL);
00232                                         }
00233                                         break;
00234                                 }
00235                         }
00236                         if(ncs->unspill==0) {
00237                                 ncs->uspillr=1.0f;
00238                                 ncs->uspillg=0.0f;
00239                                 ncs->uspillb=0.0f;
00240                         }
00241                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_red, CB_RGBA, CB_VAL);
00242                         break;
00243                 }
00244                 case 2: /*green spill*/
00245                 {
00246                         switch(node->custom2)
00247                         {
00248                                 case 0: /* simple limit */
00249                                 {
00250                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
00251                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_green, CB_RGBA);
00252                                         } else {
00253                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_green_fac, CB_RGBA,  CB_VAL);
00254                                         }
00255                                         break;
00256                                 }
00257                                 case 1: /* average limit */
00258                                 {
00259                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
00260                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_green, CB_RGBA);
00261                                         } else {
00262                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_green_fac, CB_RGBA,  CB_VAL);
00263                                         }
00264                                         break;
00265                                 }
00266                         }
00267                         if(ncs->unspill==0) {
00268                                 ncs->uspillr=0.0f;
00269                                 ncs->uspillg=1.0f;
00270                                 ncs->uspillb=0.0f;
00271                         }
00272                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_green, CB_RGBA, CB_VAL);
00273                         break;
00274                 }
00275                 case 3: /*blue spill*/
00276                 {
00277                         switch(node->custom2)
00278                         {
00279                                 case 0: /* simple limit */
00280                                 {
00281                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
00282                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_simple_spillmap_blue, CB_RGBA);
00283                                         } else {
00284                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_simple_spillmap_blue_fac, CB_RGBA,  CB_VAL);
00285                                         }
00286                                         break;
00287                                 }
00288                                 case 1: /* average limit */
00289                                 {
00290                                         if ((in[1]->data==NULL) && (in[1]->vec[0] >= 1.f)) {
00291                                                 composit1_pixel_processor(node, spillmap, cbuf, in[0]->vec, do_average_spillmap_blue, CB_RGBA);
00292                                         } else {
00293                                                 composit2_pixel_processor(node, spillmap, cbuf, in[0]->vec, in[1]->data, in[1]->vec, do_average_spillmap_blue_fac, CB_RGBA,  CB_VAL);
00294                                         }
00295                                         break;
00296                                 }
00297                         }
00298                         if(ncs->unspill==0) {
00299                                 ncs->uspillr=0.0f;
00300                                 ncs->uspillg=0.0f;
00301                                 ncs->uspillb=1.0f;
00302                         }
00303                         composit2_pixel_processor(node, rgbbuf, cbuf, in[0]->vec, spillmap, NULL, do_apply_spillmap_blue, CB_RGBA, CB_VAL);
00304                         break;
00305                 }
00306                 default:
00307                         break;
00308         }
00309 
00310         out[0]->data=rgbbuf;
00311 
00312         if(cbuf!=in[0]->data)
00313                 free_compbuf(cbuf);
00314 
00315         free_compbuf(spillmap);
00316 }
00317 
00318 static void node_composit_init_color_spill(bNode *node)
00319 {
00320         NodeColorspill *ncs= MEM_callocN(sizeof(NodeColorspill), "node colorspill");
00321         node->storage=ncs;
00322         node->custom1= 2; /* green channel */
00323         node->custom2= 0; /* simple limit algo*/
00324         ncs->limchan= 0;  /* limit by red */
00325         ncs->limscale= 1.0f; /* limit scaling factor */
00326         ncs->unspill=0;   /* do not use unspill */
00327 }
00328 
00329 void register_node_type_cmp_color_spill(ListBase *lb)
00330 {
00331         static bNodeType ntype;
00332         
00333         node_type_base(&ntype, CMP_NODE_COLOR_SPILL, "Color Spill", NODE_CLASS_MATTE, NODE_OPTIONS,
00334                                    cmp_node_color_spill_in, cmp_node_color_spill_out);
00335         node_type_size(&ntype, 140, 80, 200);
00336         node_type_init(&ntype, node_composit_init_color_spill);
00337         node_type_storage(&ntype, "NodeColorspill", node_free_standard_storage, node_copy_standard_storage);
00338         node_type_exec(&ntype, node_composit_exec_color_spill);
00339         
00340         nodeRegisterType(lb, &ntype);
00341 }