Blender V2.61 - r43446

node_composite_chromaMatte.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version. 
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include "node_composite_util.h"
00034 
00035 /* ******************* Chroma Key ********************************************************** */
00036 static bNodeSocketTemplate cmp_node_chroma_in[]={
00037     {SOCK_RGBA,1,"Image", 1.0f, 1.0f, 1.0f, 1.0f},
00038     {SOCK_RGBA,1,"Key Color", 1.0f, 1.0f, 1.0f, 1.0f},
00039     {-1,0,""}
00040 };
00041 
00042 static bNodeSocketTemplate cmp_node_chroma_out[]={
00043     {SOCK_RGBA,0,"Image"},
00044     {SOCK_FLOAT,0,"Matte"},
00045     {-1,0,""}
00046 };
00047 
00048 static void do_rgba_to_ycca_normalized(bNode *UNUSED(node), float *out, float *in)
00049 {
00050     rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
00051 
00052     //normalize to 0..1.0
00053     out[0]=out[0]/255.0f;
00054     out[1]=out[1]/255.0f;
00055     out[2]=out[2]/255.0f;
00056 
00057     //rescale to -1.0..1.0
00058     out[0]=(out[0]*2.0f)-1.0f;
00059     out[1]=(out[1]*2.0f)-1.0f;
00060     out[2]=(out[2]*2.0f)-1.0f;
00061 
00062 //  out[0]=((out[0])-16)/255.0;
00063 //  out[1]=((out[1])-128)/255.0;
00064 //  out[2]=((out[2])-128)/255.0;
00065     out[3]=in[3];
00066 }
00067 
00068 static void do_ycca_to_rgba_normalized(bNode *UNUSED(node), float *out, float *in)
00069 {
00070     /*un-normalize the normalize from above */
00071     in[0]=(in[0]+1.0f)/2.0f;
00072     in[1]=(in[1]+1.0f)/2.0f;
00073     in[2]=(in[2]+1.0f)/2.0f;
00074 
00075     in[0]=(in[0]*255.0f);
00076     in[1]=(in[1]*255.0f);
00077     in[2]=(in[2]*255.0f);
00078 
00079     //  in[0]=(in[0]*255.0)+16;
00080 //  in[1]=(in[1]*255.0)+128;
00081 //  in[2]=(in[2]*255.0)+128;
00082     ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
00083     out[3]=in[3];
00084 }
00085 
00086 static void do_chroma_key(bNode *node, float *out, float *in)
00087 {
00088     NodeChroma *c;
00089     float x, z, alpha;
00090     float theta, beta, angle, angle2;
00091     float kfg;
00092 
00093     c=node->storage;
00094 
00095     /* Algorithm from book "Video Demistified," does not include the spill reduction part */
00096 
00097     /* find theta, the angle that the color space should be rotated based on key*/
00098     theta=atan2(c->key[2], c->key[1]);
00099 
00100     /*rotate the cb and cr into x/z space */
00101     x=in[1]*cosf(theta)+in[2]*sinf(theta);
00102     z=in[2]*cosf(theta)-in[1]*sinf(theta);
00103 
00104     /*if within the acceptance angle */
00105     angle=c->t1; /* t1 is radians. */
00106 
00107     /* if kfg is <0 then the pixel is outside of the key color */
00108     kfg= x-(fabsf(z)/tanf(angle/2.0f));
00109 
00110     out[0]=in[0];
00111     out[1]=in[1];
00112     out[2]=in[2];
00113 
00114     if(kfg>0.0f) {  /* found a pixel that is within key color */
00115         alpha=(1.0f-kfg)*(c->fstrength);
00116 
00117         beta=atan2(z,x);
00118         angle2=c->t2; /* t2 is radians. */
00119 
00120         /* if beta is within the cutoff angle */
00121         if(fabsf(beta) < (angle2/2.0f)) {
00122             alpha=0.0;
00123         }
00124 
00125         /* don't make something that was more transparent less transparent */
00126         if (alpha<in[3]) {
00127             out[3]=alpha;
00128         }
00129         else {
00130             out[3]=in[3];
00131         }
00132     }
00133     else { /*pixel is outside key color */
00134         out[0]=in[0];
00135         out[1]=in[1];
00136         out[2]=in[2];
00137         out[3]=in[3]; /* make pixel just as transparent as it was before */
00138     }
00139 }
00140 
00141 static void node_composit_exec_chroma_matte(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
00142 {
00143     CompBuf *cbuf;
00144     CompBuf *chromabuf;
00145     NodeChroma *c;
00146     
00147     if(in[0]->hasinput==0) return;
00148     if(in[0]->data==NULL) return;
00149     if(out[0]->hasoutput==0 && out[1]->hasoutput==0) return;
00150     
00151     cbuf= typecheck_compbuf(in[0]->data, CB_RGBA);
00152     
00153     chromabuf= dupalloc_compbuf(cbuf);
00154     
00155     c=node->storage;
00156     
00157     /*convert rgbbuf to normalized chroma space*/
00158     composit1_pixel_processor(node, chromabuf, cbuf, in[0]->vec, do_rgba_to_ycca_normalized, CB_RGBA);
00159     /*convert key to normalized chroma color space */
00160     do_rgba_to_ycca_normalized(node, c->key, in[1]->vec);
00161     
00162     /*per pixel chroma key*/
00163     composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_chroma_key, CB_RGBA);
00164     
00165     /*convert back*/
00166     composit1_pixel_processor(node, chromabuf, chromabuf, in[0]->vec, do_ycca_to_rgba_normalized, CB_RGBA);
00167     
00168     out[0]->data= chromabuf;
00169     if(out[1]->hasoutput)
00170         out[1]->data= valbuf_from_rgbabuf(chromabuf, CHAN_A);
00171     
00172     generate_preview(data, node, chromabuf);
00173 
00174     if(cbuf!=in[0]->data)
00175         free_compbuf(cbuf);
00176 }
00177 
00178 
00179 static void node_composit_init_chroma_matte(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
00180 {
00181     NodeChroma *c= MEM_callocN(sizeof(NodeChroma), "node chroma");
00182     node->storage= c;
00183     c->t1= DEG2RADF(30.0f);
00184     c->t2= DEG2RADF(10.0f);
00185     c->t3= 0.0f;
00186     c->fsize= 0.0f;
00187     c->fstrength= 1.0f;
00188 }
00189 
00190 void register_node_type_cmp_chroma_matte(bNodeTreeType *ttype)
00191 {
00192     static bNodeType ntype;
00193 
00194     node_type_base(ttype, &ntype, CMP_NODE_CHROMA_MATTE, "Chroma Key", NODE_CLASS_MATTE, NODE_PREVIEW|NODE_OPTIONS);
00195     node_type_socket_templates(&ntype, cmp_node_chroma_in, cmp_node_chroma_out);
00196     node_type_size(&ntype, 200, 80, 300);
00197     node_type_init(&ntype, node_composit_init_chroma_matte);
00198     node_type_storage(&ntype, "NodeChroma", node_free_standard_storage, node_copy_standard_storage);
00199     node_type_exec(&ntype, node_composit_exec_chroma_matte);
00200 
00201     nodeRegisterType(ttype, &ntype);
00202 }